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