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