summaryrefslogtreecommitdiff
path: root/library/backend/vcc.y
Unidiff
Diffstat (limited to 'library/backend/vcc.y') (more/less context) (ignore whitespace changes)
-rw-r--r--library/backend/vcc.y2407
1 files changed, 1208 insertions, 1199 deletions
diff --git a/library/backend/vcc.y b/library/backend/vcc.y
index e326a64..5bcf0cb 100644
--- a/library/backend/vcc.y
+++ b/library/backend/vcc.y
@@ -1,1199 +1,1208 @@
1%{ 1%{
2 2
3/*************************************************************************** 3/***************************************************************************
4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
5Business Machines Corporation and Siemens Rolm Communications Inc. 5Business Machines Corporation and Siemens Rolm Communications Inc.
6 6
7For purposes of this license notice, the term Licensors shall mean, 7For purposes of this license notice, the term Licensors shall mean,
8collectively, Apple Computer, Inc., AT&T Corp., International 8collectively, Apple Computer, Inc., AT&T Corp., International
9Business Machines Corporation and Siemens Rolm Communications Inc. 9Business Machines Corporation and Siemens Rolm Communications Inc.
10The term Licensor shall mean any of the Licensors. 10The term Licensor shall mean any of the Licensors.
11 11
12Subject to acceptance of the following conditions, permission is hereby 12Subject to acceptance of the following conditions, permission is hereby
13granted by Licensors without the need for written agreement and without 13granted by Licensors without the need for written agreement and without
14license or royalty fees, to use, copy, modify and distribute this 14license or royalty fees, to use, copy, modify and distribute this
15software for any purpose. 15software for any purpose.
16 16
17The above copyright notice and the following four paragraphs must be 17The above copyright notice and the following four paragraphs must be
18reproduced in all copies of this software and any software including 18reproduced in all copies of this software and any software including
19this software. 19this software.
20 20
21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
23MODIFICATIONS. 23MODIFICATIONS.
24 24
25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28DAMAGE. 28DAMAGE.
29 29
30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33PURPOSE. 33PURPOSE.
34 34
35The software is provided with RESTRICTED RIGHTS. Use, duplication, or 35The software is provided with RESTRICTED RIGHTS. Use, duplication, or
36disclosure by the government are subject to restrictions set forth in 36disclosure by the government are subject to restrictions set forth in
37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
38 38
39***************************************************************************/ 39***************************************************************************/
40 40
41/* 41/*
42 * src: vcc.c 42 * src: vcc.c
43 * doc: Parser for vCard and vCalendar. Note that this code is 43 * doc: Parser for vCard and vCalendar. Note that this code is
44 * generated by a yacc parser generator. Generally it should not 44 * generated by a yacc parser generator. Generally it should not
45 * be edited by hand. The real source is vcc.y. The #line directives 45 * be edited by hand. The real source is vcc.y. The #line directives
46 * can be commented out here to make it easier to trace through 46 * can be commented out here to make it easier to trace through
47 * in a debugger. However, if a bug is found it should 47 * in a debugger. However, if a bug is found it should
48 * be fixed in vcc.y and this file regenerated. 48 * be fixed in vcc.y and this file regenerated.
49 */ 49 */
50 50
51 51
52/* debugging utilities */ 52/* debugging utilities */
53#if __DEBUG 53#if __DEBUG
54#define DBG_(x) printf x 54#define DBG_(x) printf x
55#else 55#else
56#define DBG_(x) 56#define DBG_(x)
57#endif 57#endif
58 58
59/**** External Functions ****/ 59/**** External Functions ****/
60 60
61/* assign local name to parser variables and functions so that 61/* assign local name to parser variables and functions so that
62 we can use more than one yacc based parser. 62 we can use more than one yacc based parser.
63*/ 63*/
64 64
65#if 0 65#if 0
66#define yyparse mime_parse 66#define yyparse mime_parse
67#define yylex mime_lex 67#define yylex mime_lex
68#define yyerror mime_error 68#define yyerror mime_error
69#define yychar mime_char 69#define yychar mime_char
70/* #define p_yyval p_mime_val */ 70/* #define p_yyval p_mime_val */
71#undef yyval 71#undef yyval
72#define yyval mime_yyval 72#define yyval mime_yyval
73/* #define p_yylval p_mime_lval */ 73/* #define p_yylval p_mime_lval */
74#undef yylval 74#undef yylval
75#define yylval mime_yylval 75#define yylval mime_yylval
76#define yydebug mime_debug 76#define yydebug mime_debug
77#define yynerrs mime_nerrs 77#define yynerrs mime_nerrs
78#define yyerrflag mime_errflag 78#define yyerrflag mime_errflag
79#define yyss mime_ss 79#define yyss mime_ss
80#define yyssp mime_ssp 80#define yyssp mime_ssp
81#define yyvs mime_vs 81#define yyvs mime_vs
82#define yyvsp mime_vsp 82#define yyvsp mime_vsp
83#define yylhs mime_lhs 83#define yylhs mime_lhs
84#define yylen mime_len 84#define yylen mime_len
85#define yydefred mime_defred 85#define yydefred mime_defred
86#define yydgoto mime_dgoto 86#define yydgoto mime_dgoto
87#define yysindex mime_sindex 87#define yysindex mime_sindex
88#define yyrindex mime_rindex 88#define yyrindex mime_rindex
89#define yygindex mime_gindex 89#define yygindex mime_gindex
90#define yytable mime_table 90#define yytable mime_table
91#define yycheck mime_check 91#define yycheck mime_check
92#define yyname mime_name 92#define yyname mime_name
93#define yyrule mime_rule 93#define yyrule mime_rule
94#ifdef YYPREFIX 94#ifdef YYPREFIX
95#undef YYPREFIX 95#undef YYPREFIX
96#endif 96#endif
97#define YYPREFIX "mime_" 97#define YYPREFIX "mime_"
98#endif 98#endif
99 99
100 100
101#ifndef _NO_LINE_FOLDING 101#ifndef _NO_LINE_FOLDING
102#define _SUPPORT_LINE_FOLDING 1 102#define _SUPPORT_LINE_FOLDING 1
103#endif 103#endif
104 104
105/* undef below if compile with MFC */ 105/* undef below if compile with MFC */
106/* #define INCLUDEMFC 1 */ 106/* #define INCLUDEMFC 1 */
107 107
108#if defined(WIN32) || defined(_WIN32) 108#if defined(WIN32) || defined(_WIN32)
109#ifdef INCLUDEMFC 109#ifdef INCLUDEMFC
110#include <afx.h> 110#include <afx.h>
111#endif 111#endif
112#endif 112#endif
113 113
114#include <string.h> 114#include <string.h>
115#ifndef __MWERKS__ 115#ifndef __MWERKS__
116#include <stdlib.h> 116#include <stdlib.h>
117#endif 117#endif
118#include <stdio.h> 118#include <stdio.h>
119#include <stdlib.h> 119#include <stdlib.h>
120#include <ctype.h> 120#include <ctype.h>
121 121
122//#ifdef PALMTOPCENTER 122//#ifdef PALMTOPCENTER
123//#include <qpe/vobject_p.h> 123//#include <qpe/vobject_p.h>
124//#else 124//#else
125#include "vobject_p.h" 125#include "vobject_p.h"
126//#endif 126//#endif
127 127
128/**** Types, Constants ****/ 128/**** Types, Constants ****/
129 129
130 #define YYDEBUG 0/* 1 to compile in some debugging code */ 130 #define YYDEBUG 0/* 1 to compile in some debugging code */
131 #define MAXTOKEN 256/* maximum token (line) length */ 131 #define MAXTOKEN 256/* maximum token (line) length */
132 #define YYSTACKSIZE 100// ~unref ? 132 #define YYSTACKSIZE 100// ~unref ?
133 #define MAXLEVEL 10/* max # of nested objects parseable */ 133 #define MAXLEVEL 10/* max # of nested objects parseable */
134 /* (includes outermost) */ 134 /* (includes outermost) */
135 135
136 136
137/**** Global Variables ****/ 137/**** Global Variables ****/
138int mime_lineNum, mime_numErrors; /* yyerror() can use these */ 138int mime_lineNum, mime_numErrors; /* yyerror() can use these */
139static VObject* vObjList; 139static VObject* vObjList;
140static VObject *curProp; 140static VObject *curProp;
141static VObject *curObj; 141static VObject *curObj;
142static VObject* ObjStack[MAXLEVEL]; 142static VObject* ObjStack[MAXLEVEL];
143static int ObjStackTop; 143static int ObjStackTop;
144 144
145 145
146/* A helpful utility for the rest of the app. */ 146/* A helpful utility for the rest of the app. */
147#if __CPLUSPLUS__ 147#if __CPLUSPLUS__
148extern "C" { 148extern "C" {
149#endif 149#endif
150 150
151 extern void yyerror(char *s); 151 extern void yyerror(char *s);
152 152
153#if __CPLUSPLUS__ 153#if __CPLUSPLUS__
154 }; 154 };
155#endif 155#endif
156 156
157int yyparse(); 157int yyparse();
158 158
159enum LexMode { 159enum LexMode {
160 L_NORMAL, 160 L_NORMAL,
161 L_VCARD, 161 L_VCARD,
162 L_VCAL, 162 L_VCAL,
163 L_VEVENT, 163 L_VEVENT,
164 L_VTODO, 164 L_VTODO,
165 L_VALUES, 165 L_VALUES,
166 L_BASE64, 166 L_BASE64,
167 L_QUOTED_PRINTABLE 167 L_QUOTED_PRINTABLE
168 }; 168 };
169 169
170/**** Private Forward Declarations ****/ 170/**** Private Forward Declarations ****/
171static int pushVObject(const char *prop); 171static int pushVObject(const char *prop);
172static VObject* popVObject(); 172static VObject* popVObject();
173static void lexPopMode(int top); 173static void lexPopMode(int top);
174static int lexWithinMode(enum LexMode mode); 174static int lexWithinMode(enum LexMode mode);
175static void lexPushMode(enum LexMode mode); 175static void lexPushMode(enum LexMode mode);
176static void enterProps(const char *s); 176static void enterProps(const char *s);
177static void enterAttr(const char *s1, const char *s2); 177static void enterAttr(const char *s1, const char *s2);
178static void enterValues(const char *value); 178static void enterValues(const char *value);
179#define mime_error yyerror 179#define mime_error yyerror
180void mime_error(char *s); 180void mime_error(char *s);
181void mime_error_(char *s); 181void mime_error_(char *s);
182 182
183%} 183%}
184 184
185/***************************************************************************/ 185/***************************************************************************/
186/*** The grammar ****/ 186/*** The grammar ****/
187/***************************************************************************/ 187/***************************************************************************/
188 188
189%union { 189%union {
190 char *str; 190 char *str;
191 VObject *vobj; 191 VObject *vobj;
192 } 192 }
193 193
194%token 194%token
195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE 195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE
196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL 196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL
197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO 197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO
198 ID 198 ID
199 199
200/* 200/*
201 * NEWLINE is the token that would occur outside a vCard, 201 * NEWLINE is the token that would occur outside a vCard,
202 * while LINESEP is the token that would occur inside a vCard. 202 * while LINESEP is the token that would occur inside a vCard.
203 */ 203 */
204 204
205%token <str> 205%token <str>
206 STRING ID 206 STRING ID
207 207
208%type <str> name value 208%type <str> name value
209 209
210%type <vobj> vcard vcal vobject 210%type <vobj> vcard vcal vobject
211 211
212%start mime 212%start mime
213 213
214%% 214%%
215 215
216 216
217mime: vobjects 217mime: vobjects
218 ; 218 ;
219 219
220vobjects: vobjects vobject 220vobjects: vobjects vobject
221 { addList(&vObjList, $2); curObj = 0; } 221 { addList(&vObjList, $2); curObj = 0; }
222 | vobject 222 | vobject
223 { addList(&vObjList, $1); curObj = 0; } 223 { addList(&vObjList, $1); curObj = 0; }
224 ; 224 ;
225 225
226vobject: vcard 226vobject: vcard
227 | vcal 227 | vcal
228 ; 228 ;
229 229
230vcard: 230vcard:
231 BEGIN_VCARD 231 BEGIN_VCARD
232 { 232 {
233 lexPushMode(L_VCARD); 233 lexPushMode(L_VCARD);
234 if (!pushVObject(VCCardProp)) YYERROR; 234 if (!pushVObject(VCCardProp)) YYERROR;
235 } 235 }
236 items END_VCARD 236 items END_VCARD
237 { 237 {
238 lexPopMode(0); 238 lexPopMode(0);
239 $$ = popVObject(); 239 $$ = popVObject();
240 } 240 }
241 | BEGIN_VCARD 241 | BEGIN_VCARD
242 { 242 {
243 lexPushMode(L_VCARD); 243 lexPushMode(L_VCARD);
244 if (!pushVObject(VCCardProp)) YYERROR; 244 if (!pushVObject(VCCardProp)) YYERROR;
245 } 245 }
246 END_VCARD 246 END_VCARD
247 { 247 {
248 lexPopMode(0); 248 lexPopMode(0);
249 $$ = popVObject(); 249 $$ = popVObject();
250 } 250 }
251 ; 251 ;
252 252
253items: items item 253items: items item
254 | item 254 | item
255 ; 255 ;
256 256
257item: prop COLON 257item: prop COLON
258 { 258 {
259 lexPushMode(L_VALUES); 259 lexPushMode(L_VALUES);
260 } 260 }
261 values LINESEP 261 values LINESEP
262 { 262 {
263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) 263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
264 lexPopMode(0); 264 lexPopMode(0);
265 lexPopMode(0); 265 lexPopMode(0);
266 } 266 }
267 | error 267 | error
268 ; 268 ;
269 269
270prop: name 270prop: name
271 { 271 {
272 enterProps($1); 272 enterProps($1);
273 } 273 }
274 attr_params 274 attr_params
275 | name 275 | name
276 { 276 {
277 enterProps($1); 277 enterProps($1);
278 } 278 }
279 ; 279 ;
280 280
281attr_params: attr_params attr_param 281attr_params: attr_params attr_param
282 | attr_param 282 | attr_param
283 ; 283 ;
284 284
285attr_param: SEMICOLON attr 285attr_param: SEMICOLON attr
286 ; 286 ;
287 287
288attr: name 288attr: name
289 { 289 {
290 enterAttr($1,0); 290 enterAttr($1,0);
291 } 291 }
292 | name EQ name 292 | name EQ name
293 { 293 {
294 enterAttr($1,$3); 294 enterAttr($1,$3);
295 295
296 } 296 }
297 ; 297 ;
298 298
299name: ID 299name: ID
300 ; 300 ;
301 301
302values: value SEMICOLON { enterValues($1); } values 302values: value SEMICOLON { enterValues($1); } values
303 | value 303 | value
304 { enterValues($1); } 304 { enterValues($1); }
305 ; 305 ;
306 306
307value: STRING 307value: STRING
308 | 308 |
309 { $$ = 0; } 309 { $$ = 0; }
310 ; 310 ;
311 311
312vcal: 312vcal:
313 BEGIN_VCAL 313 BEGIN_VCAL
314 { if (!pushVObject(VCCalProp)) YYERROR; } 314 { if (!pushVObject(VCCalProp)) YYERROR; }
315 calitems 315 calitems
316 END_VCAL 316 END_VCAL
317 { $$ = popVObject(); } 317 { $$ = popVObject(); }
318 | BEGIN_VCAL 318 | BEGIN_VCAL
319 { if (!pushVObject(VCCalProp)) YYERROR; } 319 { if (!pushVObject(VCCalProp)) YYERROR; }
320 END_VCAL 320 END_VCAL
321 { $$ = popVObject(); } 321 { $$ = popVObject(); }
322 ; 322 ;
323 323
324calitems: calitems calitem 324calitems: calitems calitem
325 | calitem 325 | calitem
326 ; 326 ;
327 327
328calitem: 328calitem:
329 eventitem 329 eventitem
330 | todoitem 330 | todoitem
331 | items 331 | items
332 ; 332 ;
333 333
334eventitem: 334eventitem:
335 BEGIN_VEVENT 335 BEGIN_VEVENT
336 { 336 {
337 lexPushMode(L_VEVENT); 337 lexPushMode(L_VEVENT);
338 if (!pushVObject(VCEventProp)) YYERROR; 338 if (!pushVObject(VCEventProp)) YYERROR;
339 } 339 }
340 items 340 items
341 END_VEVENT 341 END_VEVENT
342 { 342 {
343 lexPopMode(0); 343 lexPopMode(0);
344 popVObject(); 344 popVObject();
345 } 345 }
346 | BEGIN_VEVENT 346 | BEGIN_VEVENT
347 { 347 {
348 lexPushMode(L_VEVENT); 348 lexPushMode(L_VEVENT);
349 if (!pushVObject(VCEventProp)) YYERROR; 349 if (!pushVObject(VCEventProp)) YYERROR;
350 } 350 }
351 END_VEVENT 351 END_VEVENT
352 { 352 {
353 lexPopMode(0); 353 lexPopMode(0);
354 popVObject(); 354 popVObject();
355 } 355 }
356 ; 356 ;
357 357
358todoitem: 358todoitem:
359 BEGIN_VTODO 359 BEGIN_VTODO
360 { 360 {
361 lexPushMode(L_VTODO); 361 lexPushMode(L_VTODO);
362 if (!pushVObject(VCTodoProp)) YYERROR; 362 if (!pushVObject(VCTodoProp)) YYERROR;
363 } 363 }
364 items 364 items
365 END_VTODO 365 END_VTODO
366 { 366 {
367 lexPopMode(0); 367 lexPopMode(0);
368 popVObject(); 368 popVObject();
369 } 369 }
370 | BEGIN_VTODO 370 | BEGIN_VTODO
371 { 371 {
372 lexPushMode(L_VTODO); 372 lexPushMode(L_VTODO);
373 if (!pushVObject(VCTodoProp)) YYERROR; 373 if (!pushVObject(VCTodoProp)) YYERROR;
374 } 374 }
375 END_VTODO 375 END_VTODO
376 { 376 {
377 lexPopMode(0); 377 lexPopMode(0);
378 popVObject(); 378 popVObject();
379 } 379 }
380 ; 380 ;
381 381
382%% 382%%
383/*------------------------------------*/ 383/*------------------------------------*/
384static int pushVObject(const char *prop) 384static int pushVObject(const char *prop)
385 { 385 {
386 VObject *newObj; 386 VObject *newObj;
387 if (ObjStackTop == MAXLEVEL) 387 if (ObjStackTop == MAXLEVEL)
388 return FALSE; 388 return FALSE;
389 389
390 ObjStack[++ObjStackTop] = curObj; 390 ObjStack[++ObjStackTop] = curObj;
391 391
392 if (curObj) { 392 if (curObj) {
393 newObj = addProp(curObj,prop); 393 newObj = addProp(curObj,prop);
394 curObj = newObj; 394 curObj = newObj;
395 } 395 }
396 else 396 else
397 curObj = newVObject(prop); 397 curObj = newVObject(prop);
398 398
399 return TRUE; 399 return TRUE;
400 } 400 }
401 401
402 402
403/*---------------------------------------*/ 403/*---------------------------------------*/
404/* This pops the recently built vCard off the stack and returns it. */ 404/* This pops the recently built vCard off the stack and returns it. */
405static VObject* popVObject() 405static VObject* popVObject()
406 { 406 {
407 VObject *oldObj; 407 VObject *oldObj;
408 if (ObjStackTop < 0) { 408 if (ObjStackTop < 0) {
409 yyerror("pop on empty Object Stack\n"); 409 yyerror("pop on empty Object Stack\n");
410 return 0; 410 return 0;
411 } 411 }
412 oldObj = curObj; 412 oldObj = curObj;
413 curObj = ObjStack[ObjStackTop--]; 413 curObj = ObjStack[ObjStackTop--];
414 414
415 return oldObj; 415 return oldObj;
416 } 416 }
417 417
418 418
419static void enterValues(const char *value) 419static void enterValues(const char *value)
420 { 420 {
421 if (fieldedProp && *fieldedProp) { 421 if (fieldedProp && *fieldedProp) {
422 if (value) { 422 if (value) {
423 addPropValue(curProp,*fieldedProp,value); 423 addPropValue(curProp,*fieldedProp,value);
424 } 424 }
425 /* else this field is empty, advance to next field */ 425 /* else this field is empty, advance to next field */
426 fieldedProp++; 426 fieldedProp++;
427 } 427 }
428 else { 428 else {
429 if (value) { 429 if (value) {
430 setVObjectStringZValue_(curProp,strdup( value )); 430 setVObjectStringZValue_(curProp,strdup( value ));
431 } 431 }
432 } 432 }
433 deleteStr(value); 433 deleteStr(value);
434 } 434 }
435 435
436static void enterProps(const char *s) 436static void enterProps(const char *s)
437 { 437 {
438 curProp = addGroup(curObj,s); 438 curProp = addGroup(curObj,s);
439 deleteStr(s); 439 deleteStr(s);
440 } 440 }
441 441
442static void enterAttr(const char *s1, const char *s2) 442static void enterAttr(const char *s1, const char *s2)
443 { 443 {
444 const char *p1, *p2; 444 const char *p1, *p2;
445 p1 = lookupProp_(s1); 445 p1 = lookupProp_(s1);
446 if (s2) { 446 if (s2) {
447 VObject *a; 447 VObject *a;
448 p2 = lookupProp_(s2); 448 p2 = lookupProp_(s2);
449 a = addProp(curProp,p1); 449 a = addProp(curProp,p1);
450 setVObjectStringZValue(a,p2); 450 setVObjectStringZValue(a,p2);
451 } 451 }
452 else 452 else
453 addProp(curProp,p1); 453 addProp(curProp,p1);
454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) 454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
455 lexPushMode(L_BASE64); 455 lexPushMode(L_BASE64);
456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0 456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0
457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) 457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
458 lexPushMode(L_QUOTED_PRINTABLE); 458 lexPushMode(L_QUOTED_PRINTABLE);
459 deleteStr(s1); deleteStr(s2); 459 deleteStr(s1); deleteStr(s2);
460 } 460 }
461 461
462 462
463#define MAX_LEX_LOOKAHEAD_0 32 463#define MAX_LEX_LOOKAHEAD_0 32
464#define MAX_LEX_LOOKAHEAD 64 464#define MAX_LEX_LOOKAHEAD 64
465#define MAX_LEX_MODE_STACK_SIZE 10 465#define MAX_LEX_MODE_STACK_SIZE 10
466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) 466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
467 467
468struct LexBuf { 468struct LexBuf {
469 /* input */ 469 /* input */
470#ifdef INCLUDEMFC 470#ifdef INCLUDEMFC
471 CFile *inputFile; 471 CFile *inputFile;
472#else 472#else
473 FILE *inputFile; 473 FILE *inputFile;
474#endif 474#endif
475 char *inputString; 475 char *inputString;
476 unsigned long curPos; 476 unsigned long curPos;
477 unsigned long inputLen; 477 unsigned long inputLen;
478 /* lookahead buffer */ 478 /* lookahead buffer */
479 /* -- lookahead buffer is short instead of char so that EOF 479 /* -- lookahead buffer is short instead of char so that EOF
480 / can be represented correctly. 480 / can be represented correctly.
481 */ 481 */
482 unsigned long len; 482 unsigned long len;
483 short buf[MAX_LEX_LOOKAHEAD]; 483 short buf[MAX_LEX_LOOKAHEAD];
484 unsigned long getPtr; 484 unsigned long getPtr;
485 /* context stack */ 485 /* context stack */
486 unsigned long lexModeStackTop; 486 unsigned long lexModeStackTop;
487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; 487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
488 /* token buffer */ 488 /* token buffer */
489 unsigned long maxToken; 489 unsigned long maxToken;
490 char *strs; 490 char *strs;
491 unsigned long strsLen; 491 unsigned long strsLen;
492 } lexBuf; 492 } lexBuf;
493 493
494static void lexPushMode(enum LexMode mode) 494static void lexPushMode(enum LexMode mode)
495 { 495 {
496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) 496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
497 yyerror("lexical context stack overflow"); 497 yyerror("lexical context stack overflow");
498 else { 498 else {
499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; 499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
500 } 500 }
501 } 501 }
502 502
503static void lexPopMode(int top) 503static void lexPopMode(int top)
504 { 504 {
505 /* special case of pop for ease of error recovery -- this 505 /* special case of pop for ease of error recovery -- this
506 version will never underflow */ 506 version will never underflow */
507 if (top) 507 if (top)
508 lexBuf.lexModeStackTop = 0; 508 lexBuf.lexModeStackTop = 0;
509 else 509 else
510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; 510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
511 } 511 }
512 512
513static int lexWithinMode(enum LexMode mode) { 513static int lexWithinMode(enum LexMode mode) {
514 unsigned long i; 514 unsigned long i;
515 for (i=0;i<lexBuf.lexModeStackTop;i++) 515 for (i=0;i<lexBuf.lexModeStackTop;i++)
516 if (mode == lexBuf.lexModeStack[i]) return 1; 516 if (mode == lexBuf.lexModeStack[i]) return 1;
517 return 0; 517 return 0;
518 } 518 }
519 519
520static char lexGetc_() 520static int lexGetc_()
521 { 521 {
522 /* get next char from input, no buffering. */ 522 /* get next char from input, no buffering. */
523 if (lexBuf.curPos == lexBuf.inputLen) 523 if (lexBuf.curPos == lexBuf.inputLen)
524 return EOF; 524 return EOF;
525 else if (lexBuf.inputString) 525 else if (lexBuf.inputString)
526 return *(lexBuf.inputString + lexBuf.curPos++); 526 return *(lexBuf.inputString + lexBuf.curPos++);
527 else { 527 else {
528#ifdef INCLUDEMFC 528#ifdef INCLUDEMFC
529 char result; 529 char result;
530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF; 530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
531#else 531#else
532 return fgetc(lexBuf.inputFile); 532 return fgetc(lexBuf.inputFile);
533#endif 533#endif
534 } 534 }
535 } 535 }
536 536
537static int lexGeta() 537static int lexGeta()
538 { 538 {
539 ++lexBuf.len; 539 ++lexBuf.len;
540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); 540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
541 } 541 }
542 542
543static int lexGeta_(int i) 543static int lexGeta_(int i)
544 { 544 {
545 ++lexBuf.len; 545 ++lexBuf.len;
546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); 546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
547 } 547 }
548 548
549static void lexSkipLookahead() { 549static void lexSkipLookahead() {
550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
551 /* don't skip EOF. */ 551 /* don't skip EOF. */
552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
553 lexBuf.len--; 553 lexBuf.len--;
554 } 554 }
555 } 555 }
556 556
557static int lexLookahead() { 557static int lexLookahead() {
558 int c = (lexBuf.len)? 558 int c = (lexBuf.len)?
559 lexBuf.buf[lexBuf.getPtr]: 559 lexBuf.buf[lexBuf.getPtr]:
560 lexGeta(); 560 lexGeta();
561 /* do the \r\n -> \n or \r -> \n translation here */ 561 /* do the \r\n -> \n or \r -> \n translation here */
562 if (c == '\r') { 562 if (c == '\r') {
563 int a = (lexBuf.len>1)? 563 int a = (lexBuf.len>1)?
564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: 564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
565 lexGeta_(1); 565 lexGeta_(1);
566 if (a == '\n') { 566 if (a == '\n') {
567 lexSkipLookahead(); 567 lexSkipLookahead();
568 } 568 }
569 lexBuf.buf[lexBuf.getPtr] = c = '\n'; 569 lexBuf.buf[lexBuf.getPtr] = c = '\n';
570 } 570 }
571 else if (c == '\n') { 571 else if (c == '\n') {
572 int a = (lexBuf.len>1)? 572 int a = (lexBuf.len>1)?
573 lexBuf.buf[lexBuf.getPtr+1]: 573 lexBuf.buf[lexBuf.getPtr+1]:
574 lexGeta_(1); 574 lexGeta_(1);
575 if (a == '\r') { 575 if (a == '\r') {
576 lexSkipLookahead(); 576 lexSkipLookahead();
577 } 577 }
578 lexBuf.buf[lexBuf.getPtr] = '\n'; 578 lexBuf.buf[lexBuf.getPtr] = '\n';
579 } 579 }
580 return c; 580 return c;
581 } 581 }
582 582
583static int lexGetc() { 583static int lexGetc() {
584 int c = lexLookahead(); 584 int c = lexLookahead();
585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
586 /* EOF will remain in lookahead buffer */ 586 /* EOF will remain in lookahead buffer */
587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
588 lexBuf.len--; 588 lexBuf.len--;
589 } 589 }
590 return c; 590 return c;
591 } 591 }
592 592
593static void lexSkipLookaheadWord() { 593static void lexSkipLookaheadWord() {
594 if (lexBuf.strsLen <= lexBuf.len) { 594 if (lexBuf.strsLen <= lexBuf.len) {
595 lexBuf.len -= lexBuf.strsLen; 595 lexBuf.len -= lexBuf.strsLen;
596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; 596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
597 } 597 }
598 } 598 }
599 599
600static void lexClearToken() 600static void lexClearToken()
601 { 601 {
602 lexBuf.strsLen = 0; 602 lexBuf.strsLen = 0;
603 } 603 }
604 604
605static void lexAppendc(int c) 605static void lexAppendc(int c)
606 { 606 {
607 lexBuf.strs[lexBuf.strsLen] = c; 607 lexBuf.strs[lexBuf.strsLen] = c;
608 /* append up to zero termination */ 608 /* append up to zero termination */
609 if (c == 0) return; 609 if (c == 0) return;
610 lexBuf.strsLen++; 610 lexBuf.strsLen++;
611 if (lexBuf.strsLen > lexBuf.maxToken) { 611 if (lexBuf.strsLen > lexBuf.maxToken) {
612 /* double the token string size */ 612 /* double the token string size */
613 lexBuf.maxToken <<= 1; 613 lexBuf.maxToken <<= 1;
614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); 614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
615 } 615 }
616 } 616 }
617 617
618static char* lexStr() { 618static char* lexStr() {
619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); 619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
620 } 620 }
621 621
622static void lexSkipWhite() { 622static void lexSkipWhite() {
623 int c = lexLookahead(); 623 int c = lexLookahead();
624 while (c == ' ' || c == '\t') { 624 while (c == ' ' || c == '\t') {
625 lexSkipLookahead(); 625 lexSkipLookahead();
626 c = lexLookahead(); 626 c = lexLookahead();
627 } 627 }
628 } 628 }
629 629
630static char* lexGetWord() { 630static char* lexGetWord() {
631 int c; 631 int c;
632 lexSkipWhite(); 632 lexSkipWhite();
633 lexClearToken(); 633 lexClearToken();
634 c = lexLookahead(); 634 c = lexLookahead();
635 while (c != EOF && !strchr("\t\n ;:=",c)) { 635 while (c != EOF && !strchr("\t\n ;:=",c)) {
636 lexAppendc(c); 636 lexAppendc(c);
637 lexSkipLookahead(); 637 lexSkipLookahead();
638 c = lexLookahead(); 638 c = lexLookahead();
639 } 639 }
640 lexAppendc(0); 640 lexAppendc(0);
641 return lexStr(); 641 return lexStr();
642 } 642 }
643 643
644static void lexPushLookaheadc(int c) { 644static void lexPushLookaheadc(int c) {
645 int putptr; 645 int putptr;
646 /* can't putback EOF, because it never leaves lookahead buffer */ 646 /* can't putback EOF, because it never leaves lookahead buffer */
647 if (c == EOF) return; 647 if (c == EOF) return;
648 putptr = (int)lexBuf.getPtr - 1; 648 putptr = (int)lexBuf.getPtr - 1;
649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; 649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
650 lexBuf.getPtr = putptr; 650 lexBuf.getPtr = putptr;
651 lexBuf.buf[putptr] = c; 651 lexBuf.buf[putptr] = c;
652 lexBuf.len += 1; 652 lexBuf.len += 1;
653 } 653 }
654 654
655static char* lexLookaheadWord() { 655static char* lexLookaheadWord() {
656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
657 / and thing bigger than that will stop the lookahead and return 0; 657 / and thing bigger than that will stop the lookahead and return 0;
658 / leading white spaces are not recoverable. 658 / leading white spaces are not recoverable.
659 */ 659 */
660 int c; 660 int c;
661 int len = 0; 661 int len = 0;
662 int curgetptr = 0; 662 int curgetptr = 0;
663 lexSkipWhite(); 663 lexSkipWhite();
664 lexClearToken(); 664 lexClearToken();
665 curgetptr = (int)lexBuf.getPtr;// remember! 665 curgetptr = (int)lexBuf.getPtr;// remember!
666 while (len < (MAX_LEX_LOOKAHEAD_0)) { 666 while (len < (MAX_LEX_LOOKAHEAD_0)) {
667 c = lexGetc(); 667 c = lexGetc();
668 len++; 668 len++;
669 if (c == EOF || strchr("\t\n ;:=", c)) { 669 if (c == EOF || strchr("\t\n ;:=", c)) {
670 lexAppendc(0); 670 lexAppendc(0);
671 /* restore lookahead buf. */ 671 /* restore lookahead buf. */
672 lexBuf.len += len; 672 lexBuf.len += len;
673 lexBuf.getPtr = curgetptr; 673 lexBuf.getPtr = curgetptr;
674 return lexStr(); 674 return lexStr();
675 } 675 }
676 else 676 else
677 lexAppendc(c); 677 lexAppendc(c);
678 } 678 }
679 lexBuf.len += len;/* char that has been moved to lookahead buffer */ 679 lexBuf.len += len;/* char that has been moved to lookahead buffer */
680 lexBuf.getPtr = curgetptr; 680 lexBuf.getPtr = curgetptr;
681 return 0; 681 return 0;
682 } 682 }
683 683
684#ifdef _SUPPORT_LINE_FOLDING 684#ifdef _SUPPORT_LINE_FOLDING
685static void handleMoreRFC822LineBreak(int c) { 685static void handleMoreRFC822LineBreak(int c) {
686 /* suport RFC 822 line break in cases like 686 /* suport RFC 822 line break in cases like
687 *ADR: foo; 687 *ADR: foo;
688 * morefoo; 688 * morefoo;
689 * more foo; 689 * more foo;
690 */ 690 */
691 if (c == ';') { 691 if (c == ';') {
692 int a; 692 int a;
693 lexSkipLookahead(); 693 lexSkipLookahead();
694 /* skip white spaces */ 694 /* skip white spaces */
695 a = lexLookahead(); 695 a = lexLookahead();
696 while (a == ' ' || a == '\t') { 696 while (a == ' ' || a == '\t') {
697 lexSkipLookahead(); 697 lexSkipLookahead();
698 a = lexLookahead(); 698 a = lexLookahead();
699 } 699 }
700 if (a == '\n') { 700 if (a == '\n') {
701 lexSkipLookahead(); 701 lexSkipLookahead();
702 a = lexLookahead(); 702 a = lexLookahead();
703 if (a == ' ' || a == '\t') { 703 if (a == ' ' || a == '\t') {
704 /* continuation, throw away all the \n and spaces read so 704 /* continuation, throw away all the \n and spaces read so
705 * far 705 * far
706 */ 706 */
707 lexSkipWhite(); 707 lexSkipWhite();
708 lexPushLookaheadc(';'); 708 lexPushLookaheadc(';');
709 } 709 }
710 else { 710 else {
711 lexPushLookaheadc('\n'); 711 lexPushLookaheadc('\n');
712 lexPushLookaheadc(';'); 712 lexPushLookaheadc(';');
713 } 713 }
714 } 714 }
715 else { 715 else {
716 lexPushLookaheadc(';'); 716 lexPushLookaheadc(';');
717 } 717 }
718 } 718 }
719 } 719 }
720 720
721static char* lexGet1Value() { 721static char* lexGet1Value() {
722 int c; 722 int c;
723 lexSkipWhite(); 723 lexSkipWhite();
724 c = lexLookahead(); 724 c = lexLookahead();
725 lexClearToken(); 725 lexClearToken();
726 while (c != EOF && c != ';') { 726 while (c != EOF && c != ';') {
727 if (c == '\\' ) { 727 if (c == '\\' ) {
728 int a; 728 int a;
729 lexSkipLookahead(); 729 lexSkipLookahead();
730 a = lexLookahead(); 730 a = lexLookahead();
731 if ( a != ';' ) { 731 if ( a != ';' ) {
732 lexAppendc('\\'); 732 lexAppendc('\\');
733 } else { 733 } else {
734 lexAppendc( ';' ); 734 lexAppendc( ';' );
735 lexSkipLookahead(); 735 lexSkipLookahead();
736 } 736 }
737 } else if (c == '\n') { 737 } else if (c == '\n') {
738 int a; 738 int a;
739 lexSkipLookahead(); 739 lexSkipLookahead();
740 a = lexLookahead(); 740 a = lexLookahead();
741 if (a == ' ' || a == '\t') { 741 if (a == ' ' || a == '\t') {
742 lexAppendc(' '); 742 lexAppendc(' ');
743 lexSkipLookahead(); 743 lexSkipLookahead();
744 } 744 }
745 else { 745 else {
746 lexPushLookaheadc('\n'); 746 lexPushLookaheadc('\n');
747 break; 747 break;
748 } 748 }
749 } 749 }
750 else { 750 else {
751 lexAppendc(c); 751 lexAppendc(c);
752 lexSkipLookahead(); 752 lexSkipLookahead();
753 } 753 }
754 c = lexLookahead(); 754 c = lexLookahead();
755 } 755 }
756 lexAppendc(0); 756 lexAppendc(0);
757 handleMoreRFC822LineBreak(c); 757 handleMoreRFC822LineBreak(c);
758 return c==EOF?0:lexStr(); 758 return c==EOF?0:lexStr();
759 } 759 }
760#endif 760#endif
761 761
762static int match_begin_name(int end) { 762static int match_begin_name(int end) {
763 char *n = lexLookaheadWord(); 763 char *n = lexLookaheadWord();
764 int token = ID; 764 int token = ID;
765 if (n) { 765 if (n) {
766 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; 766 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
767 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; 767 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
768 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; 768 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
769 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; 769 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
770 deleteStr(n); 770 deleteStr(n);
771 return token; 771 return token;
772 } 772 }
773 return 0; 773 return 0;
774 } 774 }
775 775
776 776
777#ifdef INCLUDEMFC 777#ifdef INCLUDEMFC
778void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile) 778void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
779#else 779#else
780void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) 780void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
781#endif 781#endif
782 { 782 {
783 // initialize lex mode stack 783 // initialize lex mode stack
784 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; 784 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
785 785
786 // iniatialize lex buffer. 786 // iniatialize lex buffer.
787 lexBuf.inputString = (char*) inputstring; 787 lexBuf.inputString = (char*) inputstring;
788 lexBuf.inputLen = inputlen; 788 lexBuf.inputLen = inputlen;
789 lexBuf.curPos = 0; 789 lexBuf.curPos = 0;
790 lexBuf.inputFile = inputfile; 790 lexBuf.inputFile = inputfile;
791 791
792 lexBuf.len = 0; 792 lexBuf.len = 0;
793 lexBuf.getPtr = 0; 793 lexBuf.getPtr = 0;
794 794
795 lexBuf.maxToken = MAXTOKEN; 795 lexBuf.maxToken = MAXTOKEN;
796 lexBuf.strs = (char*)malloc(MAXTOKEN); 796 lexBuf.strs = (char*)malloc(MAXTOKEN);
797 lexBuf.strsLen = 0; 797 lexBuf.strsLen = 0;
798 798
799 } 799 }
800 800
801static void finiLex() { 801static void finiLex() {
802 free(lexBuf.strs); 802 free(lexBuf.strs);
803 } 803 }
804 804
805 805
806/*-----------------------------------*/ 806/*-----------------------------------*/
807/* This parses and converts the base64 format for binary encoding into 807/* This parses and converts the base64 format for binary encoding into
808 * a decoded buffer (allocated with new). See RFC 1521. 808 * a decoded buffer (allocated with new). See RFC 1521.
809 */ 809 */
810static char * lexGetDataFromBase64() 810static char * lexGetDataFromBase64()
811 { 811 {
812 unsigned long bytesLen = 0, bytesMax = 0; 812 unsigned long bytesLen = 0, bytesMax = 0;
813 int quadIx = 0, pad = 0; 813 int quadIx = 0, pad = 0;
814 unsigned long trip = 0; 814 unsigned long trip = 0;
815 unsigned char b; 815 unsigned char b;
816 int c; 816 int c;
817 unsigned char *bytes = NULL; 817 unsigned char *bytes = NULL;
818 unsigned char *oldBytes = NULL; 818 unsigned char *oldBytes = NULL;
819 819
820 DBG_(("db: lexGetDataFromBase64\n")); 820 DBG_(("db: lexGetDataFromBase64\n"));
821 while (1) { 821 while (1) {
822 c = lexGetc(); 822 c = lexGetc();
823 if (c == '\n') { 823 if (c == '\n') {
824 ++mime_lineNum; 824 ++mime_lineNum;
825 if (lexLookahead() == '\n') { 825 if (lexLookahead() == '\n') {
826 /* a '\n' character by itself means end of data */ 826 /* a '\n' character by itself means end of data */
827 break; 827 break;
828 } 828 }
829 else continue; /* ignore '\n' */ 829 else continue; /* ignore '\n' */
830 } 830 }
831 else { 831 else {
832 if ((c >= 'A') && (c <= 'Z')) 832 if ((c >= 'A') && (c <= 'Z'))
833 b = (unsigned char)(c - 'A'); 833 b = (unsigned char)(c - 'A');
834 else if ((c >= 'a') && (c <= 'z')) 834 else if ((c >= 'a') && (c <= 'z'))
835 b = (unsigned char)(c - 'a') + 26; 835 b = (unsigned char)(c - 'a') + 26;
836 else if ((c >= '0') && (c <= '9')) 836 else if ((c >= '0') && (c <= '9'))
837 b = (unsigned char)(c - '0') + 52; 837 b = (unsigned char)(c - '0') + 52;
838 else if (c == '+') 838 else if (c == '+')
839 b = 62; 839 b = 62;
840 else if (c == '/') 840 else if (c == '/')
841 b = 63; 841 b = 63;
842 else if (c == '=') { 842 else if (c == '=') {
843 b = 0; 843 b = 0;
844 pad++; 844 pad++;
845 } else if ((c == ' ') || (c == '\t')) { 845 } else if ((c == ' ') || (c == '\t')) {
846 continue; 846 continue;
847 } else { /* error condition */ 847 } else { /* error condition */
848 if (bytes) free(bytes); 848 if (bytes) free(bytes);
849 else if (oldBytes) free(oldBytes); 849 else if (oldBytes) free(oldBytes);
850 // error recovery: skip until 2 adjacent newlines. 850 // error recovery: skip until 2 adjacent newlines.
851 DBG_(("db: invalid character 0x%x '%c'\n", c,c)); 851 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
852 if (c != EOF) { 852 if (c != EOF) {
853 c = lexGetc(); 853 c = lexGetc();
854 while (c != EOF) { 854 while (c != EOF) {
855 if (c == '\n' && lexLookahead() == '\n') { 855 if (c == '\n' && lexLookahead() == '\n') {
856 ++mime_lineNum; 856 ++mime_lineNum;
857 break; 857 break;
858 } 858 }
859 c = lexGetc(); 859 c = lexGetc();
860 } 860 }
861 } 861 }
862 return NULL; 862 return NULL;
863 } 863 }
864 trip = (trip << 6) | b; 864 trip = (trip << 6) | b;
865 if (++quadIx == 4) { 865 if (++quadIx == 4) {
866 unsigned char outBytes[3]; 866 unsigned char outBytes[3];
867 int numOut; 867 int numOut;
868 int i; 868 int i;
869 for (i = 0; i < 3; i++) { 869 for (i = 0; i < 3; i++) {
870 outBytes[2-i] = (unsigned char)(trip & 0xFF); 870 outBytes[2-i] = (unsigned char)(trip & 0xFF);
871 trip >>= 8; 871 trip >>= 8;
872 } 872 }
873 numOut = 3 - pad; 873 numOut = 3 - pad;
874 if (bytesLen + numOut > bytesMax) { 874 if (bytesLen + numOut > bytesMax) {
875 if (!bytes) { 875 if (!bytes) {
876 bytesMax = 1024; 876 bytesMax = 1024;
877 bytes = (unsigned char*)malloc((size_t)bytesMax); 877 bytes = (unsigned char*)malloc((size_t)bytesMax);
878 } 878 }
879 else { 879 else {
880 bytesMax <<= 2; 880 bytesMax <<= 2;
881 oldBytes = bytes; 881 oldBytes = bytes;
882 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); 882 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
883 } 883 }
884 if (bytes == 0) { 884 if (bytes == 0) {
885 mime_error("out of memory while processing BASE64 data\n"); 885 mime_error("out of memory while processing BASE64 data\n");
886 } 886 }
887 } 887 }
888 if (bytes) { 888 if (bytes) {
889 memcpy(bytes + bytesLen, outBytes, numOut); 889 memcpy(bytes + bytesLen, outBytes, numOut);
890 bytesLen += numOut; 890 bytesLen += numOut;
891 } 891 }
892 trip = 0; 892 trip = 0;
893 quadIx = 0; 893 quadIx = 0;
894 } 894 }
895 } 895 }
896 } /* while */ 896 } /* while */
897 DBG_(("db: bytesLen = %d\n", bytesLen)); 897 DBG_(("db: bytesLen = %d\n", bytesLen));
898 /* kludge: all this won't be necessary if we have tree form 898 /* kludge: all this won't be necessary if we have tree form
899 representation */ 899 representation */
900 if (bytes) { 900 if (bytes) {
901 setValueWithSize(curProp,bytes,(unsigned int)bytesLen); 901 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
902 free(bytes); 902 free(bytes);
903 } 903 }
904 else if (oldBytes) { 904 else if (oldBytes) {
905 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); 905 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
906 free(oldBytes); 906 free(oldBytes);
907 } 907 }
908 return 0; 908 return 0;
909 } 909 }
910 910
911static int match_begin_end_name(int end) { 911static int match_begin_end_name(int end) {
912 int token; 912 int token;
913 lexSkipWhite(); 913 lexSkipWhite();
914 if (lexLookahead() != ':') return ID; 914 if (lexLookahead() != ':') return ID;
915 lexSkipLookahead(); 915 lexSkipLookahead();
916 lexSkipWhite(); 916 lexSkipWhite();
917 token = match_begin_name(end); 917 token = match_begin_name(end);
918 if (token == ID) { 918 if (token == ID) {
919 lexPushLookaheadc(':'); 919 lexPushLookaheadc(':');
920 DBG_(("db: ID '%s'\n", yylval.str)); 920 DBG_(("db: ID '%s'\n", yylval.str));
921 return ID; 921 return ID;
922 } 922 }
923 else if (token != 0) { 923 else if (token != 0) {
924 lexSkipLookaheadWord(); 924 lexSkipLookaheadWord();
925 deleteStr(yylval.str); 925 deleteStr(yylval.str);
926 DBG_(("db: begin/end %d\n", token)); 926 DBG_(("db: begin/end %d\n", token));
927 return token; 927 return token;
928 } 928 }
929 return 0; 929 return 0;
930 } 930 }
931 931
932static char* lexGetQuotedPrintable() 932static char* lexGetQuotedPrintable()
933 { 933{
934 char cur; 934 int c;
935 935 lexSkipWhite();
936 lexClearToken(); 936 c = lexLookahead();
937 do { 937 lexClearToken();
938 cur = lexGetc(); 938
939 switch (cur) { 939 while (c != EOF && c != ';') {
940 case '=': { 940 if (c == '\n') {
941 int c = 0; 941 // break, leave '\n' on remaining chars.
942 int next[2]; 942 break;
943 int i; 943 } else if (c == '=') {
944 for (i = 0; i < 2; i++) { 944 int cur = 0;
945 next[i] = lexGetc(); 945 int next;
946 if (next[i] >= '0' && next[i] <= '9') 946
947 c = c * 16 + next[i] - '0'; 947 lexSkipLookahead(); // skip '='
948 else if (next[i] >= 'A' && next[i] <= 'F') 948 next = lexLookahead();
949 c = c * 16 + next[i] - 'A' + 10; 949
950 else 950 if (next == '\n') {
951 break; 951 // skip and only skip the \n
952 } 952 lexSkipLookahead();
953 if (i == 0) { 953 c = lexLookahead();
954 /* single '=' follow by LINESEP is continuation sign? */ 954 ++mime_lineNum; // aid in error reporting
955 if (next[0] == '\n') { 955 continue;
956 ++mime_lineNum; 956 } else if (next >= '0' && next <= '9') {
957 } 957 cur = next - '0';
958 else { 958 } else if (next >= 'A' && next <= 'F') {
959 lexPushLookaheadc('='); 959 cur = next - 'A' + 10;
960 goto EndString; 960 } else {
961 } 961 // we have been sent buggy stuff. doesn't matter
962 } 962 // what we do so long as we keep going.
963 else if (i == 1) { 963 // should probably spit an error here
964 lexPushLookaheadc(next[1]); 964 c = lexLookahead();
965 lexPushLookaheadc(next[0]); 965 continue;
966 lexAppendc('='); 966 }
967 } else { 967
968 lexAppendc(c); 968 lexSkipLookahead(); // skip A-Z0-9
969 } 969 next = lexLookahead();
970 break; 970
971 } /* '=' */ 971 cur = cur * 16;
972 case '\n': { 972 // this time really just expecting 0-9A-F
973 lexPushLookaheadc('\n'); 973 if (next >= '0' && next <= '9') {
974 goto EndString; 974 cur += next - '0';
975 } 975 } else if (next >= 'A' && next <= 'F') {
976 case (char)EOF: 976 cur += next - 'A' + 10;
977 break; 977 } else {
978 default: 978 // we have been sent buggy stuff. doesn't matter
979 lexAppendc(cur); 979 // what we do so long as we keep going.
980 break; 980 // should probably spit an error here
981 } /* switch */ 981 c = lexLookahead();
982 } while (cur != (char)EOF); 982 continue;
983 983 }
984EndString: 984
985 lexAppendc(0); 985 // got a valid escaped =. append it.
986 return lexStr(); 986 lexSkipLookahead(); // skip second 0-9A-F
987 } /* LexQuotedPrintable */ 987 lexAppendc(cur);
988 988 } else {
989static int yylex() { 989 lexSkipLookahead(); // skip whatever we just read.
990 990 lexAppendc(c); // and append it.
991 int lexmode = LEXMODE(); 991 }
992 if (lexmode == L_VALUES) { 992 c = lexLookahead();
993 int c = lexGetc(); 993 }
994 if (c == ';') { 994 lexAppendc(0);
995 DBG_(("db: SEMICOLON\n")); 995 return c==EOF?0:lexStr();
996 lexPushLookaheadc(c); 996}
997 handleMoreRFC822LineBreak(c); 997
998 lexSkipLookahead(); 998static int yylex() {
999 return SEMICOLON; 999
1000 } 1000 int lexmode = LEXMODE();
1001 else if (strchr("\n",c)) { 1001 if (lexmode == L_VALUES) {
1002 ++mime_lineNum; 1002 int c = lexGetc();
1003 /* consume all line separator(s) adjacent to each other */ 1003 if (c == ';') {
1004 c = lexLookahead(); 1004 DBG_(("db: SEMICOLON\n"));
1005 while (strchr("\n",c)) { 1005 lexPushLookaheadc(c);
1006 lexSkipLookahead(); 1006 handleMoreRFC822LineBreak(c);
1007 c = lexLookahead(); 1007 lexSkipLookahead();
1008 ++mime_lineNum; 1008 return SEMICOLON;
1009 } 1009 }
1010 DBG_(("db: LINESEP\n")); 1010 else if (strchr("\n",c)) {
1011 return LINESEP; 1011 ++mime_lineNum;
1012 } 1012 /* consume all line separator(s) adjacent to each other */
1013 else { 1013 c = lexLookahead();
1014 char *p = 0; 1014 while (strchr("\n",c)) {
1015 lexPushLookaheadc(c); 1015 lexSkipLookahead();
1016 if (lexWithinMode(L_BASE64)) { 1016 c = lexLookahead();
1017 /* get each char and convert to bin on the fly... */ 1017 ++mime_lineNum;
1018 p = lexGetDataFromBase64(); 1018 }
1019 yylval.str = p; 1019 DBG_(("db: LINESEP\n"));
1020 return STRING; 1020 return LINESEP;
1021 } 1021 }
1022 else if (lexWithinMode(L_QUOTED_PRINTABLE)) { 1022 else {
1023 p = lexGetQuotedPrintable(); 1023 char *p = 0;
1024 } 1024 lexPushLookaheadc(c);
1025 else { 1025 if (lexWithinMode(L_BASE64)) {
1026#ifdef _SUPPORT_LINE_FOLDING 1026 /* get each char and convert to bin on the fly... */
1027 p = lexGet1Value(); 1027 p = lexGetDataFromBase64();
1028#else 1028 yylval.str = p;
1029 p = lexGetStrUntil(";\n"); 1029 return STRING;
1030#endif 1030 }
1031 } 1031 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1032 if (p) { 1032 p = lexGetQuotedPrintable();
1033 DBG_(("db: STRING: '%s'\n", p)); 1033 }
1034 yylval.str = p; 1034 else {
1035 return STRING; 1035#ifdef _SUPPORT_LINE_FOLDING
1036 } 1036 p = lexGet1Value();
1037 else return 0; 1037#else
1038 } 1038 p = lexGetStrUntil(";\n");
1039 } 1039#endif
1040 else { 1040 }
1041 /* normal mode */ 1041 if (p) {
1042 while (1) { 1042 DBG_(("db: STRING: '%s'\n", p));
1043 int c = lexGetc(); 1043 yylval.str = p;
1044 switch(c) { 1044 return STRING;
1045 case ':': { 1045 }
1046 /* consume all line separator(s) adjacent to each other */ 1046 else return 0;
1047 /* ignoring linesep immediately after colon. */ 1047 }
1048 c = lexLookahead(); 1048 }
1049 while (strchr("\n",c)) { 1049 else {
1050 lexSkipLookahead(); 1050 /* normal mode */
1051 c = lexLookahead(); 1051 while (1) {
1052 ++mime_lineNum; 1052 int c = lexGetc();
1053 } 1053 switch(c) {
1054 DBG_(("db: COLON\n")); 1054 case ':': {
1055 return COLON; 1055 /* consume all line separator(s) adjacent to each other */
1056 } 1056 /* ignoring linesep immediately after colon. */
1057 case ';': 1057 c = lexLookahead();
1058 DBG_(("db: SEMICOLON\n")); 1058 while (strchr("\n",c)) {
1059 return SEMICOLON; 1059 lexSkipLookahead();
1060 case '=': 1060 c = lexLookahead();
1061 DBG_(("db: EQ\n")); 1061 ++mime_lineNum;
1062 return EQ; 1062 }
1063 /* ignore whitespace in this mode */ 1063 DBG_(("db: COLON\n"));
1064 case '\t': 1064 return COLON;
1065 case ' ': continue; 1065 }
1066 case '\n': { 1066 case ';':
1067 ++mime_lineNum; 1067 DBG_(("db: SEMICOLON\n"));
1068 continue; 1068 return SEMICOLON;
1069 } 1069 case '=':
1070 case EOF: return 0; 1070 DBG_(("db: EQ\n"));
1071 break; 1071 return EQ;
1072 default: { 1072 /* ignore whitespace in this mode */
1073 lexPushLookaheadc(c); 1073 case '\t':
1074 if (isalnum(c)) { 1074 case ' ': continue;
1075 char *t = lexGetWord(); 1075 case '\n': {
1076 yylval.str = t; 1076 ++mime_lineNum;
1077 if (!qstricmp(t, "begin")) { 1077 continue;
1078 return match_begin_end_name(0); 1078 }
1079 } 1079 case EOF: return 0;
1080 else if (!qstricmp(t,"end")) { 1080 break;
1081 return match_begin_end_name(1); 1081 default: {
1082 } 1082 lexPushLookaheadc(c);
1083 else { 1083 if (isalnum(c)) {
1084 DBG_(("db: ID '%s'\n", t)); 1084 char *t = lexGetWord();
1085 return ID; 1085 yylval.str = t;
1086 } 1086 if (!qstricmp(t, "begin")) {
1087 } 1087 return match_begin_end_name(0);
1088 else { 1088 }
1089 /* unknow token */ 1089 else if (!qstricmp(t,"end")) {
1090 return 0; 1090 return match_begin_end_name(1);
1091 } 1091 }
1092 break; 1092 else {
1093 } 1093 DBG_(("db: ID '%s'\n", t));
1094 } 1094 return ID;
1095 } 1095 }
1096 } 1096 }
1097 return 0; 1097 else {
1098 } 1098 /* unknow token */
1099 1099 return 0;
1100 1100 }
1101/***************************************************************************/ 1101 break;
1102 /*** Public Functions ****/ 1102 }
1103/***************************************************************************/ 1103 }
1104 1104 }
1105static VObject* Parse_MIMEHelper() 1105 }
1106 { 1106 return 0;
1107 ObjStackTop = -1; 1107 }
1108 mime_numErrors = 0; 1108
1109 mime_lineNum = 1; 1109
1110 vObjList = 0; 1110/***************************************************************************/
1111 curObj = 0; 1111 /*** Public Functions ****/
1112 1112/***************************************************************************/
1113 if (yyparse() != 0) 1113
1114 return 0; 1114static VObject* Parse_MIMEHelper()
1115 1115 {
1116 finiLex(); 1116 ObjStackTop = -1;
1117 return vObjList; 1117 mime_numErrors = 0;
1118 } 1118 mime_lineNum = 1;
1119 1119 vObjList = 0;
1120/*--------------------------------------------*/ 1120 curObj = 0;
1121DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) 1121
1122 { 1122 if (yyparse() != 0)
1123 initLex(input, len, 0); 1123 return 0;
1124 return Parse_MIMEHelper(); 1124
1125 } 1125 finiLex();
1126 1126 return vObjList;
1127 1127 }
1128#if INCLUDEMFC 1128
1129 1129/*--------------------------------------------*/
1130DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file) 1130DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
1131 { 1131 {
1132 unsigned long startPos; 1132 initLex(input, len, 0);
1133 VObject *result; 1133 return Parse_MIMEHelper();
1134 1134 }
1135 initLex(0,-1,file); 1135
1136 startPos = file->GetPosition(); 1136
1137 if (!(result = Parse_MIMEHelper())) 1137#if INCLUDEMFC
1138 file->Seek(startPos, CFile::begin); 1138
1139 return result; 1139DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
1140 } 1140 {
1141 1141 unsigned long startPos;
1142#else 1142 VObject *result;
1143 1143
1144VObject* Parse_MIME_FromFile(FILE *file) 1144 initLex(0,-1,file);
1145 { 1145 startPos = file->GetPosition();
1146 VObject *result; 1146 if (!(result = Parse_MIMEHelper()))
1147 long startPos; 1147 file->Seek(startPos, CFile::begin);
1148 1148 return result;
1149 initLex(0,(unsigned long)-1,file); 1149 }
1150 startPos = ftell(file); 1150
1151 if (!(result = Parse_MIMEHelper())) { 1151#else
1152 fseek(file,startPos,SEEK_SET); 1152
1153 } 1153VObject* Parse_MIME_FromFile(FILE *file)
1154 return result; 1154 {
1155 } 1155 VObject *result;
1156 1156 long startPos;
1157DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) 1157
1158 { 1158 initLex(0,(unsigned long)-1,file);
1159 FILE *fp = fopen(fname,"r"); 1159 startPos = ftell(file);
1160 if (fp) { 1160 if (!(result = Parse_MIMEHelper())) {
1161 VObject* o = Parse_MIME_FromFile(fp); 1161 fseek(file,startPos,SEEK_SET);
1162 fclose(fp); 1162 }
1163 return o; 1163 return result;
1164 } 1164 }
1165 else { 1165
1166 char msg[80]; 1166DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
1167 sprintf(msg, "can't open file '%s' for reading\n", fname); 1167 {
1168 mime_error_(msg); 1168 FILE *fp = fopen(fname,"r");
1169 return 0; 1169 if (fp) {
1170 } 1170 VObject* o = Parse_MIME_FromFile(fp);
1171 } 1171 fclose(fp);
1172 1172 return o;
1173#endif 1173 }
1174 1174 else {
1175/*-------------------------------------*/ 1175 char msg[80];
1176 1176 sprintf(msg, "can't open file '%s' for reading\n", fname);
1177static MimeErrorHandler mimeErrorHandler; 1177 mime_error_(msg);
1178 1178 return 0;
1179DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) 1179 }
1180 { 1180 }
1181 mimeErrorHandler = me; 1181
1182 } 1182#endif
1183 1183
1184void mime_error(char *s) 1184/*-------------------------------------*/
1185 { 1185
1186 char msg[256]; 1186static MimeErrorHandler mimeErrorHandler;
1187 if (mimeErrorHandler) { 1187
1188 sprintf(msg,"%s at line %d", s, mime_lineNum); 1188DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
1189 mimeErrorHandler(msg); 1189 {
1190 } 1190 mimeErrorHandler = me;
1191 } 1191 }
1192 1192
1193void mime_error_(char *s) 1193void mime_error(char *s)
1194 { 1194 {
1195 if (mimeErrorHandler) { 1195 char msg[256];
1196 mimeErrorHandler(s); 1196 if (mimeErrorHandler) {
1197 } 1197 sprintf(msg,"%s at line %d", s, mime_lineNum);
1198 } 1198 mimeErrorHandler(msg);
1199 1199 }
1200 }
1201
1202void mime_error_(char *s)
1203 {
1204 if (mimeErrorHandler) {
1205 mimeErrorHandler(s);
1206 }
1207 }
1208