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