forked from erluko/socat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xio-ascii.c
158 lines (140 loc) · 4.6 KB
/
xio-ascii.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* source: xio-ascii.c */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains functions for text encoding, decoding, and conversions */
#include <stddef.h>
#include <ctype.h>
#include <stdio.h>
#include "xio-ascii.h"
/* for each 6 bit pattern we have an ASCII character in the arry */
const static int base64chars[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
} ;
#define CHAR64(c) (base64chars[c])
char *
xiob64encodeline(const char *data, /* input data */
size_t bytes, /* length of input data, >=0 */
char *coded /* output buffer, must be long enough */
) {
int c1, c2, c3;
while (bytes > 0) {
c1 = *data++;
*coded++ = CHAR64(c1>>2);
if (--bytes == 0) {
*coded++ = CHAR64((c1&0x03)<<4);
*coded++ = '=';
*coded++ = '=';
} else {
c2 = *data++;
*coded++ = CHAR64(((c1&0x03)<<4)|(c2>>4));
if (--bytes == 0) {
*coded++ = CHAR64((c2&0x0f)<<2);
*coded++ = '=';
} else {
c3 = *data++; --bytes;
*coded++ = CHAR64(((c2&0x0f)<<2)|(c3>>6));
*coded++ = CHAR64(c3&0x3f);
}
}
}
return coded;
}
/* sanitize "untrusted" text, replacing special control characters with the C
string version ("\x"), and replacing unprintable chars with ".".
text can grow to double size, so keep output buffer long enough!
returns a pointer to the first untouched byte of the output buffer.
*/
char *xiosanitize(const char *data, /* input data */
size_t bytes, /* length of input data, >=0 */
char *coded /* output buffer, must be long enough */
) {
int c;
while (bytes > 0) {
c = *(unsigned char *)data++;
switch (c) {
case '\0' : *coded++ = '\\'; *coded++ = '0'; break;
case '\a' : *coded++ = '\\'; *coded++ = 'a'; break;
case '\b' : *coded++ = '\\'; *coded++ = 'b'; break;
case '\t' : *coded++ = '\\'; *coded++ = 't'; break;
case '\n' : *coded++ = '\\'; *coded++ = 'n'; break;
case '\v' : *coded++ = '\\'; *coded++ = 'v'; break;
case '\f' : *coded++ = '\\'; *coded++ = 'f'; break;
case '\r' : *coded++ = '\\'; *coded++ = 'r'; break;
case '\'' : *coded++ = '\\'; *coded++ = '\''; break;
case '\"' : *coded++ = '\\'; *coded++ = '"'; break;
case '\\' : *coded++ = '\\'; *coded++ = '\\'; break;
default:
if (!isprint(c))
c = '.';
*coded++ = c;
break;
}
--bytes;
}
return coded;
}
/* print the bytes in hex */
char *
xiohexdump(const unsigned char *data, size_t bytes, char *coded) {
int space = 0;
while (bytes-- > 0) {
if (space) { *coded++ = ' '; }
coded += sprintf(coded, "%02x", *data++);
space = 1;
}
return coded;
}
/* write the binary data to output buffer codbuff in human readable form.
bytes gives the length of the data, codlen the available space in codbuff.
coding specifies how the data is to be presented. Not much to select now.
returns a pointer to the first char in codbuff that has not been overwritten;
it might also point to the first char after the buffer!
this function does not write a terminating \0
*/
static char *
_xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
int coding) {
int start = 1;
int space = coding & 0xff;
if (bytes <= 0) { return codbuff; }
if (codlen < 1) { return codbuff; }
if (space == 0) space = -1;
if (0) {
; /* for canonical reasons */
} else if (1) {
/* simple hexadecimal output */
if (3*bytes+1 > codlen) {
bytes = (codlen-1)/3; /* "truncate" data so generated text fits */
}
*codbuff++ = 'x';
while (bytes-- > 0) {
if (start == 0 && space == 0) {
*codbuff++ = ' ';
space = (coding & 0xff);
}
codbuff += sprintf(codbuff, "%02x", *data++);
start = 0;
}
}
return codbuff;
}
/* write the binary data to codbuff in human readable form.
bytes gives the length of the data, codlen the available space in codbuff.
coding specifies how the data is to be presented. Not much to select now.
null terminates the output. returns a pointer to the output string.
*/
char *
xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
int coding) {
char *result;
result = _xiodump(data, bytes, codbuff, codlen-1, coding);
*result = '\0';
return codbuff;
}