comparison src/parse.c @ 10:26e34ae9a3e3

changed indention and line wrapping to a more consistent style
author meillo@marmaro.de
date Mon, 27 Oct 2008 16:23:10 +0100
parents 08114f7dcc23
children f671821d8222
comparison
equal deleted inserted replaced
9:31cc8a89cb74 10:26e34ae9a3e3
31 31
32 static gchar *specials = "()<>@,;:\\\".[]`"; 32 static gchar *specials = "()<>@,;:\\\".[]`";
33 33
34 char *parse_error = NULL; 34 char *parse_error = NULL;
35 35
36 static 36 static gchar*
37 gchar *skip_comment(gchar *p) 37 skip_comment(gchar * p)
38 { 38 {
39 39
40 #ifdef PARSE_TEST 40 #ifdef PARSE_TEST
41 g_print("skip_comment: %s\n", p); 41 g_print("skip_comment: %s\n", p);
42 #endif 42 #endif
43 43
44 p++; 44 p++;
45 while(*p && *p != ')'){ 45 while (*p && *p != ')') {
46 p++; 46 p++;
47 if(*p == '(') 47 if (*p == '(')
48 p = skip_comment(p); 48 p = skip_comment(p);
49 } 49 }
50 p++; 50 p++;
51 51
52 return p; 52 return p;
53 } 53 }
54 54
55 static 55 static gboolean
56 gboolean read_word(gchar *p, gchar **b, gchar **e) 56 read_word(gchar * p, gchar ** b, gchar ** e)
57 { 57 {
58 #ifdef PARSE_TEST 58 #ifdef PARSE_TEST
59 g_print("read_word: %s\n", p); 59 g_print("read_word: %s\n", p);
60 #endif 60 #endif
61 /* eat leading spaces */ 61 /* eat leading spaces */
62 while(*p && isspace(*p)) p++; 62 while (*p && isspace(*p))
63 63 p++;
64 *b = p; 64
65 /* b = &p;*/ 65 *b = p;
66 if(*p == '\"'){ 66 /* b = &p; */
67 /* quoted-string */ 67 if (*p == '\"') {
68 p++; 68 /* quoted-string */
69 while(*p && (*p != '\"')) p++; 69 p++;
70 p++; 70 while (*p && (*p != '\"'))
71 }else{ 71 p++;
72 /* atom */ 72 p++;
73 while(*p && !strchr(specials, *p) && !iscntrl(*p) && !isspace(*p)) 73 } else {
74 p++; 74 /* atom */
75 } 75 while (*p && !strchr(specials, *p) && !iscntrl(*p) && !isspace(*p))
76 *e = p; 76 p++;
77 return TRUE; 77 }
78 } 78 *e = p;
79 79 return TRUE;
80 static 80 }
81 gboolean read_word_with_dots(gchar *p, gchar **b, gchar **e) 81
82 { 82 static gboolean
83 gchar *b0 = p; 83 read_word_with_dots(gchar * p, gchar ** b, gchar ** e)
84 84 {
85 #ifdef PARSE_TEST 85 gchar *b0 = p;
86 g_print("read_word_with_dots: %s\n", p); 86
87 #endif 87 #ifdef PARSE_TEST
88 while(TRUE){ 88 g_print("read_word_with_dots: %s\n", p);
89 if(!read_word(p, b, e)) 89 #endif
90 return FALSE; 90 while (TRUE) {
91 p = *e; 91 if (!read_word(p, b, e))
92 if(*p != '.') break; 92 return FALSE;
93 p++; 93 p = *e;
94 } 94 if (*p != '.')
95 *b = b0; 95 break;
96 *e = p; 96 p++;
97 return TRUE; 97 }
98 } 98 *b = b0;
99 99 *e = p;
100 static 100 return TRUE;
101 gboolean read_domain(gchar *p, gchar **b, gchar **e) 101 }
102 { 102
103 #ifdef PARSE_TEST 103 static gboolean
104 g_print("read_domain: %s\n", p); 104 read_domain(gchar * p, gchar ** b, gchar ** e)
105 #endif 105 {
106 *b = p; 106 #ifdef PARSE_TEST
107 if(*p != '['){ 107 g_print("read_domain: %s\n", p);
108 while(isalnum(*p) || (*p == '-') || (*p == '.')) 108 #endif
109 p++; 109 *b = p;
110 }else{ 110 if (*p != '[') {
111 p++; 111 while (isalnum(*p) || (*p == '-') || (*p == '.'))
112 while(isalpha(*p) || (*p == '.')) 112 p++;
113 p++; 113 } else {
114 if(*p != ']'){ 114 p++;
115 parse_error = 115 while (isalpha(*p) || (*p == '.'))
116 g_strdup_printf("']' expected at end of literal address %s", *b); 116 p++;
117 return FALSE; 117 if (*p != ']') {
118 } 118 parse_error = g_strdup_printf("']' expected at end of literal address %s", *b);
119 p++; 119 return FALSE;
120 } 120 }
121 *e = p; 121 p++;
122 return TRUE; 122 }
123 } 123 *e = p;
124 124 return TRUE;
125 gboolean parse_address_rfc822(gchar *string, 125 }
126 gchar **local_begin, gchar **local_end, 126
127 gchar **domain_begin, gchar **domain_end, 127 gboolean
128 gchar **address_end) 128 parse_address_rfc822(gchar* string, gchar** local_begin, gchar** local_end, gchar** domain_begin, gchar** domain_end, gchar** address_end)
129 { 129 {
130 gint angle_brackets = 0; 130 gint angle_brackets = 0;
131 131
132 gchar *p = string; 132 gchar *p = string;
133 gchar *b, *e; 133 gchar *b, *e;
134 134
135 *local_begin = *local_end = NULL; 135 *local_begin = *local_end = NULL;
136 *domain_begin = *domain_end = NULL; 136 *domain_begin = *domain_end = NULL;
137 137
138 /* might be some memory left from previous call: */ 138 /* might be some memory left from previous call: */
139 if(parse_error != NULL){ 139 if (parse_error != NULL) {
140 g_free(parse_error); 140 g_free(parse_error);
141 parse_error = NULL; 141 parse_error = NULL;
142 } 142 }
143 143
144 /* leading spaces and angle brackets */ 144 /* leading spaces and angle brackets */
145 while(*p && (isspace(*p) || (*p == '<'))){ 145 while (*p && (isspace(*p) || (*p == '<'))) {
146 if(*p == '<') 146 if (*p == '<')
147 angle_brackets++; 147 angle_brackets++;
148 p++; 148 p++;
149 } 149 }
150 150
151 if(*p){ 151 if (*p) {
152 while(TRUE){ 152 while (TRUE) {
153 if(read_word_with_dots(p, &b, &e)){ 153 if (read_word_with_dots(p, &b, &e)) {
154 p = e; 154 p = e;
155 #ifdef PARSE_TEST 155 #ifdef PARSE_TEST
156 g_print("after read_word_with_dots: %s\n", p); 156 g_print("after read_word_with_dots: %s\n", p);
157 #endif 157 #endif
158 /* eat white spaces and comments */ 158 /* eat white spaces and comments */
159 while((*p && (isspace(*p))) || (*p == '(')){ 159 while ((*p && (isspace(*p))) || (*p == '(')) {
160 if(*p == '('){ 160 if (*p == '(') {
161 if(!(p = skip_comment(p))){ 161 if (!(p = skip_comment(p))) {
162 parse_error = 162 parse_error = g_strdup("missing right bracket ')'");
163 g_strdup("missing right bracket ')'"); 163 return FALSE;
164 return FALSE; 164 }
165 } 165 } else
166 }else 166 p++;
167 p++; 167 }
168 } 168 /* we now have a non-space char that is not
169 /* we now have a non-space char that is not 169 the beginning of a comment */
170 the beginning of a comment */ 170
171 171 if (*p == '@') {
172 if(*p == '@'){ 172 /* the last word was the local_part
173 /* the last word was the local_part 173 of an addr-spec */
174 of an addr-spec */ 174 *local_begin = b;
175 *local_begin = b; 175 *local_end = e;
176 *local_end = e; 176 #ifdef PARSE_TEST
177 #ifdef PARSE_TEST 177 g_print("found local part: %s\n", *local_begin);
178 g_print("found local part: %s\n", *local_begin); 178 #endif
179 #endif 179 if (*p == '@') {
180 if(*p == '@'){ 180 p++; /* skip @ */
181 p++; /* skip @ */ 181 /* now the domain */
182 /* now the domain */ 182 if (read_domain(p, &b, &e)) {
183 if(read_domain(p, &b, &e)){ 183 p = e;
184 p = e; 184 *domain_begin = b;
185 *domain_begin = b; 185 *domain_end = e;
186 *domain_end = e; 186 } else
187 } 187 return FALSE;
188 else 188 } else {
189 return FALSE; 189 /* unqualified? */
190 }else{ 190 *domain_begin = *domain_end = NULL;
191 /* unqualified? */ 191 }
192 *domain_begin = *domain_end = NULL; 192 break;
193 } 193 } else if (*p == '<') {
194 break; 194 /* addr-spec follows */
195 }else if(*p == '<'){ 195 while (isspace(*p) || (*p == '<')) {
196 /* addr-spec follows */ 196 if (*p == '<')
197 while(isspace(*p) || (*p == '<')){ 197 angle_brackets++;
198 if(*p == '<') 198 p++;
199 angle_brackets++; 199 }
200 p++; 200 if (read_word_with_dots(p, &b, &e)) {
201 } 201 p = e;
202 if(read_word_with_dots(p, &b, &e)){ 202 *local_begin = b;
203 p = e; 203 *local_end = e;
204 *local_begin = b; 204 #ifdef PARSE_TEST
205 *local_end = e; 205 g_print("found local part: %s\n", *local_begin);
206 #ifdef PARSE_TEST 206 #endif
207 g_print("found local part: %s\n", *local_begin); 207 } else
208 #endif 208 return FALSE;
209 }else 209 if (*p == '@') {
210 return FALSE; 210 p++;
211 if(*p == '@'){ 211 if (read_domain(p, &b, &e)) {
212 p++; 212 p = e;
213 if(read_domain(p, &b, &e)){ 213 *domain_begin = b;
214 p = e; 214 *domain_end = e;
215 *domain_begin = b; 215 } else
216 *domain_end = e; 216 return FALSE;
217 }else 217 } else {
218 return FALSE; 218 /* may be unqualified address */
219 }else{ 219 *domain_begin = *domain_end = NULL;
220 /* may be unqualified address */ 220 }
221 *domain_begin = *domain_end = NULL; 221 break;
222 } 222 } else if (!*p || *p == '>') {
223 break; 223 *local_begin = b;
224 }else if(!*p || *p == '>'){ 224 *local_end = e;
225 *local_begin = b; 225 #ifdef PARSE_TEST
226 *local_end = e; 226 g_print("found local part: %s\n", *local_begin);
227 #ifdef PARSE_TEST 227 #endif
228 g_print("found local part: %s\n", *local_begin); 228 *domain_begin = *domain_end = NULL;
229 #endif 229 break;
230 *domain_begin = *domain_end = NULL; 230 } else if (strchr(specials, *p) || iscntrl(*p) || isspace(*p)) {
231 break; 231 parse_error = g_strdup_printf("unexpected character: %c", *p);
232 }else if(strchr(specials, *p) || iscntrl(*p) || isspace(*p)){ 232 return FALSE;
233 parse_error = g_strdup_printf("unexpected character: %c", *p); 233 }
234 return FALSE; 234 } else
235 } 235 return FALSE;
236 }else 236 }
237 /* trailing spaces and angle brackets */
238 #ifdef PARSE_TEST
239 g_print("down counting trailing '>'\n");
240 #endif
241 while (*p && (isspace(*p) || (*p == '>'))) {
242 if (*p == '>')
243 angle_brackets--;
244 p++;
245 }
246
247 *address_end = p;
248
249 if (angle_brackets != 0) {
250 if (angle_brackets > 0)
251 parse_error = g_strdup("missing '>' at end of string");
252 else
253 parse_error = g_strdup("superfluous '>' at end of string");
254 return FALSE;
255 } else {
256 /* we successfully parsed the address */
257 return TRUE;
258 }
259 /* we never get here */
260 }
237 return FALSE; 261 return FALSE;
238 } 262 }
239 /* trailing spaces and angle brackets */ 263
240 #ifdef PARSE_TEST 264 gboolean
241 g_print("down counting trailing '>'\n"); 265 parse_address_rfc821(gchar* string, gchar** local_begin, gchar** local_end, gchar** domain_begin, gchar** domain_end, gchar** address_end)
242 #endif 266 {
243 while(*p && (isspace(*p) || (*p == '>'))){ 267 gint angle_brackets = 0;
244 if(*p == '>') 268
245 angle_brackets--; 269 gchar *p = string;
246 p++; 270 gchar *b, *e;
247 } 271
248 272 *local_begin = *local_end = NULL;
249 *address_end = p; 273 *domain_begin = *domain_end = NULL;
250 274
251 if(angle_brackets != 0){ 275 /* might be some memory left from previous call: */
252 if(angle_brackets > 0) 276 if (parse_error != NULL) {
253 parse_error = g_strdup("missing '>' at end of string"); 277 g_free(parse_error);
254 else 278 parse_error = NULL;
255 parse_error = g_strdup("superfluous '>' at end of string"); 279 }
256 return FALSE; 280
257 }else{ 281 /* leading spaces and angle brackets */
258 /* we successfully parsed the address */ 282 while (*p && (isspace(*p) || (*p == '<'))) {
259 return TRUE; 283 if (*p == '<')
260 } 284 angle_brackets++;
261 /* we never get here */ 285 p++;
262 } 286 }
263 return FALSE; 287
264 } 288 if (*p) {
265 289 while (TRUE) {
266 gboolean parse_address_rfc821(gchar *string, 290 if (read_word_with_dots(p, &b, &e)) {
267 gchar **local_begin, gchar **local_end, 291 p = e;
268 gchar **domain_begin, gchar **domain_end, 292 #ifdef PARSE_TEST
269 gchar **address_end) 293 g_print("after read_word_with_dots: %s\n", p);
270 { 294 #endif
271 gint angle_brackets = 0; 295 *local_begin = b;
272 296 *local_end = e;
273 gchar *p = string; 297 #ifdef PARSE_TEST
274 gchar *b, *e; 298 g_print("found local part: %s\n", *local_begin);
275 299 g_print("local_end = %s\n", *local_end);
276 *local_begin = *local_end = NULL; 300 #endif
277 *domain_begin = *domain_end = NULL; 301 if (!(*p) || isspace(*p) || (*p == '>')) {
278 302 /* unqualified ? */
279 /* might be some memory left from previous call: */ 303 domain_begin = domain_end = NULL;
280 if(parse_error != NULL){ 304 break;
281 g_free(parse_error); 305 } else if (*p == '@') {
282 parse_error = NULL; 306 p++;
283 } 307 if (read_domain(p, &b, &e)) {
284 308 p = e;
285 /* leading spaces and angle brackets */ 309 *domain_begin = b;
286 while(*p && (isspace(*p) || (*p == '<'))){ 310 *domain_end = e;
287 if(*p == '<') 311 }
288 angle_brackets++; 312 break;
289 p++; 313 } else {
290 } 314 parse_error = g_strdup_printf ("unexpected character after local part '%c'", *p);
291 315 return FALSE;
292 if(*p){ 316 }
293 while(TRUE){ 317 } else
294 if(read_word_with_dots(p, &b, &e)){ 318 return FALSE;
295 p = e; 319 }
296 #ifdef PARSE_TEST 320
297 g_print("after read_word_with_dots: %s\n", p); 321 /* trailing spaces and angle brackets */
298 #endif 322 #ifdef PARSE_TEST
299 *local_begin = b; 323 g_print("down counting trailing '>'\n");
300 *local_end = e; 324 #endif
301 #ifdef PARSE_TEST 325 while (*p && (isspace(*p) || (*p == '>'))) {
302 g_print("found local part: %s\n", *local_begin); 326 if (*p == '>')
303 g_print("local_end = %s\n", *local_end); 327 angle_brackets--;
304 #endif 328 p++;
305 if(!(*p) || isspace(*p) || (*p == '>')){ 329 }
306 /* unqualified ?*/ 330 *address_end = p;
307 domain_begin = domain_end = NULL; 331
308 break; 332 if (angle_brackets != 0) {
309 }else if(*p == '@'){ 333 if (angle_brackets > 0)
310 p++; 334 parse_error = g_strdup("missing '>' at end of string");
311 if(read_domain(p, &b, &e)){ 335 else
312 p = e; 336 parse_error = g_strdup("superfluous '>' at end of string");
313 *domain_begin = b; 337 return FALSE;
314 *domain_end = e; 338 } else {
315 } 339 /* we successfully parsed the address */
316 break; 340 return TRUE;
317 }else{ 341 }
318 parse_error = 342 /* we never get here */
319 g_strdup_printf("unexpected character after local part '%c'",*p); 343 }
320 return FALSE; 344 return FALSE;
321 }
322 } else
323 return FALSE;
324 }
325
326 /* trailing spaces and angle brackets */
327 #ifdef PARSE_TEST
328 g_print("down counting trailing '>'\n");
329 #endif
330 while(*p && (isspace(*p) || (*p == '>'))){
331 if(*p == '>')
332 angle_brackets--;
333 p++;
334 }
335 *address_end = p;
336
337 if(angle_brackets != 0){
338 if(angle_brackets > 0)
339 parse_error = g_strdup("missing '>' at end of string");
340 else
341 parse_error = g_strdup("superfluous '>' at end of string");
342 return FALSE;
343 }else{
344 /* we successfully parsed the address */
345 return TRUE;
346 }
347 /* we never get here */
348 }
349 return FALSE;
350 } 345 }
351 346
352 /* 347 /*
353 allocate address, reading from string. 348 allocate address, reading from string.
354 On failure, returns NULL. 349 On failure, returns NULL.
356 end may be NULL, if we are not interested. 351 end may be NULL, if we are not interested.
357 352
358 parses both rfc 821 and rfc 822 addresses, depending on flag is_rfc821 353 parses both rfc 821 and rfc 822 addresses, depending on flag is_rfc821
359 */ 354 */
360 355
361 address *_create_address(gchar *string, gchar **end, gboolean is_rfc821) 356 address*
362 { 357 _create_address(gchar * string, gchar ** end, gboolean is_rfc821)
363 gchar *loc_beg, *loc_end; 358 {
364 gchar *dom_beg, *dom_end; 359 gchar *loc_beg, *loc_end;
365 gchar *addr_end; 360 gchar *dom_beg, *dom_end;
366 361 gchar *addr_end;
367 if (string && (string[0] == 0)) { 362
368 address *addr = g_malloc(sizeof(address)); 363 if (string && (string[0] == 0)) {
369 addr->address = g_strdup(""); 364 address *addr = g_malloc(sizeof(address));
370 addr->local_part = g_strdup(""); 365 addr->address = g_strdup("");
371 addr->domain = g_strdup(""); /* 'NULL' address (failure notice), 366 addr->local_part = g_strdup("");
372 "" makes sure it will not be qualified with a hostname */ 367 addr->domain = g_strdup(""); /* 'NULL' address (failure notice), "" makes sure it will not be qualified with a hostname */
373 return addr; 368 return addr;
374 } 369 }
375 370
376 if(is_rfc821 ? 371 if (is_rfc821
377 parse_address_rfc821(string, 372 ? parse_address_rfc821(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end)
378 &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end) : 373 : parse_address_rfc822(string, &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end))
379 parse_address_rfc822(string, 374 {
380 &loc_beg, &loc_end, &dom_beg, &dom_end, &addr_end)){ 375 address *addr = g_malloc(sizeof(address));
381 address *addr = g_malloc(sizeof(address)); 376 gchar *p = addr_end;
382 gchar *p = addr_end; 377
383 378
384 379 memset(addr, 0, sizeof(address));
385 memset(addr, 0, sizeof(address)); 380
386 381 if (loc_beg[0] == '|') {
387 if(loc_beg[0] == '|'){ 382 parse_error = g_strdup("no pipe allowed for RFC 822/821 address");
388 parse_error = g_strdup("no pipe allowed for RFC 822/821 address"); 383 return NULL;
389 return NULL; 384 }
390 } 385
391 386 while (*p && (*p != ','))
392 while(*p && (*p != ',')) p++; 387 p++;
393 addr->address = g_strndup(string, p - string); 388 addr->address = g_strndup(string, p - string);
394 389
395 addr->local_part = g_strndup(loc_beg, loc_end - loc_beg); 390 addr->local_part = g_strndup(loc_beg, loc_end - loc_beg);
396 391
397 #ifdef PARSE_TEST 392 #ifdef PARSE_TEST
398 g_print("addr->local_part = %s\n", addr->local_part); 393 g_print("addr->local_part = %s\n", addr->local_part);
399 #endif 394 #endif
400 395
401 if(dom_beg != NULL){ 396 if (dom_beg != NULL) {
402 addr->domain = g_strndup(dom_beg, dom_end - dom_beg); 397 addr->domain = g_strndup(dom_beg, dom_end - dom_beg);
403 }else{ 398 } else {
404 if(addr->local_part[0] == 0) 399 if (addr->local_part[0] == 0)
405 addr->domain = g_strdup(""); /* 'NULL' address (failure notice), 400 addr->domain = g_strdup(""); /* 'NULL' address (failure notice), "" makes sure it will not be qualified with a hostname */
406 "" makes sure it will not be qualified with a hostname */ 401 else
407 else 402 addr->domain = NULL;
408 addr->domain = NULL; 403 }
409 } 404
410 405 if (end != NULL)
411 if(end != NULL) 406 *end = p;
412 *end = p;
413 407
414 #ifndef PARSE_TEST 408 #ifndef PARSE_TEST
415 addr_unmark_delivered(addr); 409 addr_unmark_delivered(addr);
416 #endif 410 #endif
417 411
418 return addr; 412 return addr;
419 } 413 }
420 return NULL; 414 return NULL;
421 } 415 }
422 416
423 address *create_address_rfc822(gchar *string, gchar **end){ 417 address*
424 return _create_address(string, end, FALSE); 418 create_address_rfc822(gchar * string, gchar ** end)
425 } 419 {
426 420 return _create_address(string, end, FALSE);
427 address *create_address_rfc821(gchar *string, gchar **end){ 421 }
428 return _create_address(string, end, TRUE); 422
429 } 423 address*
430 424 create_address_rfc821(gchar * string, gchar ** end)
431 GList *addr_list_append_rfc822(GList *addr_list, gchar *string, gchar *domain) 425 {
432 { 426 return _create_address(string, end, TRUE);
433 gchar *p = string; 427 }
434 gchar *end; 428
435 429 GList*
436 while(*p){ 430 addr_list_append_rfc822(GList * addr_list, gchar * string, gchar * domain)
437 address *addr = _create_address(p, &end, FALSE); 431 {
438 if(addr){ 432 gchar *p = string;
439 if(domain) 433 gchar *end;
440 if(addr->domain == NULL) 434
441 addr->domain = g_strdup(domain); 435 while (*p) {
442 436 address *addr = _create_address(p, &end, FALSE);
443 addr_list = g_list_append(addr_list, addr); 437 if (addr) {
444 p = end; 438 if (domain)
445 }else 439 if (addr->domain == NULL)
446 break; 440 addr->domain = g_strdup(domain);
447 while(*p == ',' || isspace(*p)) p++; 441
448 } 442 addr_list = g_list_append(addr_list, addr);
449 return addr_list; 443 p = end;
450 } 444 } else
445 break;
446 while (*p == ',' || isspace(*p))
447 p++;
448 }
449 return addr_list;
450 }