1 /* 2 * Copyright (c) 2006 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 */ 9 10 #pragma ident "%Z%%M% %I% %E% SMI" 11 12 #include <sm/gen.h> 13 SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.9 2006/08/24 21:26:13 ca Exp $") 14 15 #include <stdio.h> 16 #include <sm/sendmail.h> 17 #include <sm/assert.h> 18 #include <sm/heap.h> 19 #include <sm/string.h> 20 #include <sm/test.h> 21 22 extern bool SmTestVerbose; 23 24 25 void 26 show_diff(s1, s2) 27 const char *s1; 28 const char *s2; 29 { 30 int i; 31 32 for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++) 33 { 34 if (s1[i] != s2[i]) 35 { 36 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", 37 i, (unsigned char) s1[i], 38 (unsigned char) s2[i]); 39 return; 40 } 41 } 42 if (s1[i] != s2[i]) 43 { 44 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", 45 i, (unsigned char) s1[i], (unsigned char) s2[i]); 46 } 47 } 48 49 char *quote_unquote __P((char *, char *, int, int)); 50 51 char * 52 quote_unquote(in, out, outlen, exp) 53 char *in; 54 char *out; 55 int outlen; 56 int exp; 57 { 58 char *obp, *bp; 59 char line_back[1024]; 60 char line_in[1024]; 61 int cmp; 62 63 sm_strlcpy(line_in, in, sizeof(line_in)); 64 obp = quote_internal_chars(in, out, &outlen); 65 bp = str2prt(line_in); 66 dequote_internal_chars(obp, line_back, sizeof(line_back)); 67 cmp = strcmp(line_in, line_back); 68 SM_TEST(exp == cmp); 69 if (cmp != exp && !SmTestVerbose) 70 { 71 fprintf(stderr, "in: %s\n", bp); 72 bp = str2prt(line_back); 73 fprintf(stderr, "out:%s\n", bp); 74 fprintf(stderr, "cmp=%d\n", cmp); 75 show_diff(in, line_back); 76 } 77 if (SmTestVerbose) 78 { 79 fprintf(stderr, "%s -> ", bp); 80 bp = str2prt(obp); 81 fprintf(stderr, "%s\n", bp); 82 fprintf(stderr, "cmp=%d\n", cmp); 83 } 84 return obp; 85 } 86 87 struct sm_qic_S 88 { 89 char *qic_in; 90 char *qic_out; 91 int qic_exp; 92 }; 93 94 typedef struct sm_qic_S sm_qic_T; 95 96 97 int 98 main(argc, argv) 99 int argc; 100 char *argv[]; 101 { 102 char line_in[1024], line[256], line_out[32], *obp; 103 int i, los, cmp; 104 sm_qic_T inout[] = { 105 { "", "", 0 } 106 , { "abcdef", "abcdef", 0 } 107 , { "01234567890123456789", "01234567890123456789", 0 } 108 , { "01234567890123456789\001", "01234567890123456789\001", 109 0 } 110 , { "012345\2067890123456789", "012345\377\2067890123456789", 111 0 } 112 , { "\377", "\377\377", 0 } 113 , { "\240", "\240", 0 } 114 , { "\220", "\377\220", 0 } 115 , { "\240\220", "\240\377\220", 0 } 116 , { "\377\377", "\377\377\377\377", 0 } 117 , { "\377a\377b", "\377\377a\377\377b", 0 } 118 , { "\376a\377b", "\376a\377\377b", 0 } 119 , { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240", 120 "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240", 121 0 } 122 , { NULL, NULL, 0 } 123 }; 124 125 sm_test_begin(argc, argv, "test meta quoting"); 126 for (i = 0; i < sizeof(line_out); i++) 127 line_out[i] = '\0'; 128 for (i = 0; i < sizeof(line_in); i++) 129 line_in[i] = '\0'; 130 for (i = 0; i < sizeof(line_in) / 2; i++) 131 { 132 char ch; 133 134 ch = 0200 + i; 135 if ('\0' == ch) 136 ch = '0'; 137 line_in[i] = ch; 138 } 139 los = sizeof(line_out) / 2; 140 obp = quote_unquote(line_in, line_out, los, 0); 141 if (obp != line_out) 142 SM_FREE(obp); 143 144 for (i = 0; i < sizeof(line_in); i++) 145 line_in[i] = '\0'; 146 for (i = 0; i < sizeof(line_in) / 2; i++) 147 { 148 char ch; 149 150 ch = 0200 + i; 151 if ('\0' == ch) 152 ch = '0'; 153 line_in[i] = ch; 154 } 155 los = sizeof(line_in); 156 obp = quote_unquote(line_in, line_in, los, 0); 157 if (obp != line_in) 158 SM_FREE(obp); 159 160 for (i = 0; inout[i].qic_in != NULL; i++) 161 { 162 los = sizeof(line_out) / 2; 163 obp = quote_unquote(inout[i].qic_in, line_out, los, 164 inout[i].qic_exp); 165 cmp = strcmp(inout[i].qic_out, obp); 166 SM_TEST(inout[i].qic_exp == cmp); 167 if (inout[i].qic_exp != cmp && !SmTestVerbose) 168 { 169 char *bp; 170 171 bp = str2prt(obp); 172 fprintf(stderr, "got: %s\n", bp); 173 bp = str2prt(inout[i].qic_out); 174 fprintf(stderr, "exp:%s\n", bp); 175 fprintf(stderr, "cmp=%d\n", cmp); 176 show_diff(inout[i].qic_in, inout[i].qic_out); 177 } 178 if (obp != line_out) 179 SM_FREE(obp); 180 } 181 182 /* use same buffer for in and out */ 183 for (i = 0; inout[i].qic_in != NULL; i++) 184 { 185 bool same; 186 187 same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0; 188 los = sm_strlcpy(line, inout[i].qic_in, sizeof(line)); 189 SM_TEST(los + 1 < sizeof(line)); 190 ++los; 191 obp = quote_unquote(line, line, los, inout[i].qic_exp); 192 cmp = strcmp(inout[i].qic_out, obp); 193 SM_TEST(inout[i].qic_exp == cmp); 194 if (inout[i].qic_exp != cmp && !SmTestVerbose) 195 { 196 char *bp; 197 198 bp = str2prt(obp); 199 fprintf(stderr, "got: %s\n", bp); 200 bp = str2prt(inout[i].qic_out); 201 fprintf(stderr, "exp:%s\n", bp); 202 fprintf(stderr, "cmp=%d\n", cmp); 203 show_diff(inout[i].qic_in, inout[i].qic_out); 204 } 205 if (obp != line) 206 { 207 SM_TEST(!same); 208 if (same) 209 show_diff(obp, inout[i].qic_out); 210 SM_FREE(obp); 211 } 212 } 213 214 /* use NULL buffer for out */ 215 for (i = 0; inout[i].qic_in != NULL; i++) 216 { 217 los = 0; 218 obp = quote_unquote(inout[i].qic_in, NULL, los, 219 inout[i].qic_exp); 220 SM_TEST(obp != NULL); 221 cmp = strcmp(inout[i].qic_out, obp); 222 SM_TEST(inout[i].qic_exp == cmp); 223 if (inout[i].qic_exp != cmp && !SmTestVerbose) 224 { 225 char *bp; 226 227 bp = str2prt(obp); 228 fprintf(stderr, "got: %s\n", bp); 229 bp = str2prt(inout[i].qic_out); 230 fprintf(stderr, "exp:%s\n", bp); 231 fprintf(stderr, "cmp=%d\n", cmp); 232 show_diff(inout[i].qic_in, inout[i].qic_out); 233 } 234 } 235 236 return sm_test_end(); 237 } 238