masqmail
diff src/parse.c @ 271:899175e8dff0
heavy refactoring in the small of parse.c
I really hope I didn't change any behavior.
This reminds me that we really need a test framework.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Fri, 03 Dec 2010 13:05:59 -0300 |
parents | a80ebfa16cd5 |
children | 00724782b6c9 |
line diff
1.1 --- a/src/parse.c Fri Dec 03 13:02:45 2010 -0300 1.2 +++ b/src/parse.c Fri Dec 03 13:05:59 2010 -0300 1.3 @@ -1,5 +1,6 @@ 1.4 /* MasqMail 1.5 Copyright (C) 1999-2001 Oliver Kurth 1.6 + Copyright (C) 2010 markus schnalke <meillo@marmaro.de> 1.7 1.8 This program is free software; you can redistribute it and/or modify 1.9 it under the terms of the GNU General Public License as published by 1.10 @@ -44,8 +45,9 @@ 1.11 p++; 1.12 while (*p && *p != ')') { 1.13 p++; 1.14 - if (*p == '(') 1.15 + if (*p == '(') { 1.16 p = skip_comment(p); 1.17 + } 1.18 } 1.19 p++; 1.20 1.21 @@ -59,21 +61,24 @@ 1.22 g_print("read_word: %s\n", p); 1.23 #endif 1.24 /* eat leading spaces */ 1.25 - while (*p && isspace(*p)) 1.26 + while (*p && isspace(*p)) { 1.27 p++; 1.28 + } 1.29 1.30 *b = p; 1.31 /* b = &p; */ 1.32 if (*p == '\"') { 1.33 /* quoted-string */ 1.34 p++; 1.35 - while (*p && (*p != '\"')) 1.36 + while (*p && (*p != '\"')) { 1.37 p++; 1.38 + } 1.39 p++; 1.40 } else { 1.41 /* atom */ 1.42 - while (*p && !strchr(specials, *p) && !iscntrl(*p) && !isspace(*p)) 1.43 + while (*p && !strchr(specials, *p) && !iscntrl(*p) && !isspace(*p)) { 1.44 p++; 1.45 + } 1.46 } 1.47 *e = p; 1.48 return TRUE; 1.49 @@ -88,11 +93,13 @@ 1.50 g_print("read_word_with_dots: %s\n", p); 1.51 #endif 1.52 while (TRUE) { 1.53 - if (!read_word(p, b, e)) 1.54 + if (!read_word(p, b, e)) { 1.55 return FALSE; 1.56 + } 1.57 p = *e; 1.58 - if (*p != '.') 1.59 + if (*p != '.') { 1.60 break; 1.61 + } 1.62 p++; 1.63 } 1.64 *b = b0; 1.65 @@ -108,12 +115,14 @@ 1.66 #endif 1.67 *b = p; 1.68 if (*p != '[') { 1.69 - while (isalnum(*p) || (*p == '-') || (*p == '.')) 1.70 + while (isalnum(*p) || (*p == '-') || (*p == '.')) { 1.71 p++; 1.72 + } 1.73 } else { 1.74 p++; 1.75 - while (isalpha(*p) || (*p == '.')) 1.76 + while (isalpha(*p) || (*p == '.')) { 1.77 p++; 1.78 + } 1.79 if (*p != ']') { 1.80 parse_error = g_strdup_printf("']' expected at end of literal address %s", *b); 1.81 return FALSE; 1.82 @@ -144,122 +153,130 @@ 1.83 1.84 /* leading spaces and angle brackets */ 1.85 while (*p && (isspace(*p) || (*p == '<'))) { 1.86 - if (*p == '<') 1.87 + if (*p == '<') { 1.88 angle_brackets++; 1.89 + } 1.90 p++; 1.91 } 1.92 1.93 - if (*p) { 1.94 - while (TRUE) { 1.95 - if (read_word_with_dots(p, &b, &e)) { 1.96 - p = e; 1.97 + if (!*p) { 1.98 + return FALSE; 1.99 + } 1.100 + 1.101 + while (TRUE) { 1.102 + if (!read_word_with_dots(p, &b, &e)) { 1.103 + return FALSE; 1.104 + } 1.105 + 1.106 + p = e; 1.107 #ifdef PARSE_TEST 1.108 - g_print("after read_word_with_dots: %s\n", p); 1.109 + g_print("after read_word_with_dots: %s\n", p); 1.110 #endif 1.111 - /* eat white spaces and comments */ 1.112 - while ((*p && (isspace(*p))) || (*p == '(')) { 1.113 - if (*p == '(') { 1.114 - if (!(p = skip_comment(p))) { 1.115 - parse_error = g_strdup("missing right bracket ')'"); 1.116 - return FALSE; 1.117 - } 1.118 - } else 1.119 - p++; 1.120 - } 1.121 - /* we now have a non-space char that is not 1.122 - the beginning of a comment */ 1.123 - 1.124 - if (*p == '@') { 1.125 - /* the last word was the local_part 1.126 - of an addr-spec */ 1.127 - *local_begin = b; 1.128 - *local_end = e; 1.129 -#ifdef PARSE_TEST 1.130 - g_print("found local part: %s\n", *local_begin); 1.131 -#endif 1.132 - if (*p == '@') { 1.133 - p++; /* skip @ */ 1.134 - /* now the domain */ 1.135 - if (read_domain(p, &b, &e)) { 1.136 - p = e; 1.137 - *domain_begin = b; 1.138 - *domain_end = e; 1.139 - } else 1.140 - return FALSE; 1.141 - } else { 1.142 - /* unqualified? */ 1.143 - *domain_begin = *domain_end = NULL; 1.144 - } 1.145 - break; 1.146 - } else if (*p == '<') { 1.147 - /* addr-spec follows */ 1.148 - while (isspace(*p) || (*p == '<')) { 1.149 - if (*p == '<') 1.150 - angle_brackets++; 1.151 - p++; 1.152 - } 1.153 - if (read_word_with_dots(p, &b, &e)) { 1.154 - p = e; 1.155 - *local_begin = b; 1.156 - *local_end = e; 1.157 -#ifdef PARSE_TEST 1.158 - g_print("found local part: %s\n", *local_begin); 1.159 -#endif 1.160 - } else 1.161 - return FALSE; 1.162 - if (*p == '@') { 1.163 - p++; 1.164 - if (read_domain(p, &b, &e)) { 1.165 - p = e; 1.166 - *domain_begin = b; 1.167 - *domain_end = e; 1.168 - } else 1.169 - return FALSE; 1.170 - } else { 1.171 - /* may be unqualified address */ 1.172 - *domain_begin = *domain_end = NULL; 1.173 - } 1.174 - break; 1.175 - } else if (!*p || *p == '>') { 1.176 - *local_begin = b; 1.177 - *local_end = e; 1.178 -#ifdef PARSE_TEST 1.179 - g_print("found local part: %s\n", *local_begin); 1.180 -#endif 1.181 - *domain_begin = *domain_end = NULL; 1.182 - break; 1.183 - } else if (strchr(specials, *p) || iscntrl(*p) || isspace(*p)) { 1.184 - parse_error = g_strdup_printf("unexpected character: %c", *p); 1.185 + /* eat white spaces and comments */ 1.186 + while ((*p && (isspace(*p))) || (*p == '(')) { 1.187 + if (*p == '(') { 1.188 + if (!(p = skip_comment(p))) { 1.189 + parse_error = g_strdup("missing right bracket ')'"); 1.190 return FALSE; 1.191 } 1.192 - } else 1.193 + } else { 1.194 + p++; 1.195 + } 1.196 + } 1.197 + /* we now have a non-space char that is not 1.198 + the beginning of a comment */ 1.199 + 1.200 + if (*p == '@') { 1.201 + /* the last word was the local_part of an addr-spec */ 1.202 + *local_begin = b; 1.203 + *local_end = e; 1.204 +#ifdef PARSE_TEST 1.205 + g_print("found local part: %s\n", *local_begin); 1.206 +#endif 1.207 + if (*p == '@') { 1.208 + p++; /* skip @ */ 1.209 + /* now the domain */ 1.210 + if (!read_domain(p, &b, &e)) { 1.211 + return FALSE; 1.212 + } 1.213 + p = e; 1.214 + *domain_begin = b; 1.215 + *domain_end = e; 1.216 + } else { 1.217 + /* unqualified? */ 1.218 + *domain_begin = *domain_end = NULL; 1.219 + } 1.220 + break; 1.221 + 1.222 + } else if (*p == '<') { 1.223 + /* addr-spec follows */ 1.224 + while (isspace(*p) || (*p == '<')) { 1.225 + if (*p == '<') { 1.226 + angle_brackets++; 1.227 + } 1.228 + p++; 1.229 + } 1.230 + if (!read_word_with_dots(p, &b, &e)) { 1.231 return FALSE; 1.232 + } 1.233 + p = e; 1.234 + *local_begin = b; 1.235 + *local_end = e; 1.236 +#ifdef PARSE_TEST 1.237 + g_print("found local part: %s\n", *local_begin); 1.238 +#endif 1.239 + if (*p == '@') { 1.240 + p++; 1.241 + if (!read_domain(p, &b, &e)) { 1.242 + return FALSE; 1.243 + } 1.244 + p = e; 1.245 + *domain_begin = b; 1.246 + *domain_end = e; 1.247 + } else { 1.248 + /* may be unqualified address */ 1.249 + *domain_begin = *domain_end = NULL; 1.250 + } 1.251 + break; 1.252 + 1.253 + } else if (!*p || *p == '>') { 1.254 + *local_begin = b; 1.255 + *local_end = e; 1.256 +#ifdef PARSE_TEST 1.257 + g_print("found local part: %s\n", *local_begin); 1.258 +#endif 1.259 + *domain_begin = *domain_end = NULL; 1.260 + break; 1.261 + 1.262 + } else if (strchr(specials, *p) || iscntrl(*p) || isspace(*p)) { 1.263 + parse_error = g_strdup_printf("unexpected character: %c", *p); 1.264 + return FALSE; 1.265 } 1.266 - /* trailing spaces and angle brackets */ 1.267 + } 1.268 + 1.269 + /* trailing spaces and angle brackets */ 1.270 #ifdef PARSE_TEST 1.271 - g_print("down counting trailing '>'\n"); 1.272 + g_print("down counting trailing '>'\n"); 1.273 #endif 1.274 - while (*p && (isspace(*p) || (*p == '>'))) { 1.275 - if (*p == '>') 1.276 - angle_brackets--; 1.277 - p++; 1.278 + while (*p && (isspace(*p) || (*p == '>'))) { 1.279 + if (*p == '>') { 1.280 + angle_brackets--; 1.281 } 1.282 + p++; 1.283 + } 1.284 1.285 - *address_end = p; 1.286 + *address_end = p; 1.287 1.288 - if (angle_brackets != 0) { 1.289 - if (angle_brackets > 0) 1.290 - parse_error = g_strdup("missing '>' at end of string"); 1.291 - else 1.292 - parse_error = g_strdup("superfluous '>' at end of string"); 1.293 - return FALSE; 1.294 - } else { 1.295 - /* we successfully parsed the address */ 1.296 - return TRUE; 1.297 - } 1.298 - /* we never get here */ 1.299 + if (angle_brackets > 0) { 1.300 + parse_error = g_strdup("missing '>' at end of string"); 1.301 + return FALSE; 1.302 + } else if (angle_brackets < 0) { 1.303 + parse_error = g_strdup("superfluous '>' at end of string"); 1.304 + return FALSE; 1.305 } 1.306 - return FALSE; 1.307 + 1.308 + /* we successfully parsed the address */ 1.309 + return TRUE; 1.310 } 1.311 1.312 gboolean 1.313 @@ -282,68 +299,71 @@ 1.314 1.315 /* leading spaces and angle brackets */ 1.316 while (*p && (isspace(*p) || (*p == '<'))) { 1.317 - if (*p == '<') 1.318 + if (*p == '<') { 1.319 angle_brackets++; 1.320 + } 1.321 p++; 1.322 } 1.323 1.324 - if (*p) { 1.325 - while (TRUE) { 1.326 - if (read_word_with_dots(p, &b, &e)) { 1.327 - p = e; 1.328 -#ifdef PARSE_TEST 1.329 - g_print("after read_word_with_dots: %s\n", p); 1.330 -#endif 1.331 - *local_begin = b; 1.332 - *local_end = e; 1.333 -#ifdef PARSE_TEST 1.334 - g_print("found local part: %s\n", *local_begin); 1.335 - g_print("local_end = %s\n", *local_end); 1.336 -#endif 1.337 - if (!(*p) || isspace(*p) || (*p == '>')) { 1.338 - /* unqualified ? */ 1.339 - domain_begin = domain_end = NULL; 1.340 - break; 1.341 - } else if (*p == '@') { 1.342 - p++; 1.343 - if (read_domain(p, &b, &e)) { 1.344 - p = e; 1.345 - *domain_begin = b; 1.346 - *domain_end = e; 1.347 - } 1.348 - break; 1.349 - } else { 1.350 - parse_error = g_strdup_printf ("unexpected character after local part '%c'", *p); 1.351 - return FALSE; 1.352 - } 1.353 - } else 1.354 - return FALSE; 1.355 + if (!*p) { 1.356 + return FALSE; 1.357 + } 1.358 + 1.359 + while (TRUE) { 1.360 + if (!read_word_with_dots(p, &b, &e)) { 1.361 + return FALSE; 1.362 } 1.363 1.364 - /* trailing spaces and angle brackets */ 1.365 + p = e; 1.366 #ifdef PARSE_TEST 1.367 - g_print("down counting trailing '>'\n"); 1.368 + g_print("after read_word_with_dots: %s\n", p); 1.369 #endif 1.370 - while (*p && (isspace(*p) || (*p == '>'))) { 1.371 - if (*p == '>') 1.372 - angle_brackets--; 1.373 + *local_begin = b; 1.374 + *local_end = e; 1.375 +#ifdef PARSE_TEST 1.376 + g_print("found local part: %s\n", *local_begin); 1.377 + g_print("local_end = %s\n", *local_end); 1.378 +#endif 1.379 + if (!(*p) || isspace(*p) || (*p == '>')) { 1.380 + /* unqualified ? */ 1.381 + domain_begin = domain_end = NULL; 1.382 + break; 1.383 + } else if (*p == '@') { 1.384 p++; 1.385 + if (read_domain(p, &b, &e)) { 1.386 + p = e; 1.387 + *domain_begin = b; 1.388 + *domain_end = e; 1.389 + } 1.390 + break; 1.391 + } else { 1.392 + parse_error = g_strdup_printf ("unexpected character after local part '%c'", *p); 1.393 + return FALSE; 1.394 } 1.395 - *address_end = p; 1.396 + } 1.397 1.398 - if (angle_brackets != 0) { 1.399 - if (angle_brackets > 0) 1.400 - parse_error = g_strdup("missing '>' at end of string"); 1.401 - else 1.402 - parse_error = g_strdup("superfluous '>' at end of string"); 1.403 - return FALSE; 1.404 - } else { 1.405 - /* we successfully parsed the address */ 1.406 - return TRUE; 1.407 + /* trailing spaces and angle brackets */ 1.408 +#ifdef PARSE_TEST 1.409 + g_print("down counting trailing '>'\n"); 1.410 +#endif 1.411 + while (*p && (isspace(*p) || (*p == '>'))) { 1.412 + if (*p == '>') { 1.413 + angle_brackets--; 1.414 } 1.415 - /* we never get here */ 1.416 + p++; 1.417 } 1.418 - return FALSE; 1.419 + *address_end = p; 1.420 + 1.421 + if (angle_brackets > 0) { 1.422 + parse_error = g_strdup("missing '>' at end of string"); 1.423 + return FALSE; 1.424 + } else if (angle_brackets < 0) { 1.425 + parse_error = g_strdup("superfluous '>' at end of string"); 1.426 + return FALSE; 1.427 + } 1.428 + 1.429 + /* we successfully parsed the address */ 1.430 + return TRUE; 1.431 } 1.432 1.433 /* 1.434 @@ -360,60 +380,66 @@ 1.435 gchar *loc_beg, *loc_end; 1.436 gchar *dom_beg, *dom_end; 1.437 gchar *addr_end; 1.438 + gboolean ret; 1.439 1.440 - if (string && (string[0] == 0)) { 1.441 + if (string && (string[0] == '\0')) { 1.442 address *addr = g_malloc(sizeof(address)); 1.443 addr->address = g_strdup(""); 1.444 addr->local_part = g_strdup(""); 1.445 - addr->domain = g_strdup(""); /* 'NULL' address (failure notice), 1.446 - "" makes sure it will not be qualified with a hostname */ 1.447 + /* 'NULL' address (failure notice), 1.448 + "" makes sure it will not be qualified with a hostname */ 1.449 + addr->domain = g_strdup(""); 1.450 return addr; 1.451 } 1.452 1.453 - if (is_rfc821 1.454 - ? parse_address_rfc821(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end) 1.455 - : parse_address_rfc822(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end)) 1.456 - { 1.457 - address *addr = g_malloc(sizeof(address)); 1.458 - gchar *p = addr_end; 1.459 + if (is_rfc821) { 1.460 + ret = parse_address_rfc821(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end); 1.461 + } else { 1.462 + ret = parse_address_rfc822(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end); 1.463 + } 1.464 + if (!ret) { 1.465 + return NULL; 1.466 + } 1.467 1.468 - memset(addr, 0, sizeof(address)); 1.469 + address *addr = g_malloc(sizeof(address)); 1.470 + gchar *p = addr_end; 1.471 1.472 - if (loc_beg[0] == '|') { 1.473 - parse_error = g_strdup("no pipe allowed for RFC 822/821 address"); 1.474 - return NULL; 1.475 - } 1.476 + memset(addr, 0, sizeof(address)); 1.477 1.478 - while (*p && (*p != ',')) 1.479 - p++; 1.480 - addr->address = g_strndup(string, p - string); 1.481 + if (loc_beg[0] == '|') { 1.482 + parse_error = g_strdup("no pipe allowed for RFC 822/821 address"); 1.483 + return NULL; 1.484 + } 1.485 1.486 - addr->local_part = g_strndup(loc_beg, loc_end - loc_beg); 1.487 + while (*p && (*p != ',')) { 1.488 + p++; 1.489 + } 1.490 + addr->address = g_strndup(string, p - string); 1.491 + addr->local_part = g_strndup(loc_beg, loc_end - loc_beg); 1.492 1.493 #ifdef PARSE_TEST 1.494 - g_print("addr->local_part = %s\n", addr->local_part); 1.495 + g_print("addr->local_part = %s\n", addr->local_part); 1.496 #endif 1.497 1.498 - if (dom_beg != NULL) { 1.499 - addr->domain = g_strndup(dom_beg, dom_end - dom_beg); 1.500 - } else { 1.501 - if (addr->local_part[0] == 0) 1.502 - addr->domain = g_strdup(""); /* 'NULL' address (failure notice), 1.503 - "" makes sure it will not be qualified with a hostname */ 1.504 - else 1.505 - addr->domain = NULL; 1.506 - } 1.507 + if (dom_beg != NULL) { 1.508 + addr->domain = g_strndup(dom_beg, dom_end - dom_beg); 1.509 + } else if (addr->local_part[0] == 0) { 1.510 + /* 'NULL' address (failure notice), 1.511 + "" makes sure it will not be qualified with a hostname */ 1.512 + addr->domain = g_strdup(""); 1.513 + } else { 1.514 + addr->domain = NULL; 1.515 + } 1.516 1.517 - if (end != NULL) 1.518 - *end = p; 1.519 + if (end != NULL) { 1.520 + *end = p; 1.521 + } 1.522 1.523 #ifndef PARSE_TEST 1.524 - addr_unmark_delivered(addr); 1.525 + addr_unmark_delivered(addr); 1.526 #endif 1.527 1.528 - return addr; 1.529 - } 1.530 - return NULL; 1.531 + return addr; 1.532 } 1.533 1.534 address* 1.535 @@ -436,17 +462,24 @@ 1.536 1.537 while (*p) { 1.538 address *addr = _create_address(p, &end, FALSE); 1.539 - if (addr) { 1.540 - if (domain) 1.541 - if (addr->domain == NULL) 1.542 - addr->domain = g_strdup(domain); 1.543 + fprintf(stderr, "string: %s\n", p); 1.544 1.545 - addr_list = g_list_append(addr_list, addr); 1.546 - p = end; 1.547 - } else 1.548 + if (!addr) { 1.549 break; 1.550 - while (*p == ',' || isspace(*p)) 1.551 + } 1.552 + 1.553 + fprintf(stderr, " addr: %s (%s<@>%s)\n", addr->address, addr->local_part, addr->domain); 1.554 + if (domain && !addr->domain) { 1.555 + addr->domain = g_strdup(domain); 1.556 + } 1.557 + fprintf(stderr, " %s (%s<@>%s)\n", addr->address, addr->local_part, addr->domain); 1.558 + 1.559 + addr_list = g_list_append(addr_list, addr); 1.560 + p = end; 1.561 + 1.562 + while (*p == ',' || isspace(*p)) { 1.563 p++; 1.564 + } 1.565 } 1.566 return addr_list; 1.567 }