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