1 /* $NetBSD: xtext.c,v 1.1.1.2 2014/07/06 19:27:52 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* xtext 3 6 /* SUMMARY 7 /* quote/unquote text, xtext style. 8 /* SYNOPSIS 9 /* #include <xtext.h> 10 /* 11 /* VSTRING *xtext_quote(quoted, unquoted, special) 12 /* VSTRING *quoted; 13 /* const char *unquoted; 14 /* const char *special; 15 /* 16 /* VSTRING *xtext_quote_append(unquoted, quoted, special) 17 /* VSTRING *unquoted; 18 /* const char *quoted; 19 /* const char *special; 20 /* 21 /* VSTRING *xtext_unquote(unquoted, quoted) 22 /* VSTRING *unquoted; 23 /* const char *quoted; 24 /* 25 /* VSTRING *xtext_unquote_append(unquoted, quoted) 26 /* VSTRING *unquoted; 27 /* const char *quoted; 28 /* DESCRIPTION 29 /* xtext_quote() takes a null-terminated string and replaces characters 30 /* +, <33(10) and >126(10), as well as characters specified with "special" 31 /* by +XX, XX being the two-digit uppercase hexadecimal equivalent. 32 /* 33 /* xtext_quote_append() is like xtext_quote(), but appends the conversion 34 /* result to the result buffer. 35 /* 36 /* xtext_unquote() performs the opposite transformation. This function 37 /* understands lowercase, uppercase, and mixed case +XX sequences. The 38 /* result value is the unquoted argument in case of success, a null pointer 39 /* otherwise. 40 /* 41 /* xtext_unquote_append() is like xtext_unquote(), but appends 42 /* the conversion result to the result buffer. 43 /* BUGS 44 /* This module cannot process null characters in data. 45 /* LICENSE 46 /* .ad 47 /* .fi 48 /* The Secure Mailer license must be distributed with this software. 49 /* AUTHOR(S) 50 /* Wietse Venema 51 /* IBM T.J. Watson Research 52 /* P.O. Box 704 53 /* Yorktown Heights, NY 10598, USA 54 /*--*/ 55 56 /* System library. */ 57 58 #include <sys_defs.h> 59 #include <string.h> 60 #include <ctype.h> 61 62 /* Utility library. */ 63 64 #include "msg.h" 65 #include "vstring.h" 66 #include "xtext.h" 67 68 /* Application-specific. */ 69 70 #define STR(x) vstring_str(x) 71 #define LEN(x) VSTRING_LEN(x) 72 73 /* xtext_quote_append - append unquoted data to quoted data */ 74 75 VSTRING *xtext_quote_append(VSTRING *quoted, const char *unquoted, 76 const char *special) 77 { 78 const char *cp; 79 int ch; 80 81 for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) { 82 if (ch != '+' && ch > 32 && ch < 127 83 && (*special == 0 || strchr(special, ch) == 0)) { 84 VSTRING_ADDCH(quoted, ch); 85 } else { 86 vstring_sprintf_append(quoted, "+%02X", ch); 87 } 88 } 89 VSTRING_TERMINATE(quoted); 90 return (quoted); 91 } 92 93 /* xtext_quote - unquoted data to quoted */ 94 95 VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special) 96 { 97 VSTRING_RESET(quoted); 98 xtext_quote_append(quoted, unquoted, special); 99 return (quoted); 100 } 101 102 /* xtext_unquote_append - quoted data to unquoted */ 103 104 VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted) 105 { 106 const char *cp; 107 int ch; 108 109 for (cp = quoted; (ch = *cp) != 0; cp++) { 110 if (ch == '+') { 111 if (ISDIGIT(cp[1])) 112 ch = (cp[1] - '0') << 4; 113 else if (cp[1] >= 'a' && cp[1] <= 'f') 114 ch = (cp[1] - 'a' + 10) << 4; 115 else if (cp[1] >= 'A' && cp[1] <= 'F') 116 ch = (cp[1] - 'A' + 10) << 4; 117 else 118 return (0); 119 if (ISDIGIT(cp[2])) 120 ch |= (cp[2] - '0'); 121 else if (cp[2] >= 'a' && cp[2] <= 'f') 122 ch |= (cp[2] - 'a' + 10); 123 else if (cp[2] >= 'A' && cp[2] <= 'F') 124 ch |= (cp[2] - 'A' + 10); 125 else 126 return (0); 127 cp += 2; 128 } 129 VSTRING_ADDCH(unquoted, ch); 130 } 131 VSTRING_TERMINATE(unquoted); 132 return (unquoted); 133 } 134 /* xtext_unquote - quoted data to unquoted */ 135 136 VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted) 137 { 138 VSTRING_RESET(unquoted); 139 xtext_unquote_append(unquoted, quoted); 140 return (unquoted); 141 } 142 143 #ifdef TEST 144 145 /* 146 * Proof-of-concept test program: convert to quoted and back. 147 */ 148 #include <vstream.h> 149 150 #define BUFLEN 1024 151 152 static ssize_t read_buf(VSTREAM *fp, VSTRING *buf) 153 { 154 ssize_t len; 155 156 VSTRING_RESET(buf); 157 len = vstream_fread(fp, STR(buf), vstring_avail(buf)); 158 VSTRING_AT_OFFSET(buf, len); /* XXX */ 159 VSTRING_TERMINATE(buf); 160 return (len); 161 } 162 163 int main(int unused_argc, char **unused_argv) 164 { 165 VSTRING *unquoted = vstring_alloc(BUFLEN); 166 VSTRING *quoted = vstring_alloc(100); 167 ssize_t len; 168 169 while ((len = read_buf(VSTREAM_IN, unquoted)) > 0) { 170 xtext_quote(quoted, STR(unquoted), "+="); 171 if (xtext_unquote(unquoted, STR(quoted)) == 0) 172 msg_fatal("bad input: %.100s", STR(quoted)); 173 if (LEN(unquoted) != len) 174 msg_fatal("len %ld != unquoted len %ld", 175 (long) len, (long) LEN(unquoted)); 176 if (vstream_fwrite(VSTREAM_OUT, STR(unquoted), LEN(unquoted)) != LEN(unquoted)) 177 msg_fatal("write error: %m"); 178 } 179 vstream_fflush(VSTREAM_OUT); 180 vstring_free(unquoted); 181 vstring_free(quoted); 182 return (0); 183 } 184 185 #endif 186