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