masqmail

changeset 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 0c44b239c7fe
children 681863fdafbb
files src/parse.c
diffstat 1 files changed, 232 insertions(+), 199 deletions(-) [+]
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  }