summaryrefslogtreecommitdiffabout
path: root/libkcal/versit
Side-by-side diff
Diffstat (limited to 'libkcal/versit') (more/less context) (show whitespace changes)
-rw-r--r--libkcal/versit/port.h75
-rw-r--r--libkcal/versit/vcc.c2162
-rw-r--r--libkcal/versit/vcc.h76
-rw-r--r--libkcal/versit/versit.pro15
-rw-r--r--libkcal/versit/versit.pro.back15
-rw-r--r--libkcal/versit/vobject.c1433
-rw-r--r--libkcal/versit/vobject.h384
7 files changed, 4160 insertions, 0 deletions
diff --git a/libkcal/versit/port.h b/libkcal/versit/port.h
new file mode 100644
index 0000000..afc16dd
--- a/dev/null
+++ b/libkcal/versit/port.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+#ifndef __PORT_H__
+#define __PORT_H__ 1
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+extern "C" {
+#endif
+
+#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
+#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
+
+/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
+are globally unique IDs which can be used to generate clipboard format
+ID's as per the requirements of a specific platform. For example, in
+Windows they are used as the parameter in a call to RegisterClipboardFormat.
+For example:
+
+ CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
+
+*/
+
+#define vCardMimeType "text/x-vCard"
+#define vCalendarMimeType "text/x-vCalendar"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define Parse_Debug(t)
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+}
+#endif
+
+#endif /* __PORT_H__ */
diff --git a/libkcal/versit/vcc.c b/libkcal/versit/vcc.c
new file mode 100644
index 0000000..350cac3
--- a/dev/null
+++ b/libkcal/versit/vcc.c
@@ -0,0 +1,2162 @@
+
+/* A Bison parser, made from ./vcc.y
+ by GNU Bison version 1.28 */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#ifdef _WIN32_
+#define strcasecmp _stricmp
+#endif
+
+#define EQ 257
+#define COLON 258
+#define DOT 259
+#define SEMICOLON 260
+#define SPACE 261
+#define HTAB 262
+#define LINESEP 263
+#define NEWLINE 264
+#define BEGIN_VCARD 265
+#define END_VCARD 266
+#define BEGIN_VCAL 267
+#define END_VCAL 268
+#define BEGIN_VEVENT 269
+#define END_VEVENT 270
+#define BEGIN_VTODO 271
+#define END_VTODO 272
+#define ID 273
+#define STRING 274
+
+#line 1 "./vcc.y"
+
+
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+ * src: vcc.c
+ * doc: Parser for vCard and vCalendar. Note that this code is
+ * generated by a yacc parser generator. Generally it should not
+ * be edited by hand. The real source is vcc.y. The #line directives
+ * can be commented out here to make it easier to trace through
+ * in a debugger. However, if a bug is found it should
+ * be fixed in vcc.y and this file regenerated.
+ */
+
+
+/* debugging utilities */
+#if __DEBUG
+#define DBG_(x) printf x
+#else
+#define DBG_(x)
+#endif
+
+/**** External Functions ****/
+
+/* assign local name to parser variables and functions so that
+ we can use more than one yacc based parser.
+*/
+
+#define yyparse mime_parse
+#define yylex mime_lex
+#define yyerror mime_error
+#define yychar mime_char
+/* #define p_yyval p_mime_val */
+#undef yyval
+#define yyval mime_yyval
+/* #define p_yylval p_mime_lval */
+#undef yylval
+#define yylval mime_yylval
+#define yydebug mime_debug
+#define yynerrs mime_nerrs
+#define yyerrflag mime_errflag
+#define yyss mime_ss
+#define yyssp mime_ssp
+#define yyvs mime_vs
+#define yyvsp mime_vsp
+#define yylhs mime_lhs
+#define yylen mime_len
+#define yydefred mime_defred
+#define yydgoto mime_dgoto
+#define yysindex mime_sindex
+#define yyrindex mime_rindex
+#define yygindex mime_gindex
+#define yytable mime_table
+#define yycheck mime_check
+#define yyname mime_name
+#define yyrule mime_rule
+#undef YYPREFIX
+#define YYPREFIX "mime_"
+
+
+#ifndef _NO_LINE_FOLDING
+#define _SUPPORT_LINE_FOLDING 1
+#endif
+
+#include <string.h>
+#ifndef __FreeBSD__
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "vcc.h"
+
+/* The following is a hack that I hope will get things compiling
+ * on SunOS 4.1.x systems
+ */
+#ifndef SEEK_SET
+#define SEEK_SET 0 /* Seek from beginning of file. */
+#define SEEK_CUR 1 /* Seek from current position. */
+#define SEEK_END 2 /* Seek from end of file. */
+#endif
+
+/**** Types, Constants ****/
+
+#define YYDEBUG 0 /* 1 to compile in some debugging code */
+#define MAXTOKEN 256 /* maximum token (line) length */
+#define YYSTACKSIZE 1000 /* ~unref ? */
+#define MAXLEVEL 10 /* max # of nested objects parseable */
+ /* (includes outermost) */
+
+
+/**** Global Variables ****/
+int mime_lineNum, mime_numErrors; /* yyerror() can use these */
+static VObject* vObjList;
+static VObject *curProp;
+static VObject *curObj;
+static VObject* ObjStack[MAXLEVEL];
+static int ObjStackTop;
+
+
+/* A helpful utility for the rest of the app. */
+#if __CPLUSPLUS__
+extern "C" {
+#endif
+
+ /* static void Parse_Debug(const char *s);*/
+ static void yyerror(char *s);
+
+#if __CPLUSPLUS__
+ };
+#endif
+
+int yyparse();
+static int yylex();
+enum LexMode {
+ L_NORMAL,
+ L_VCARD,
+ L_VCAL,
+ L_VEVENT,
+ L_VTODO,
+ L_VALUES,
+ L_BASE64,
+ L_QUOTED_PRINTABLE
+ };
+
+/**** Private Forward Declarations ****/
+static int pushVObject(const char *prop);
+static VObject* popVObject();
+char* lexDataFromBase64();
+static void lexPopMode(int top);
+static int lexWithinMode(enum LexMode mode);
+static void lexPushMode(enum LexMode mode);
+static void enterProps(const char *s);
+static void enterAttr(const char *s1, const char *s2);
+/* static void enterValues(const char *value); */
+static void appendValue(const char *value);
+static void mime_error_(char *s);
+
+
+#line 181 "./vcc.y"
+typedef union {
+ char *str;
+ VObject *vobj;
+ } YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 62
+#define YYFLAG -32768
+#define YYNTBASE 21
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 274 ? yytranslate[x] : 51)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 3, 7, 9, 11, 13, 14, 19, 20,
+ 24, 27, 29, 30, 36, 38, 39, 43, 45, 48,
+ 50, 53, 55, 59, 61, 62, 67, 69, 71, 72,
+ 73, 78, 79, 83, 86, 88, 90, 92, 94, 95,
+ 100, 101, 105, 106, 111, 112
+};
+
+static const short yyrhs[] = { 22,
+ 0, 0, 24, 23, 22, 0, 24, 0, 25, 0,
+ 40, 0, 0, 11, 26, 28, 12, 0, 0, 11,
+ 27, 12, 0, 29, 28, 0, 29, 0, 0, 31,
+ 4, 30, 37, 9, 0, 1, 0, 0, 36, 32,
+ 33, 0, 36, 0, 34, 33, 0, 34, 0, 6,
+ 35, 0, 36, 0, 36, 3, 36, 0, 19, 0,
+ 0, 39, 6, 38, 37, 0, 39, 0, 20, 0,
+ 0, 0, 13, 41, 43, 14, 0, 0, 13, 42,
+ 14, 0, 44, 43, 0, 44, 0, 45, 0, 48,
+ 0, 28, 0, 0, 15, 46, 28, 16, 0, 0,
+ 15, 47, 16, 0, 0, 17, 49, 28, 18, 0,
+ 0, 17, 50, 18, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 209, 212, 215, 215, 219, 220, 223, 229, 234, 240,
+ 246, 247, 250, 254, 260, 263, 268, 268, 274, 275,
+ 278, 281, 285, 292, 295, 296, 296, 300, 301, 305,
+ 309, 311, 314, 317, 318, 321, 323, 324, 327, 334,
+ 339, 345, 351, 358, 363, 369
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = { "$","error","$undefined.","EQ","COLON",
+"DOT","SEMICOLON","SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD",
+"BEGIN_VCAL","END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO",
+"ID","STRING","mime","vobjects","@1","vobject","vcard","@2","@3","items","item",
+"@4","prop","@5","attr_params","attr_param","attr","name","values","@6","value",
+"vcal","@7","@8","calitems","calitem","eventitem","@9","@10","todoitem","@11",
+"@12", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 21, 23, 22, 22, 24, 24, 26, 25, 27, 25,
+ 28, 28, 30, 29, 29, 32, 31, 31, 33, 33,
+ 34, 35, 35, 36, 38, 37, 37, 39, 39, 41,
+ 40, 42, 40, 43, 43, 44, 44, 44, 46, 45,
+ 47, 45, 49, 48, 50, 48
+};
+
+static const short yyr2[] = { 0,
+ 1, 0, 3, 1, 1, 1, 0, 4, 0, 3,
+ 2, 1, 0, 5, 1, 0, 3, 1, 2, 1,
+ 2, 1, 3, 1, 0, 4, 1, 1, 0, 0,
+ 4, 0, 3, 2, 1, 1, 1, 1, 0, 4,
+ 0, 3, 0, 4, 0, 3
+};
+
+static const short yydefact[] = { 0,
+ 7, 30, 1, 2, 5, 6, 0, 0, 0, 0,
+ 0, 15, 24, 0, 0, 0, 16, 10, 39, 43,
+ 38, 0, 0, 36, 37, 33, 3, 8, 11, 13,
+ 0, 0, 0, 0, 0, 31, 34, 29, 0, 17,
+ 20, 0, 42, 0, 46, 28, 0, 27, 21, 22,
+ 19, 40, 44, 14, 25, 0, 29, 23, 26, 0,
+ 0, 0
+};
+
+static const short yydefgoto[] = { 60,
+ 3, 11, 4, 5, 7, 8, 21, 15, 38, 16,
+ 31, 40, 41, 49, 17, 47, 57, 48, 6, 9,
+ 10, 22, 23, 24, 32, 33, 25, 34, 35
+};
+
+static const short yypact[] = { -9,
+ -6, -5,-32768, 7,-32768,-32768, 2, -1, 19, 15,
+ -9,-32768,-32768, 1, 0, 26, 27,-32768, 16, 17,
+-32768, 23, 9,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 33, 2, 24, 2, 25,-32768,-32768, 13, 22,-32768,
+ 33, 28,-32768, 29,-32768,-32768, 36, 40,-32768, 39,
+-32768,-32768,-32768,-32768,-32768, 22, 13,-32768,-32768, 48,
+ 49,-32768
+};
+
+static const short yypgoto[] = {-32768,
+ 41,-32768,-32768,-32768,-32768,-32768, -7,-32768,-32768,-32768,
+-32768, 10,-32768,-32768, -34, -4,-32768,-32768,-32768,-32768,
+-32768, 31,-32768,-32768,-32768,-32768,-32768,-32768,-32768
+};
+
+
+#define YYLAST 54
+
+
+static const short yytable[] = { 14,
+ 12, 1, 12, 2, 50, -9, -4, 29, -32, 12,
+ 18, -12, 28, -12, -12, -12, -12, -12, 13, 12,
+ 13, 58, -35, 19, 42, 20, 44, 13, 26, 30,
+ -18, -41, 46, 19, -45, 20, 36, 13, 39, 43,
+ 13, 56, 45, 52, 54, 55, 53, 61, 62, 0,
+ 51, 27, 59, 37
+};
+
+static const short yycheck[] = { 7,
+ 1, 11, 1, 13, 39, 12, 0, 15, 14, 1,
+ 12, 12, 12, 14, 15, 16, 17, 18, 19, 1,
+ 19, 56, 14, 15, 32, 17, 34, 19, 14, 4,
+ 4, 16, 20, 15, 18, 17, 14, 19, 6, 16,
+ 19, 3, 18, 16, 9, 6, 18, 0, 0, -1,
+ 41, 11, 57, 23
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/bison.simple"
+/* This file comes from bison-1.28. */
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
+/* #include <malloc.h> */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ unsigned int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+ register char *t = to;
+ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 217 "/usr/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes. */
+#if defined (__GNUC__) && ! defined (__cplusplus)
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 2:
+#line 213 "./vcc.y"
+{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ;
+ break;}
+case 4:
+#line 216 "./vcc.y"
+{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ;
+ break;}
+case 7:
+#line 225 "./vcc.y"
+{
+ lexPushMode(L_VCARD);
+ if (!pushVObject(VCCardProp)) YYERROR;
+ ;
+ break;}
+case 8:
+#line 230 "./vcc.y"
+{
+ lexPopMode(0);
+ yyval.vobj = popVObject();
+ ;
+ break;}
+case 9:
+#line 235 "./vcc.y"
+{
+ lexPushMode(L_VCARD);
+ if (!pushVObject(VCCardProp)) YYERROR;
+ ;
+ break;}
+case 10:
+#line 240 "./vcc.y"
+{
+ lexPopMode(0);
+ yyval.vobj = popVObject();
+ ;
+ break;}
+case 13:
+#line 251 "./vcc.y"
+{
+ lexPushMode(L_VALUES);
+ ;
+ break;}
+case 14:
+#line 255 "./vcc.y"
+{
+ if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
+ lexPopMode(0);
+ lexPopMode(0);
+ ;
+ break;}
+case 16:
+#line 264 "./vcc.y"
+{
+ enterProps(yyvsp[0].str);
+ ;
+ break;}
+case 18:
+#line 269 "./vcc.y"
+{
+ enterProps(yyvsp[0].str);
+ ;
+ break;}
+case 22:
+#line 282 "./vcc.y"
+{
+ enterAttr(yyvsp[0].str,0);
+ ;
+ break;}
+case 23:
+#line 286 "./vcc.y"
+{
+ enterAttr(yyvsp[-2].str,yyvsp[0].str);
+
+ ;
+ break;}
+case 25:
+#line 295 "./vcc.y"
+{ appendValue(yyvsp[-1].str); ;
+ break;}
+case 27:
+#line 297 "./vcc.y"
+{ appendValue(yyvsp[0].str); ;
+ break;}
+case 29:
+#line 302 "./vcc.y"
+{ yyval.str = 0; ;
+ break;}
+case 30:
+#line 307 "./vcc.y"
+{ if (!pushVObject(VCCalProp)) YYERROR; ;
+ break;}
+case 31:
+#line 310 "./vcc.y"
+{ yyval.vobj = popVObject(); ;
+ break;}
+case 32:
+#line 312 "./vcc.y"
+{ if (!pushVObject(VCCalProp)) YYERROR; ;
+ break;}
+case 33:
+#line 314 "./vcc.y"
+{ yyval.vobj = popVObject(); ;
+ break;}
+case 39:
+#line 329 "./vcc.y"
+{
+ lexPushMode(L_VEVENT);
+ if (!pushVObject(VCEventProp)) YYERROR;
+ ;
+ break;}
+case 40:
+#line 335 "./vcc.y"
+{
+ lexPopMode(0);
+ popVObject();
+ ;
+ break;}
+case 41:
+#line 340 "./vcc.y"
+{
+ lexPushMode(L_VEVENT);
+ if (!pushVObject(VCEventProp)) YYERROR;
+ ;
+ break;}
+case 42:
+#line 345 "./vcc.y"
+{
+ lexPopMode(0);
+ popVObject();
+ ;
+ break;}
+case 43:
+#line 353 "./vcc.y"
+{
+ lexPushMode(L_VTODO);
+ if (!pushVObject(VCTodoProp)) YYERROR;
+ ;
+ break;}
+case 44:
+#line 359 "./vcc.y"
+{
+ lexPopMode(0);
+ popVObject();
+ ;
+ break;}
+case 45:
+#line 364 "./vcc.y"
+{
+ lexPushMode(L_VTODO);
+ if (!pushVObject(VCTodoProp)) YYERROR;
+ ;
+ break;}
+case 46:
+#line 369 "./vcc.y"
+{
+ lexPopMode(0);
+ popVObject();
+ ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
+}
+#line 375 "./vcc.y"
+
+/****************************************************************************/
+static int pushVObject(const char *prop)
+ {
+ VObject *newObj;
+ if (ObjStackTop == MAXLEVEL)
+ return FALSE;
+
+ ObjStack[++ObjStackTop] = curObj;
+
+ if (curObj) {
+ newObj = addProp(curObj,prop);
+ curObj = newObj;
+ }
+ else
+ curObj = newVObject(prop);
+
+ return TRUE;
+ }
+
+
+/****************************************************************************/
+/* This pops the recently built vCard off the stack and returns it. */
+static VObject* popVObject()
+ {
+ VObject *oldObj;
+ if (ObjStackTop < 0) {
+ yyerror("pop on empty Object Stack\n");
+ return 0;
+ }
+ oldObj = curObj;
+ curObj = ObjStack[ObjStackTop--];
+
+ return oldObj;
+ }
+
+
+/* static void enterValues(const char *value) */
+/* { */
+/* if (fieldedProp && *fieldedProp) { */
+/* if (value) { */
+/* addPropValue(curProp,*fieldedProp,value); */
+/* } */
+ /* else this field is empty, advance to next field */
+/* fieldedProp++; */
+/* } */
+/* else { */
+/* if (value) { */
+/* setVObjectUStringZValue_(curProp,fakeUnicode(value,0)); */
+/* } */
+/* } */
+/* deleteStr(value); */
+/* } */
+
+static void appendValue(const char *value)
+{
+ char *p1, *p2;
+ wchar_t *p3;
+ int i;
+
+ if (fieldedProp && *fieldedProp) {
+ if (value) {
+ addPropValue(curProp, *fieldedProp, value);
+ }
+ /* else this field is empty, advance to next field */
+ fieldedProp++;
+ } else {
+ if (value) {
+ if (vObjectUStringZValue(curProp)) {
+ p1 = fakeCString(vObjectUStringZValue(curProp));
+ p2 = malloc(sizeof(char *) * (strlen(p1)+strlen(value)+1));
+ strcpy(p2, p1);
+ deleteStr(p1);
+
+ i = strlen(p2);
+ p2[i] = ',';
+ p2[i+1] = '\0';
+ p2 = strcat(p2, value);
+ p3 = (wchar_t *) vObjectUStringZValue(curProp);
+ free(p3);
+ setVObjectUStringZValue_(curProp,fakeUnicode(p2,0));
+ deleteStr(p2);
+ } else {
+ setVObjectUStringZValue_(curProp,fakeUnicode(value,0));
+ }
+ }
+ }
+ deleteStr(value);
+}
+
+
+static void enterProps(const char *s)
+ {
+ curProp = addGroup(curObj,s);
+ deleteStr(s);
+ }
+
+static void enterAttr(const char *s1, const char *s2)
+ {
+ const char *p1=0L, *p2=0L;
+ p1 = lookupProp_(s1);
+ if (s2) {
+ VObject *a;
+ p2 = lookupProp_(s2);
+ a = addProp(curProp,p1);
+ setVObjectStringZValue(a,p2);
+ }
+ else
+ addProp(curProp,p1);
+ if (strcasecmp(p1,VCBase64Prop) == 0 || (s2 && strcasecmp(p2,VCBase64Prop)==0))
+ lexPushMode(L_BASE64);
+ else if (strcasecmp(p1,VCQuotedPrintableProp) == 0
+ || (s2 && strcasecmp(p2,VCQuotedPrintableProp)==0))
+ lexPushMode(L_QUOTED_PRINTABLE);
+ deleteStr(s1); deleteStr(s2);
+ }
+
+
+#define MAX_LEX_LOOKAHEAD_0 32
+#define MAX_LEX_LOOKAHEAD 64
+#define MAX_LEX_MODE_STACK_SIZE 10
+#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
+
+struct LexBuf {
+ /* input */
+ FILE *inputFile;
+ char *inputString;
+ unsigned long curPos;
+ unsigned long inputLen;
+ /* lookahead buffer */
+ /* -- lookahead buffer is short instead of char so that EOF
+ / can be represented correctly.
+ */
+ unsigned long len;
+ short buf[MAX_LEX_LOOKAHEAD];
+ unsigned long getPtr;
+ /* context stack */
+ unsigned long lexModeStackTop;
+ enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
+ /* token buffer */
+ unsigned long maxToken;
+ char *strs;
+ unsigned long strsLen;
+ } lexBuf;
+
+static void lexPushMode(enum LexMode mode)
+ {
+ if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
+ yyerror("lexical context stack overflow");
+ else {
+ lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
+ }
+ }
+
+static void lexPopMode(int top)
+ {
+ /* special case of pop for ease of error recovery -- this
+ version will never underflow */
+ if (top)
+ lexBuf.lexModeStackTop = 0;
+ else
+ if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
+ }
+
+static int lexWithinMode(enum LexMode mode) {
+ unsigned long i;
+ for (i=0;i<lexBuf.lexModeStackTop;i++)
+ if (mode == lexBuf.lexModeStack[i]) return 1;
+ return 0;
+ }
+
+static int lexGetc_()
+ {
+ /* get next char from input, no buffering. */
+ if (lexBuf.curPos == lexBuf.inputLen)
+ return EOF;
+ else if (lexBuf.inputString)
+ return *(lexBuf.inputString + lexBuf.curPos++);
+ else {
+ if (!feof(lexBuf.inputFile))
+ return fgetc(lexBuf.inputFile);
+ else
+ return EOF;
+ }
+ }
+
+static int lexGeta()
+ {
+ ++lexBuf.len;
+ return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
+ }
+
+static int lexGeta_(int i)
+ {
+ ++lexBuf.len;
+ return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
+ }
+
+static void lexSkipLookahead() {
+ if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
+ /* don't skip EOF. */
+ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
+ lexBuf.len--;
+ }
+ }
+
+static int lexLookahead() {
+ int c = (lexBuf.len)?
+ lexBuf.buf[lexBuf.getPtr]:
+ lexGeta();
+ /* do the \r\n -> \n or \r -> \n translation here */
+ if (c == '\r') {
+ int a = (lexBuf.len>1)?
+ lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
+ lexGeta_(1);
+ if (a == '\n') {
+ lexSkipLookahead();
+ }
+ lexBuf.buf[lexBuf.getPtr] = c = '\n';
+ }
+ else if (c == '\n') {
+ int a;
+ if (lexBuf.len > 1)
+ a = lexBuf.buf[lexBuf.getPtr];
+ else
+ a = lexGeta_(1);
+ if (a == '\r') {
+ lexSkipLookahead();
+ }
+ lexBuf.buf[lexBuf.getPtr] = '\n';
+ }
+ return c;
+ }
+
+static int lexGetc() {
+ int c = lexLookahead();
+ if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
+ /* EOF will remain in lookahead buffer */
+ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
+ lexBuf.len--;
+ }
+ return c;
+ }
+
+static void lexSkipLookaheadWord() {
+ if (lexBuf.strsLen <= lexBuf.len) {
+ lexBuf.len -= lexBuf.strsLen;
+ lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
+ }
+ }
+
+static void lexClearToken()
+ {
+ lexBuf.strsLen = 0;
+ }
+
+static void lexAppendc(int c)
+ {
+ /* not sure if I am doing this right to fix purify report -- PGB */
+ lexBuf.strs = (char *) realloc(lexBuf.strs, (size_t) lexBuf.strsLen + 1);
+ lexBuf.strs[lexBuf.strsLen] = c;
+ /* append up to zero termination */
+ if (c == 0) return;
+ lexBuf.strsLen++;
+ if (lexBuf.strsLen > lexBuf.maxToken) {
+ /* double the token string size */
+ lexBuf.maxToken <<= 1;
+ lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
+ }
+ }
+
+static char* lexStr() {
+ return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
+ }
+
+static void lexSkipWhite() {
+ int c = lexLookahead();
+ while (c == ' ' || c == '\t') {
+ lexSkipLookahead();
+ c = lexLookahead();
+ }
+ }
+
+static char* lexGetWord() {
+ int c;
+ lexSkipWhite();
+ lexClearToken();
+ c = lexLookahead();
+ /* some "words" have a space in them, like "NEEDS ACTION".
+ this may be an oversight of the spec, but it is true nevertheless.
+ while (c != EOF && !strchr("\t\n ;:=",c)) { */
+ while (c != EOF && !strchr("\n;:=",c)) {
+ lexAppendc(c);
+ lexSkipLookahead();
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ return lexStr();
+ }
+
+void lexPushLookahead(char *s, int len) {
+ int putptr;
+ if (len == 0) len = strlen(s);
+ putptr = (int)lexBuf.getPtr - len;
+ /* this function assumes that length of word to push back
+ / is not greater than MAX_LEX_LOOKAHEAD.
+ */
+ if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
+ lexBuf.getPtr = putptr;
+ while (*s) {
+ lexBuf.buf[putptr] = *s++;
+ putptr = (putptr + 1) % MAX_LEX_LOOKAHEAD;
+ }
+ lexBuf.len += len;
+ }
+
+static void lexPushLookaheadc(int c) {
+ int putptr;
+ /* can't putback EOF, because it never leaves lookahead buffer */
+ if (c == EOF) return;
+ putptr = (int)lexBuf.getPtr - 1;
+ if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
+ lexBuf.getPtr = putptr;
+ lexBuf.buf[putptr] = c;
+ lexBuf.len += 1;
+ }
+
+static char* lexLookaheadWord() {
+ /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
+ / and thing bigger than that will stop the lookahead and return 0;
+ / leading white spaces are not recoverable.
+ */
+ int c;
+ int len = 0;
+ int curgetptr = 0;
+ lexSkipWhite();
+ lexClearToken();
+ curgetptr = (int)lexBuf.getPtr; /* remember! */
+ while (len < (MAX_LEX_LOOKAHEAD_0)) {
+ c = lexGetc();
+ len++;
+ if (c == EOF || strchr("\t\n ;:=", c)) {
+ lexAppendc(0);
+ /* restore lookahead buf. */
+ lexBuf.len += len;
+ lexBuf.getPtr = curgetptr;
+ return lexStr();
+ }
+ else
+ lexAppendc(c);
+ }
+ lexBuf.len += len; /* char that has been moved to lookahead buffer */
+ lexBuf.getPtr = curgetptr;
+ return 0;
+ }
+
+#ifdef _SUPPORT_LINE_FOLDING
+static void handleMoreRFC822LineBreak(int c) {
+ /* suport RFC 822 line break in cases like
+ * ADR: foo;
+ * morefoo;
+ * more foo;
+ */
+ if (c == ';') {
+ int a;
+ lexSkipLookahead();
+ /* skip white spaces */
+ a = lexLookahead();
+ while (a == ' ' || a == '\t') {
+ lexSkipLookahead();
+ a = lexLookahead();
+ }
+ if (a == '\n') {
+ lexSkipLookahead();
+ a = lexLookahead();
+ if (a == ' ' || a == '\t') {
+ /* continuation, throw away all the \n and spaces read so
+ * far
+ */
+ lexSkipWhite();
+ lexPushLookaheadc(';');
+ }
+ else {
+ lexPushLookaheadc('\n');
+ lexPushLookaheadc(';');
+ }
+ }
+ else {
+ lexPushLookaheadc(';');
+ }
+ }
+ }
+
+static char* lexGet1Value() {
+ int c;
+ lexSkipWhite();
+ c = lexLookahead();
+ lexClearToken();
+ while (c != EOF && c != ';') {
+ if (c == '\n') {
+ int a;
+ lexSkipLookahead();
+ a = lexLookahead();
+ if (a == ' ' || a == '\t') {
+ lexAppendc(' ');
+ lexSkipLookahead();
+ }
+ else {
+ lexPushLookaheadc('\n');
+ break;
+ }
+ }
+ else {
+ lexAppendc(c);
+ lexSkipLookahead();
+ }
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ handleMoreRFC822LineBreak(c);
+ return c==EOF?0:lexStr();
+ }
+#endif
+
+char* lexGetStrUntil(char *termset) {
+ int c = lexLookahead();
+ lexClearToken();
+ while (c != EOF && !strchr(termset,c)) {
+ lexAppendc(c);
+ lexSkipLookahead();
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ return c==EOF?0:lexStr();
+ }
+
+static int match_begin_name(int end) {
+ char *n = lexLookaheadWord();
+ int token = ID;
+ if (n) {
+ if (!strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
+ else if (!strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
+ else if (!strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
+ else if (!strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
+ deleteStr(n);
+ return token;
+ }
+ return 0;
+ }
+
+
+void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
+ {
+ /* initialize lex mode stack */
+ lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
+
+ /* iniatialize lex buffer. */
+ lexBuf.inputString = (char*) inputstring;
+ lexBuf.inputLen = inputlen;
+ lexBuf.curPos = 0;
+ lexBuf.inputFile = inputfile;
+
+ lexBuf.len = 0;
+ lexBuf.getPtr = 0;
+
+ lexBuf.maxToken = MAXTOKEN;
+ lexBuf.strs = (char*)malloc(MAXTOKEN);
+ lexBuf.strsLen = 0;
+
+ }
+
+static void finiLex() {
+ free(lexBuf.strs);
+ }
+
+
+/****************************************************************************/
+/* This parses and converts the base64 format for binary encoding into
+ * a decoded buffer (allocated with new). See RFC 1521.
+ */
+static char * lexGetDataFromBase64()
+ {
+ unsigned long bytesLen = 0, bytesMax = 0;
+ int quadIx = 0, pad = 0;
+ unsigned long trip = 0;
+ unsigned char b;
+ int c;
+ unsigned char *bytes = NULL;
+ unsigned char *oldBytes = NULL;
+
+ DBG_(("db: lexGetDataFromBase64\n"));
+ while (1) {
+ c = lexGetc();
+ if (c == '\n') {
+ ++mime_lineNum;
+ if (lexLookahead() == '\n') {
+ /* a '\n' character by itself means end of data */
+ break;
+ }
+ else continue; /* ignore '\n' */
+ }
+ else {
+ if ((c >= 'A') && (c <= 'Z'))
+ b = (unsigned char)(c - 'A');
+ else if ((c >= 'a') && (c <= 'z'))
+ b = (unsigned char)(c - 'a') + 26;
+ else if ((c >= '0') && (c <= '9'))
+ b = (unsigned char)(c - '0') + 52;
+ else if (c == '+')
+ b = 62;
+ else if (c == '/')
+ b = 63;
+ else if (c == '=') {
+ b = 0;
+ pad++;
+ } else if ((c == ' ') || (c == '\t')) {
+ continue;
+ } else { /* error condition */
+ if (bytes) free(bytes);
+ else if (oldBytes) free(oldBytes);
+ /* error recovery: skip until 2 adjacent newlines. */
+ DBG_(("db: invalid character 0x%x '%c'\n", c,c));
+ if (c != EOF) {
+ c = lexGetc();
+ while (c != EOF) {
+ if (c == '\n' && lexLookahead() == '\n') {
+ ++mime_lineNum;
+ break;
+ }
+ c = lexGetc();
+ }
+ }
+ return NULL;
+ }
+ trip = (trip << 6) | b;
+ if (++quadIx == 4) {
+ unsigned char outBytes[3];
+ int numOut;
+ int i;
+ for (i = 0; i < 3; i++) {
+ outBytes[2-i] = (unsigned char)(trip & 0xFF);
+ trip >>= 8;
+ }
+ numOut = 3 - pad;
+ if (bytesLen + numOut > bytesMax) {
+ if (!bytes) {
+ bytesMax = 1024;
+ bytes = (unsigned char*)malloc((size_t)bytesMax);
+ }
+ else {
+ bytesMax <<= 2;
+ oldBytes = bytes;
+ bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
+ }
+ if (bytes == 0) {
+ mime_error("out of memory while processing BASE64 data\n");
+ }
+ }
+ if (bytes) {
+ memcpy(bytes + bytesLen, outBytes, numOut);
+ bytesLen += numOut;
+ }
+ trip = 0;
+ quadIx = 0;
+ }
+ }
+ } /* while */
+ DBG_(("db: bytesLen = %d\n", bytesLen));
+ /* kludge: all this won't be necessary if we have tree form
+ representation */
+ if (bytes) {
+ setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
+ free(bytes);
+ }
+ else if (oldBytes) {
+ setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
+ free(oldBytes);
+ }
+ return 0;
+ }
+
+static int match_begin_end_name(int end) {
+ int token;
+ lexSkipWhite();
+ if (lexLookahead() != ':') return ID;
+ lexSkipLookahead();
+ lexSkipWhite();
+ token = match_begin_name(end);
+ if (token == ID) {
+ lexPushLookaheadc(':');
+ DBG_(("db: ID '%s'\n", yylval.str));
+ return ID;
+ }
+ else if (token != 0) {
+ lexSkipLookaheadWord();
+ deleteStr(yylval.str);
+ DBG_(("db: begin/end %d\n", token));
+ return token;
+ }
+ return 0;
+ }
+
+static char* lexGetQuotedPrintable()
+ {
+ char cur;
+
+ lexClearToken();
+ do {
+ cur = lexGetc();
+ switch (cur) {
+ case '=': {
+ int c = 0;
+ int next[2];
+ int i;
+ for (i = 0; i < 2; i++) {
+ next[i] = lexGetc();
+ if (next[i] >= '0' && next[i] <= '9')
+ c = c * 16 + next[i] - '0';
+ else if (next[i] >= 'A' && next[i] <= 'F')
+ c = c * 16 + next[i] - 'A' + 10;
+ else
+ break;
+ }
+ if (i == 0) {
+ /* single '=' follow by LINESEP is continuation sign? */
+ if (next[0] == '\n') {
+ ++mime_lineNum;
+ }
+ else {
+ lexPushLookaheadc('=');
+ goto EndString;
+ }
+ }
+ else if (i == 1) {
+ lexPushLookaheadc(next[1]);
+ lexPushLookaheadc(next[0]);
+ lexAppendc('=');
+ } else {
+ lexAppendc(c);
+ }
+ break;
+ } /* '=' */
+ case '\n': {
+ lexPushLookaheadc('\n');
+ goto EndString;
+ }
+ case (char)EOF:
+ break;
+ default:
+ lexAppendc(cur);
+ break;
+ } /* switch */
+ } while (cur != (char)EOF);
+
+EndString:
+ lexAppendc(0);
+ return lexStr();
+ } /* LexQuotedPrintable */
+
+static int yylex() {
+
+ int lexmode = LEXMODE();
+ if (lexmode == L_VALUES) {
+ int c = lexGetc();
+ if (c == ';') {
+ DBG_(("db: SEMICOLON\n"));
+ lexPushLookaheadc(c);
+ handleMoreRFC822LineBreak(c);
+ lexSkipLookahead();
+ return SEMICOLON;
+ }
+ else if (strchr("\n",c)) {
+ ++mime_lineNum;
+ /* consume all line separator(s) adjacent to each other */
+ c = lexLookahead();
+ while (strchr("\n",c)) {
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum;
+ }
+ DBG_(("db: LINESEP\n"));
+ return LINESEP;
+ }
+ else {
+ char *p = 0;
+ lexPushLookaheadc(c);
+ if (lexWithinMode(L_BASE64)) {
+ /* get each char and convert to bin on the fly... */
+ p = lexGetDataFromBase64();
+ yylval.str = p;
+ return STRING;
+ }
+ else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
+ p = lexGetQuotedPrintable();
+ }
+ else {
+#ifdef _SUPPORT_LINE_FOLDING
+ p = lexGet1Value();
+#else
+ p = lexGetStrUntil(";\n");
+#endif
+ }
+ if (p) {
+ DBG_(("db: STRING: '%s'\n", p));
+ yylval.str = p;
+ return STRING;
+ }
+ else return 0;
+ }
+ }
+
+ else {
+ /* normal mode */
+ while (1) {
+ int c = lexGetc();
+ switch(c) {
+ case ':': {
+ /* consume all line separator(s) adjacent to each other */
+ /* ignoring linesep immediately after colon. */
+ c = lexLookahead();
+ while (strchr("\n",c)) {
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum;
+ }
+ DBG_(("db: COLON\n"));
+ return COLON;
+ }
+ case ';':
+ DBG_(("db: SEMICOLON\n"));
+ return SEMICOLON;
+ case '=':
+ DBG_(("db: EQ\n"));
+ return EQ;
+ /* ignore tabs/newlines in this mode. We can't ignore
+ * spaces, because values like NEEDS ACTION have a space. */
+ case '\t': continue;
+ case '\n': {
+ ++mime_lineNum;
+ continue;
+ }
+ case EOF: return 0;
+ break;
+ default: {
+ lexPushLookaheadc(c);
+ /* pending lutz : why linker error with isalpha(c)? */
+ /*if ( isalpha(c) || c == ' ') { */
+ if ( ( c >= 'A' && c <= 'Z') || ( c >= 'a' && c <= 'z') || c == ' ') {
+
+ char *t = lexGetWord();
+ yylval.str = t;
+ if (!strcasecmp(t, "begin")) {
+ return match_begin_end_name(0);
+ }
+ else if (!strcasecmp(t,"end")) {
+ return match_begin_end_name(1);
+ }
+ else {
+ DBG_(("db: ID '%s'\n", t));
+ return ID;
+ }
+ }
+ else {
+ /* unknown token */
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+
+
+/***************************************************************************/
+/*** Public Functions ****/
+/***************************************************************************/
+
+static VObject* Parse_MIMEHelper()
+ {
+ ObjStackTop = -1;
+ mime_numErrors = 0;
+ mime_lineNum = 1;
+ vObjList = 0;
+ curObj = 0;
+
+ if (yyparse() != 0)
+ return 0;
+
+ finiLex();
+ return vObjList;
+ }
+
+/****************************************************************************/
+VObject* Parse_MIME(const char *input, unsigned long len)
+ {
+ initLex(input, len, 0);
+ return Parse_MIMEHelper();
+ }
+
+
+VObject* Parse_MIME_FromFile(FILE *file)
+ {
+ VObject *result;
+ long startPos;
+
+ initLex(0,(unsigned long)-1,file);
+ startPos = ftell(file);
+ if (!(result = Parse_MIMEHelper())) {
+ fseek(file,startPos,SEEK_SET);
+ }
+ return result;
+ }
+
+VObject* Parse_MIME_FromFileName(const char *fname)
+ {
+ FILE *fp = fopen(fname,"r");
+ if (fp) {
+ VObject* o = Parse_MIME_FromFile(fp);
+ fclose(fp);
+ return o;
+ }
+ else {
+ char msg[255];
+ sprintf(msg, "can't open file '%s' for reading\n", fname);
+ mime_error_(msg);
+ return 0;
+ }
+ }
+
+/****************************************************************************/
+void YYDebug(const char *s)
+{
+ Parse_Debug(s);
+}
+
+
+static MimeErrorHandler mimeErrorHandler;
+
+void registerMimeErrorHandler(MimeErrorHandler me)
+ {
+ mimeErrorHandler = me;
+ }
+
+static void mime_error(char *s)
+ {
+ char msg[256];
+ if (mimeErrorHandler) {
+ sprintf(msg,"%s at line %d", s, mime_lineNum);
+ mimeErrorHandler(msg);
+ }
+ }
+
+static void mime_error_(char *s)
+ {
+ if (mimeErrorHandler) {
+ mimeErrorHandler(s);
+ }
+ }
+
diff --git a/libkcal/versit/vcc.h b/libkcal/versit/vcc.h
new file mode 100644
index 0000000..03886d1
--- a/dev/null
+++ b/libkcal/versit/vcc.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+#ifndef __VCC_H__
+#define __VCC_H__ 1
+
+#include "vobject.h"
+
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef void (*MimeErrorHandler)(char *);
+
+extern void registerMimeErrorHandler(MimeErrorHandler);
+
+extern VObject* Parse_MIME(const char *input, unsigned long len);
+extern VObject* Parse_MIME_FromFileName(const char* fname);
+
+
+/* NOTE regarding Parse_MIME_FromFile
+The function below, Parse_MIME_FromFile, come in two flavors,
+neither of which is exported from the DLL. Each version takes
+a CFile or FILE* as a parameter, neither of which can be
+passed across a DLL interface (at least that is my experience).
+If you are linking this code into your build directly then
+you may find them a more convenient API that the other flavors
+that take a file name. If you use them with the DLL LIB you
+will get a link error.
+*/
+
+
+extern VObject* Parse_MIME_FromFile(FILE *file);
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+}
+#endif
+
+#endif /* __VCC_H__ */
+
diff --git a/libkcal/versit/versit.pro b/libkcal/versit/versit.pro
new file mode 100644
index 0000000..915c25c
--- a/dev/null
+++ b/libkcal/versit/versit.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+CONFIG = qt warn_on release
+TARGET = versit
+INTERFACES = \
+
+HEADERS = \
+ port.h \
+ vcc.h \
+ vobject.h \
+
+SOURCES = \
+ \ \
+ vcc.c \
+ vobject.c \
+
diff --git a/libkcal/versit/versit.pro.back b/libkcal/versit/versit.pro.back
new file mode 100644
index 0000000..915c25c
--- a/dev/null
+++ b/libkcal/versit/versit.pro.back
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+CONFIG = qt warn_on release
+TARGET = versit
+INTERFACES = \
+
+HEADERS = \
+ port.h \
+ vcc.h \
+ vobject.h \
+
+SOURCES = \
+ \ \
+ vcc.c \
+ vobject.c \
+
diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c
new file mode 100644
index 0000000..637efb2
--- a/dev/null
+++ b/libkcal/versit/vobject.c
@@ -0,0 +1,1433 @@
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+ * src: vobject.c
+ * doc: vobject and APIs to construct vobject, APIs pretty print
+ * vobject, and convert a vobject into its textual representation.
+ */
+
+#include <stdlib.h>
+
+#include "vobject.h"
+#include <string.h>
+#include <stdio.h>
+#ifdef _WIN32_
+
+ #define strcasecmp _stricmp
+
+#endif
+
+#define NAME_OF(o) o->id
+#define VALUE_TYPE(o) o->valType
+#define STRINGZ_VALUE_OF(o) o->val.strs
+#define USTRINGZ_VALUE_OF(o) o->val.ustrs
+#define INTEGER_VALUE_OF(o) o->val.i
+#define LONG_VALUE_OF(o) o->val.l
+#define ANY_VALUE_OF(o) o->val.any
+#define VOBJECT_VALUE_OF(o) o->val.vobj
+
+const char** fieldedProp;
+
+
+
+/*----------------------------------------------------------------------
+ The following functions involve with memory allocation:
+ newVObject
+ deleteVObject
+ dupStr
+ deleteStr
+ newStrItem
+ deleteStrItem
+ ----------------------------------------------------------------------*/
+
+VObject* newVObject_(const char *id)
+{
+ VObject *p = (VObject*)malloc(sizeof(VObject));
+ p->next = 0;
+ p->id = id;
+ p->prop = 0;
+ VALUE_TYPE(p) = 0;
+ ANY_VALUE_OF(p) = 0;
+ return p;
+}
+
+VObject* newVObject(const char *id)
+{
+ return newVObject_(lookupStr(id));
+}
+
+void deleteVObject(VObject *p)
+{
+ if (p->id)
+ unUseStr(p->id);
+ if (p)
+ free(p);
+ p = NULL;
+}
+
+char* dupStr(const char *s, unsigned int size)
+{
+ char *t;
+ if (size == 0) {
+ size = strlen(s);
+ }
+ t = (char*)malloc(size+1);
+ if (t) {
+ memcpy(t,s,size);
+ t[size] = 0;
+ return t;
+ }
+ else {
+ return (char*)0;
+ }
+}
+
+void deleteStr(const char *p)
+{
+ if (p)
+ free((void*)p);
+ p = NULL;
+}
+
+
+static StrItem* newStrItem(const char *s, StrItem *next)
+{
+ StrItem *p = (StrItem*)malloc(sizeof(StrItem));
+ p->next = next;
+ p->s = s;
+ p->refCnt = 1;
+ return p;
+}
+
+static void deleteStrItem(StrItem *p)
+{
+ if (p)
+ free((void*)p);
+ p = NULL;
+}
+
+
+/*----------------------------------------------------------------------
+ The following function provide accesses to VObject's value.
+ ----------------------------------------------------------------------*/
+
+const char* vObjectName(VObject *o)
+{
+ return NAME_OF(o);
+}
+
+void setVObjectName(VObject *o, const char* id)
+{
+ NAME_OF(o) = id;
+}
+
+const char* vObjectStringZValue(VObject *o)
+{
+ return STRINGZ_VALUE_OF(o);
+}
+
+void setVObjectStringZValue(VObject *o, const char *s)
+{
+ STRINGZ_VALUE_OF(o) = dupStr(s,0);
+ VALUE_TYPE(o) = VCVT_STRINGZ;
+}
+
+void setVObjectStringZValue_(VObject *o, const char *s)
+{
+ STRINGZ_VALUE_OF(o) = s;
+ VALUE_TYPE(o) = VCVT_STRINGZ;
+}
+
+const wchar_t* vObjectUStringZValue(VObject *o)
+{
+ return USTRINGZ_VALUE_OF(o);
+}
+
+void setVObjectUStringZValue(VObject *o, const wchar_t *s)
+{
+ USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2);
+ VALUE_TYPE(o) = VCVT_USTRINGZ;
+}
+
+void setVObjectUStringZValue_(VObject *o, const wchar_t *s)
+{
+ USTRINGZ_VALUE_OF(o) = s;
+ VALUE_TYPE(o) = VCVT_USTRINGZ;
+}
+
+unsigned int vObjectIntegerValue(VObject *o)
+{
+ return INTEGER_VALUE_OF(o);
+}
+
+void setVObjectIntegerValue(VObject *o, unsigned int i)
+{
+ INTEGER_VALUE_OF(o) = i;
+ VALUE_TYPE(o) = VCVT_UINT;
+}
+
+unsigned long vObjectLongValue(VObject *o)
+{
+ return LONG_VALUE_OF(o);
+}
+
+void setVObjectLongValue(VObject *o, unsigned long l)
+{
+ LONG_VALUE_OF(o) = l;
+ VALUE_TYPE(o) = VCVT_ULONG;
+}
+
+void* vObjectAnyValue(VObject *o)
+{
+ return ANY_VALUE_OF(o);
+}
+
+void setVObjectAnyValue(VObject *o, void *t)
+{
+ ANY_VALUE_OF(o) = t;
+ VALUE_TYPE(o) = VCVT_RAW;
+}
+
+VObject* vObjectVObjectValue(VObject *o)
+{
+ return VOBJECT_VALUE_OF(o);
+}
+
+void setVObjectVObjectValue(VObject *o, VObject *p)
+{
+ VOBJECT_VALUE_OF(o) = p;
+ VALUE_TYPE(o) = VCVT_VOBJECT;
+}
+
+int vObjectValueType(VObject *o)
+{
+ return VALUE_TYPE(o);
+}
+
+
+/*----------------------------------------------------------------------
+ The following functions can be used to build VObject.
+ ----------------------------------------------------------------------*/
+
+VObject* addVObjectProp(VObject *o, VObject *p)
+{
+ /* circular link list pointed to tail */
+ /*
+ o {next,id,prop,val}
+ V
+ pn {next,id,prop,val}
+ V
+ ...
+ p1 {next,id,prop,val}
+ V
+ pn
+ -->
+ o {next,id,prop,val}
+ V
+ pn {next,id,prop,val}
+ V
+ p {next,id,prop,val}
+ ...
+ p1 {next,id,prop,val}
+ V
+ pn
+ */
+
+ VObject *tail = o->prop;
+ if (tail) {
+ p->next = tail->next;
+ o->prop = tail->next = p;
+ }
+ else {
+ o->prop = p->next = p;
+ }
+ return p;
+}
+
+VObject* addProp(VObject *o, const char *id)
+{
+ return addVObjectProp(o,newVObject(id));
+}
+
+VObject* addProp_(VObject *o, const char *id)
+{
+ return addVObjectProp(o,newVObject_(id));
+}
+
+void addList(VObject **o, VObject *p)
+{
+ p->next = 0;
+ if (*o == 0) {
+ *o = p;
+ }
+ else {
+ VObject *t = *o;
+ while (t->next) {
+ t = t->next;
+ }
+ t->next = p;
+ }
+}
+
+VObject* nextVObjectInList(VObject *o)
+{
+ return o->next;
+}
+
+VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size)
+{
+ VObject *sizeProp;
+ setVObjectAnyValue(prop, val);
+ sizeProp = addProp(prop,VCDataSizeProp);
+ setVObjectLongValue(sizeProp, size);
+ return prop;
+}
+
+VObject* setValueWithSize(VObject *prop, void *val, unsigned int size)
+{
+ void *p = dupStr(val,size);
+ return setValueWithSize_(prop,p,p?size:0);
+}
+
+void initPropIterator(VObjectIterator *i, VObject *o)
+{
+ i->start = o->prop;
+ i->next = 0;
+}
+
+void initVObjectIterator(VObjectIterator *i, VObject *o)
+{
+ i->start = o->next;
+ i->next = 0;
+}
+
+int moreIteration(VObjectIterator *i)
+{
+ return (i->start && (i->next==0 || i->next!=i->start));
+}
+
+VObject* nextVObject(VObjectIterator *i)
+{
+ if (i->start && i->next != i->start) {
+ if (i->next == 0) {
+ i->next = i->start->next;
+ return i->next;
+ }
+ else {
+ i->next = i->next->next;
+ return i->next;
+ }
+ }
+ else return (VObject*)0;
+}
+
+VObject* isAPropertyOf(VObject *o, const char *id)
+{
+ VObjectIterator i;
+ initPropIterator(&i,o);
+ while (moreIteration(&i)) {
+ VObject *each = nextVObject(&i);
+ if (!strcasecmp(id,each->id))
+ return each;
+ }
+ return (VObject*)0;
+}
+
+VObject* addGroup(VObject *o, const char *g)
+{
+ /*
+ a.b.c
+ -->
+ prop(c)
+ prop(VCGrouping=b)
+ prop(VCGrouping=a)
+ */
+ char *dot = strrchr(g,'.');
+ if (dot) {
+ VObject *p, *t;
+ char *gs, *n = dot+1;
+ gs = dupStr(g,0); /* so we can write to it. */
+ /* used to be
+ * t = p = addProp_(o,lookupProp_(n));
+ */
+ t = p = addProp_(o,lookupProp(n));
+ dot = strrchr(gs,'.');
+ *dot = 0;
+ do {
+ dot = strrchr(gs,'.');
+ if (dot) {
+ n = dot+1;
+ *dot=0;
+ }
+ else
+ n = gs;
+ /* property(VCGroupingProp=n);
+ * and the value may have VCGrouping property
+ */
+ t = addProp(t,VCGroupingProp);
+ setVObjectStringZValue(t,lookupProp_(n));
+ } while (n != gs);
+ deleteStr(gs);
+ return p;
+ }
+ else
+ return addProp_(o,lookupProp(g));
+}
+
+VObject* addPropValue(VObject *o, const char *p, const char *v)
+{
+ VObject *prop;
+ prop = addProp(o,p);
+ setVObjectUStringZValue_(prop, fakeUnicode(v,0));
+ return prop;
+}
+
+VObject* addPropSizedValue_(VObject *o, const char *p, const char *v,
+ unsigned int size)
+{
+ VObject *prop;
+ prop = addProp(o,p);
+ setValueWithSize_(prop, (void*)v, size);
+ return prop;
+}
+
+VObject* addPropSizedValue(VObject *o, const char *p, const char *v,
+ unsigned int size)
+{
+ return addPropSizedValue_(o,p,dupStr(v,size),size);
+}
+
+
+
+/*----------------------------------------------------------------------
+ The following pretty print a VObject
+ ----------------------------------------------------------------------*/
+
+static void printVObject_(FILE *fp, VObject *o, int level);
+
+static void indent(FILE *fp, int level)
+{
+ int i;
+ for (i=0;i<level*4;i++) {
+ fputc(' ', fp);
+ }
+}
+
+static void printValue(FILE *fp, VObject *o, int level)
+{
+ switch (VALUE_TYPE(o)) {
+ case VCVT_USTRINGZ: {
+ char c;
+ char *t,*s;
+ s = t = fakeCString(USTRINGZ_VALUE_OF(o));
+ fputc('"',fp);
+ while (c=*t,c) {
+ fputc(c,fp);
+ if (c == '\n') indent(fp,level+2);
+ t++;
+ }
+ fputc('"',fp);
+ deleteStr(s);
+ break;
+ }
+ case VCVT_STRINGZ: {
+ char c;
+ const char *s = STRINGZ_VALUE_OF(o);
+ fputc('"',fp);
+ while (c=*s,c) {
+ fputc(c,fp);
+ if (c == '\n') indent(fp,level+2);
+ s++;
+ }
+ fputc('"',fp);
+ break;
+ }
+ case VCVT_UINT:
+ fprintf(fp,"%d", INTEGER_VALUE_OF(o)); break;
+ case VCVT_ULONG:
+ fprintf(fp,"%ld", LONG_VALUE_OF(o)); break;
+ case VCVT_RAW:
+ fprintf(fp,"[raw data]"); break;
+ case VCVT_VOBJECT:
+ fprintf(fp,"[vobject]\n");
+ printVObject_(fp,VOBJECT_VALUE_OF(o),level+1);
+ break;
+ case 0:
+ fprintf(fp,"[none]"); break;
+ default:
+ fprintf(fp,"[unknown]"); break;
+ }
+}
+
+static void printNameValue(FILE *fp,VObject *o, int level)
+{
+ indent(fp,level);
+ if (NAME_OF(o)) {
+ fprintf(fp,"%s", NAME_OF(o));
+ }
+ if (VALUE_TYPE(o)) {
+ fputc('=',fp);
+ printValue(fp,o, level);
+ }
+ fprintf(fp,"\n");
+}
+
+static void printVObject_(FILE *fp, VObject *o, int level)
+ {
+ VObjectIterator t;
+ if (o == 0) {
+ fprintf(fp,"[NULL]\n");
+ return;
+ }
+ printNameValue(fp,o,level);
+ initPropIterator(&t,o);
+ while (moreIteration(&t)) {
+ VObject *eachProp = nextVObject(&t);
+ printVObject_(fp,eachProp,level+1);
+ }
+ }
+
+void printVObject(FILE *fp,VObject *o)
+{
+ printVObject_(fp,o,0);
+}
+
+void printVObjectToFile(char *fname,VObject *o)
+{
+ FILE *fp = fopen(fname,"w");
+ if (fp) {
+ printVObject(fp,o);
+ fclose(fp);
+ }
+}
+
+void printVObjectsToFile(char *fname,VObject *list)
+{
+ FILE *fp = fopen(fname,"w");
+ if (fp) {
+ while (list) {
+ printVObject(fp,list);
+ list = nextVObjectInList(list);
+ }
+ fclose(fp);
+ }
+}
+
+void cleanVObject(VObject *o)
+{
+ if (o == 0) return;
+ if (o->prop) {
+ /* destroy time: cannot use the iterator here.
+ Have to break the cycle in the circular link
+ list and turns it into regular NULL-terminated
+ list -- since at some point of destruction,
+ the reference entry for the iterator to work
+ will not longer be valid.
+ */
+ VObject *p;
+ p = o->prop->next;
+ o->prop->next = 0;
+ do {
+ VObject *t = p->next;
+ cleanVObject(p);
+ p = t;
+ } while (p);
+ }
+ switch (VALUE_TYPE(o)) {
+ case VCVT_USTRINGZ:
+ case VCVT_STRINGZ:
+ case VCVT_RAW:
+ /* assume they are all allocated by malloc. */
+ free((char*)STRINGZ_VALUE_OF(o));
+ break;
+ case VCVT_VOBJECT:
+ cleanVObject(VOBJECT_VALUE_OF(o));
+ break;
+ }
+ deleteVObject(o);
+}
+
+void cleanVObjects(VObject *list)
+{
+ while (list) {
+ VObject *t = list;
+ list = nextVObjectInList(list);
+ cleanVObject(t);
+ }
+}
+
+/*----------------------------------------------------------------------
+ The following is a String Table Facilities.
+ ----------------------------------------------------------------------*/
+
+#define STRTBLSIZE 255
+
+static StrItem *strTbl[STRTBLSIZE];
+
+static unsigned int hashStr(const char *s)
+{
+ unsigned int h = 0;
+ int i;
+ for (i=0;s[i];i++) {
+ h += s[i]*i;
+ }
+ return h % STRTBLSIZE;
+}
+
+const char* lookupStr(const char *s)
+{
+ char *newS;
+
+ StrItem *t;
+ unsigned int h = hashStr(s);
+ if ((t = strTbl[h]) != 0) {
+ do {
+ if (strcasecmp(t->s,s) == 0) {
+ t->refCnt++;
+ return t->s;
+ }
+ t = t->next;
+ } while (t);
+ }
+ newS = dupStr(s,0);
+ strTbl[h] = newStrItem(newS,strTbl[h]);
+ return newS;
+}
+
+void unUseStr(const char *s)
+{
+ StrItem *cur, *prev;
+
+ unsigned int h = hashStr(s);
+ cur = strTbl[h];
+ prev = cur;
+ while (cur != 0) {
+ if (strcasecmp(cur->s,s) == 0) {
+ cur->refCnt--;
+ /* if that was the last reference to this string, kill it. */
+ if (cur->refCnt == 0) {
+ if (cur == strTbl[h]) {
+ strTbl[h] = cur->next;
+ deleteStr(prev->s);
+ deleteStrItem(prev);
+ } else {
+ prev->next = cur->next;
+ deleteStr(cur->s);
+ deleteStrItem(cur);
+ }
+ return;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+}
+
+void cleanStrTbl()
+{
+ int i;
+ for (i=0; i<STRTBLSIZE;i++) {
+ StrItem *t = strTbl[i];
+ while (t) {
+ StrItem *p;
+ deleteStr(t->s);
+ p = t;
+ t = t->next;
+ deleteStrItem(p);
+ }
+ strTbl[i] = 0;
+ }
+}
+
+
+struct PreDefProp {
+ const char *name;
+ const char *alias;
+ const char** fields;
+ unsigned int flags;
+ };
+
+/* flags in PreDefProp */
+#define PD_BEGIN 0x1
+#define PD_INTERNAL 0x2
+
+static const char *adrFields[] = {
+ VCPostalBoxProp,
+ VCExtAddressProp,
+ VCStreetAddressProp,
+ VCCityProp,
+ VCRegionProp,
+ VCPostalCodeProp,
+ VCCountryNameProp,
+ 0
+};
+
+static const char *nameFields[] = {
+ VCFamilyNameProp,
+ VCGivenNameProp,
+ VCAdditionalNamesProp,
+ VCNamePrefixesProp,
+ VCNameSuffixesProp,
+ NULL
+ };
+
+static const char *orgFields[] = {
+ VCOrgNameProp,
+ VCOrgUnitProp,
+ VCOrgUnit2Prop,
+ VCOrgUnit3Prop,
+ VCOrgUnit4Prop,
+ NULL
+ };
+
+static const char *AAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCAudioContentProp,
+ 0
+ };
+
+/* ExDate -- has unamed fields */
+/* RDate -- has unamed fields */
+
+static const char *DAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCDisplayStringProp,
+ 0
+ };
+
+static const char *MAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCEmailAddressProp,
+ VCNoteProp,
+ 0
+ };
+
+static const char *PAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCProcedureNameProp,
+ 0
+ };
+
+static struct PreDefProp propNames[] = {
+ { VC7bitProp, 0, 0, 0 },
+ { VC8bitProp, 0, 0, 0 },
+ { VCAAlarmProp, 0, AAlarmFields, 0 },
+ { VCAdditionalNamesProp, 0, 0, 0 },
+ { VCAdrProp, 0, adrFields, 0 },
+ { VCAgentProp, 0, 0, 0 },
+ { VCAIFFProp, 0, 0, 0 },
+ { VCAOLProp, 0, 0, 0 },
+ { VCAppleLinkProp, 0, 0, 0 },
+ { VCAttachProp, 0, 0, 0 },
+ { VCAttendeeProp, 0, 0, 0 },
+ { VCATTMailProp, 0, 0, 0 },
+ { VCAudioContentProp, 0, 0, 0 },
+ { VCAVIProp, 0, 0, 0 },
+ { VCBase64Prop, 0, 0, 0 },
+ { VCBBSProp, 0, 0, 0 },
+ { VCBirthDateProp, 0, 0, 0 },
+ { VCBMPProp, 0, 0, 0 },
+ { VCBodyProp, 0, 0, 0 },
+ { VCBusinessRoleProp, 0, 0, 0 },
+ { VCCalProp, 0, 0, PD_BEGIN },
+ { VCCaptionProp, 0, 0, 0 },
+ { VCCardProp, 0, 0, PD_BEGIN },
+ { VCCarProp, 0, 0, 0 },
+ { VCCategoriesProp, 0, 0, 0 },
+ { VCCellularProp, 0, 0, 0 },
+ { VCCGMProp, 0, 0, 0 },
+ { VCCharSetProp, 0, 0, 0 },
+ { VCCIDProp, VCContentIDProp, 0, 0 },
+ { VCCISProp, 0, 0, 0 },
+ { VCCityProp, 0, 0, 0 },
+ { VCClassProp, 0, 0, 0 },
+ { VCCommentProp, 0, 0, 0 },
+ { VCCompletedProp, 0, 0, 0 },
+ { VCContentIDProp, 0, 0, 0 },
+ { VCCountryNameProp, 0, 0, 0 },
+ { VCDAlarmProp, 0, DAlarmFields, 0 },
+ { VCDataSizeProp, 0, 0, PD_INTERNAL },
+ { VCDayLightProp, 0, 0, 0 },
+ { VCDCreatedProp, 0, 0, 0 },
+ { VCDeliveryLabelProp, 0, 0, 0 },
+ { VCDescriptionProp, 0, 0, 0 },
+ { VCDIBProp, 0, 0, 0 },
+ { VCDisplayStringProp, 0, 0, 0 },
+ { VCDomesticProp, 0, 0, 0 },
+ { VCDTendProp, 0, 0, 0 },
+ { VCDTstartProp, 0, 0, 0 },
+ { VCDueProp, 0, 0, 0 },
+ { VCEmailAddressProp, 0, 0, 0 },
+ { VCEncodingProp, 0, 0, 0 },
+ { VCEndProp, 0, 0, 0 },
+ { VCEventProp, 0, 0, PD_BEGIN },
+ { VCEWorldProp, 0, 0, 0 },
+ { VCExNumProp, 0, 0, 0 },
+ { VCExDateProp, 0, 0, 0 },
+ { VCExpectProp, 0, 0, 0 },
+ { VCExtAddressProp, 0, 0, 0 },
+ { VCFamilyNameProp, 0, 0, 0 },
+ { VCFaxProp, 0, 0, 0 },
+ { VCFullNameProp, 0, 0, 0 },
+ { VCGeoLocationProp, 0, 0, 0 },
+ { VCGeoProp, 0, 0, 0 },
+ { VCGIFProp, 0, 0, 0 },
+ { VCGivenNameProp, 0, 0, 0 },
+ { VCGroupingProp, 0, 0, 0 },
+ { VCHomeProp, 0, 0, 0 },
+ { VCIBMMailProp, 0, 0, 0 },
+ { VCInlineProp, 0, 0, 0 },
+ { VCInternationalProp, 0, 0, 0 },
+ { VCInternetProp, 0, 0, 0 },
+ { VCISDNProp, 0, 0, 0 },
+ { VCJPEGProp, 0, 0, 0 },
+ { VCLanguageProp, 0, 0, 0 },
+ { VCLastModifiedProp, 0, 0, 0 },
+ { VCLastRevisedProp, 0, 0, 0 },
+ { VCLocationProp, 0, 0, 0 },
+ { VCLogoProp, 0, 0, 0 },
+ { VCMailerProp, 0, 0, 0 },
+ { VCMAlarmProp, 0, MAlarmFields, 0 },
+ { VCMCIMailProp, 0, 0, 0 },
+ { VCMessageProp, 0, 0, 0 },
+ { VCMETProp, 0, 0, 0 },
+ { VCModemProp, 0, 0, 0 },
+ { VCMPEG2Prop, 0, 0, 0 },
+ { VCMPEGProp, 0, 0, 0 },
+ { VCMSNProp, 0, 0, 0 },
+ { VCNamePrefixesProp, 0, 0, 0 },
+ { VCNameProp, 0, nameFields, 0 },
+ { VCNameSuffixesProp, 0, 0, 0 },
+ { VCNoteProp, 0, 0, 0 },
+ { VCOrgNameProp, 0, 0, 0 },
+ { VCOrgProp, 0, orgFields, 0 },
+ { VCOrgUnit2Prop, 0, 0, 0 },
+ { VCOrgUnit3Prop, 0, 0, 0 },
+ { VCOrgUnit4Prop, 0, 0, 0 },
+ { VCOrgUnitProp, 0, 0, 0 },
+ { VCPagerProp, 0, 0, 0 },
+ { VCPAlarmProp, 0, PAlarmFields, 0 },
+ { VCParcelProp, 0, 0, 0 },
+ { VCPartProp, 0, 0, 0 },
+ { VCPCMProp, 0, 0, 0 },
+ { VCPDFProp, 0, 0, 0 },
+ { VCPGPProp, 0, 0, 0 },
+ { VCPhotoProp, 0, 0, 0 },
+ { VCPICTProp, 0, 0, 0 },
+ { VCPMBProp, 0, 0, 0 },
+ { VCPostalBoxProp, 0, 0, 0 },
+ { VCPostalCodeProp, 0, 0, 0 },
+ { VCPostalProp, 0, 0, 0 },
+ { VCPowerShareProp, 0, 0, 0 },
+ { VCPreferredProp, 0, 0, 0 },
+ { VCPriorityProp, 0, 0, 0 },
+ { VCProcedureNameProp, 0, 0, 0 },
+ { VCProdIdProp, 0, 0, 0 },
+ { VCProdigyProp, 0, 0, 0 },
+ { VCPronunciationProp, 0, 0, 0 },
+ { VCPSProp, 0, 0, 0 },
+ { VCPublicKeyProp, 0, 0, 0 },
+ { VCQPProp, VCQuotedPrintableProp, 0, 0 },
+ { VCQuickTimeProp, 0, 0, 0 },
+ { VCQuotedPrintableProp, 0, 0, 0 },
+ { VCRDateProp, 0, 0, 0 },
+ { VCRegionProp, 0, 0, 0 },
+ { VCRelatedToProp, 0, 0, 0 },
+ { VCRepeatCountProp, 0, 0, 0 },
+ { VCResourcesProp, 0, 0, 0 },
+ { VCRNumProp, 0, 0, 0 },
+ { VCRoleProp, 0, 0, 0 },
+ { VCRRuleProp, 0, 0, 0 },
+ { VCRSVPProp, 0, 0, 0 },
+ { VCRunTimeProp, 0, 0, 0 },
+ { VCSequenceProp, 0, 0, 0 },
+ { VCSnoozeTimeProp, 0, 0, 0 },
+ { VCStartProp, 0, 0, 0 },
+ { VCStatusProp, 0, 0, 0 },
+ { VCStreetAddressProp, 0, 0, 0 },
+ { VCSubTypeProp, 0, 0, 0 },
+ { VCSummaryProp, 0, 0, 0 },
+ { VCTelephoneProp, 0, 0, 0 },
+ { VCTIFFProp, 0, 0, 0 },
+ { VCTimeZoneProp, 0, 0, 0 },
+ { VCTitleProp, 0, 0, 0 },
+ { VCTLXProp, 0, 0, 0 },
+ { VCTodoProp, 0, 0, PD_BEGIN },
+ { VCTranspProp, 0, 0, 0 },
+ { VCUniqueStringProp, 0, 0, 0 },
+ { VCURLProp, 0, 0, 0 },
+ { VCURLValueProp, 0, 0, 0 },
+ { VCValueProp, 0, 0, 0 },
+ { VCVersionProp, 0, 0, 0 },
+ { VCVideoProp, 0, 0, 0 },
+ { VCVoiceProp, 0, 0, 0 },
+ { VCWAVEProp, 0, 0, 0 },
+ { VCWMFProp, 0, 0, 0 },
+ { VCWorkProp, 0, 0, 0 },
+ { VCX400Prop, 0, 0, 0 },
+ { VCX509Prop, 0, 0, 0 },
+ { VCXRuleProp, 0, 0, 0 },
+ { 0,0,0,0 }
+ };
+
+
+static struct PreDefProp* lookupPropInfo(const char* str)
+{
+ /* brute force for now, could use a hash table here. */
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (strcasecmp(str, propNames[i].name) == 0) {
+ return &propNames[i];
+ }
+
+ return 0;
+}
+
+
+const char* lookupProp_(const char* str)
+{
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (strcasecmp(str, propNames[i].name) == 0) {
+ const char* s;
+ s = propNames[i].alias?propNames[i].alias:propNames[i].name;
+ return lookupStr(s);
+ }
+ return lookupStr(str);
+}
+
+
+const char* lookupProp(const char* str)
+{
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (strcasecmp(str, propNames[i].name) == 0) {
+ const char *s;
+ fieldedProp = propNames[i].fields;
+ s = propNames[i].alias?propNames[i].alias:propNames[i].name;
+ return lookupStr(s);
+ }
+ fieldedProp = 0;
+ return lookupStr(str);
+}
+
+
+/*----------------------------------------------------------------------
+ APIs to Output text form.
+ ----------------------------------------------------------------------*/
+#define OFILE_REALLOC_SIZE 256
+typedef struct OFile {
+ FILE *fp;
+ char *s;
+ int len;
+ int limit;
+ int alloc:1;
+ int fail:1;
+ } OFile;
+
+
+/* vCalendar files need crlf linebreaks. The disabled functions didn't provide
+ that. */
+#if 0
+
+static void appendsOFile(OFile *fp, const char *s)
+{
+ int slen;
+ if (fp->fail) return;
+ slen = strlen(s);
+ if (fp->fp) {
+ fwrite(s,1,slen,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len + slen < fp->limit) {
+ memcpy(fp->s+fp->len,s,slen);
+ fp->len += slen;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
+ if (fp->s)
+ fp->s = realloc(fp->s,fp->limit);
+ else
+ fp->s = malloc(fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+
+static void appendcOFile(OFile *fp, char c)
+{
+ if (fp->fail) return;
+ if (fp->fp) {
+ fputc(c,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len+1 < fp->limit) {
+ fp->s[fp->len] = c;
+ fp->len++;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ fp->s = realloc(fp->s,fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+
+#else
+
+static void appendcOFile_(OFile *fp, char c)
+{
+ if (fp->fail) return;
+ if (fp->fp) {
+ fputc(c,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len+1 < fp->limit) {
+ fp->s[fp->len] = c;
+ fp->len++;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ fp->s = realloc(fp->s,fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+
+static void appendcOFile(OFile *fp, char c)
+{
+ if (c == '\n') {
+ /* write out as <CR><LF> */
+ appendcOFile_(fp,0xd);
+ appendcOFile_(fp,0xa);
+ }
+ else
+ appendcOFile_(fp,c);
+}
+
+static void appendsOFile(OFile *fp, const char *s)
+{
+ int i, slen;
+ slen = strlen(s);
+ for (i=0; i<slen; i++) {
+ appendcOFile(fp,s[i]);
+ }
+}
+
+#endif
+
+static void initOFile(OFile *fp, FILE *ofp)
+{
+ fp->fp = ofp;
+ fp->s = 0;
+ fp->len = 0;
+ fp->limit = 0;
+ fp->alloc = 0;
+ fp->fail = 0;
+}
+
+static void initMemOFile(OFile *fp, char *s, int len)
+{
+ fp->fp = 0;
+ fp->s = s;
+ fp->len = 0;
+ fp->limit = s?len:0;
+ fp->alloc = s?0:1;
+ fp->fail = 0;
+}
+
+
+static int writeBase64(OFile *fp, unsigned char *s, long len)
+{
+ long cur = 0;
+ int i, numQuads = 0;
+ unsigned long trip;
+ unsigned char b;
+ char quad[5];
+#define MAXQUADS 16
+
+ quad[4] = 0;
+
+ while (cur < len) {
+ /* collect the triplet of bytes into 'trip' */
+ trip = 0;
+ for (i = 0; i < 3; i++) {
+ b = (cur < len) ? *(s + cur) : 0;
+ cur++;
+ trip = trip << 8 | b;
+ }
+ /* fill in 'quad' with the appropriate four characters */
+ for (i = 3; i >= 0; i--) {
+ b = (unsigned char)(trip & 0x3F);
+ trip = trip >> 6;
+ if ((3 - i) < (cur - len))
+ quad[i] = '='; /* pad char */
+ else if (b < 26) quad[i] = (char)b + 'A';
+ else if (b < 52) quad[i] = (char)(b - 26) + 'a';
+ else if (b < 62) quad[i] = (char)(b - 52) + '0';
+ else if (b == 62) quad[i] = '+';
+ else quad[i] = '/';
+ }
+ /* now output 'quad' with appropriate whitespace and line ending */
+ appendsOFile(fp, (numQuads == 0 ? " " : ""));
+ appendsOFile(fp, quad);
+ appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
+ numQuads = (numQuads + 1) % MAXQUADS;
+ }
+ appendcOFile(fp,'\n');
+
+ return 1;
+}
+
+/* this function really sucks. Too basic. */
+static void writeQPString(OFile *fp, const char *s, int qp)
+{
+ const char *p = s;
+ while (*p) {
+ if (*p == '\n') {
+ if (p[1]) appendsOFile(fp,"=0A=");
+ }
+ if (*p == '=' && qp)
+ appendsOFile(fp,"=3D");
+ else
+ appendcOFile(fp,*p);
+ p++;
+ }
+}
+
+static void writeVObject_(OFile *fp, VObject *o);
+
+static void writeValue(OFile *fp, VObject *o, unsigned long size)
+{
+ if (o == 0) return;
+ switch (VALUE_TYPE(o)) {
+ case VCVT_USTRINGZ: {
+ char *s = fakeCString(USTRINGZ_VALUE_OF(o));
+ if (isAPropertyOf(o, VCQuotedPrintableProp))
+ writeQPString(fp, s, 1);
+ else
+ writeQPString(fp, s, 0);
+ deleteStr(s);
+ break;
+ }
+ case VCVT_STRINGZ: {
+ if (isAPropertyOf(o, VCQuotedPrintableProp))
+ writeQPString(fp, STRINGZ_VALUE_OF(o), 1);
+ else
+ writeQPString(fp, STRINGZ_VALUE_OF(o), 0);
+ break;
+ }
+ case VCVT_UINT: {
+ char buf[16];
+ sprintf(buf,"%u", INTEGER_VALUE_OF(o));
+ appendsOFile(fp,buf);
+ break;
+ }
+ case VCVT_ULONG: {
+ char buf[16];
+ sprintf(buf,"%lu", LONG_VALUE_OF(o));
+ appendsOFile(fp,buf);
+ break;
+ }
+ case VCVT_RAW: {
+ appendcOFile(fp,'\n');
+ writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
+ break;
+ }
+ case VCVT_VOBJECT:
+ appendcOFile(fp,'\n');
+ writeVObject_(fp,VOBJECT_VALUE_OF(o));
+ break;
+ }
+}
+
+static void writeAttrValue(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ pi = lookupPropInfo(NAME_OF(o));
+ if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
+ appendcOFile(fp,';');
+ appendsOFile(fp,NAME_OF(o));
+ }
+ else
+ appendcOFile(fp,';');
+ if (VALUE_TYPE(o)) {
+ appendcOFile(fp,'=');
+ writeValue(fp,o,0);
+ }
+}
+
+static void writeGroup(OFile *fp, VObject *o)
+{
+ char buf1[256];
+ char buf2[256];
+ strcpy(buf1,NAME_OF(o));
+ while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
+ strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2));
+ buf2[sizeof(buf2)] = '\0';
+ strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1);
+ strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1);
+ strcpy(buf1,buf2);
+ }
+ appendsOFile(fp,buf1);
+}
+
+static int inList(const char **list, const char *s)
+{
+ if (list == 0) return 0;
+ while (*list) {
+ if (strcasecmp(*list,s) == 0) return 1;
+ list++;
+ }
+ return 0;
+}
+
+static void writeProp(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ VObjectIterator t;
+ const char **fields_ = 0;
+ pi = lookupPropInfo(NAME_OF(o));
+ if (pi && ((pi->flags & PD_BEGIN) != 0)) {
+ writeVObject_(fp,o);
+ return;
+ }
+ if (isAPropertyOf(o,VCGroupingProp))
+ writeGroup(fp,o);
+ else
+ appendsOFile(fp,NAME_OF(o));
+ if (pi) fields_ = pi->fields;
+ initPropIterator(&t,o);
+ while (moreIteration(&t)) {
+ const char *s;
+ VObject *eachProp = nextVObject(&t);
+ s = NAME_OF(eachProp);
+ if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s))
+ writeAttrValue(fp,eachProp);
+ }
+ if (fields_) {
+ int i = 0, n = 0;
+ const char** fields = fields_;
+ /* output prop as fields */
+ appendcOFile(fp,':');
+ while (*fields) {
+ VObject *tl = isAPropertyOf(o,*fields);
+ i++;
+ if (tl) n = i;
+ fields++;
+ }
+ fields = fields_;
+ for (i=0;i<n;i++) {
+ writeValue(fp,isAPropertyOf(o,*fields),0);
+ fields++;
+ if (i<(n-1)) appendcOFile(fp,';');
+ }
+ }
+ }
+
+ if (VALUE_TYPE(o)) {
+ unsigned long size = 0;
+ VObject *p = isAPropertyOf(o,VCDataSizeProp);
+ if (p) size = LONG_VALUE_OF(p);
+ appendcOFile(fp,':');
+ writeValue(fp,o,size);
+ }
+
+ appendcOFile(fp,'\n');
+}
+
+static void writeVObject_(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ pi = lookupPropInfo(NAME_OF(o));
+
+ if (pi && ((pi->flags & PD_BEGIN) != 0)) {
+ VObjectIterator t;
+ const char *begin = NAME_OF(o);
+ appendsOFile(fp,"BEGIN:");
+ appendsOFile(fp,begin);
+ appendcOFile(fp,'\n');
+ initPropIterator(&t,o);
+ while (moreIteration(&t)) {
+ VObject *eachProp = nextVObject(&t);
+ writeProp(fp, eachProp);
+ }
+ appendsOFile(fp,"END:");
+ appendsOFile(fp,begin);
+ appendsOFile(fp,"\n\n");
+ }
+ }
+}
+
+void writeVObject(FILE *fp, VObject *o)
+{
+ OFile ofp;
+ initOFile(&ofp,fp);
+ writeVObject_(&ofp,o);
+}
+
+void writeVObjectToFile(char *fname, VObject *o)
+{
+ FILE *fp = fopen(fname,"w");
+ if (fp) {
+ writeVObject(fp,o);
+ fclose(fp);
+ }
+}
+
+void writeVObjectsToFile(char *fname, VObject *list)
+{
+ FILE *fp = fopen(fname,"w");
+ if (fp) {
+ while (list) {
+ writeVObject(fp,list);
+ list = nextVObjectInList(list);
+ }
+ fclose(fp);
+ }
+}
+
+char* writeMemVObject(char *s, int *len, VObject *o)
+{
+ OFile ofp;
+ initMemOFile(&ofp,s,len?*len:0);
+ writeVObject_(&ofp,o);
+ if (len) *len = ofp.len;
+ appendcOFile(&ofp,0);
+ return ofp.s;
+}
+
+char* writeMemVObjects(char *s, int *len, VObject *list)
+{
+ OFile ofp;
+ initMemOFile(&ofp,s,len?*len:0);
+ while (list) {
+ writeVObject_(&ofp,list);
+ list = nextVObjectInList(list);
+ }
+ if (len) *len = ofp.len;
+ appendcOFile(&ofp,0);
+ return ofp.s;
+}
+
+/*----------------------------------------------------------------------
+ APIs to do fake Unicode stuff.
+ ----------------------------------------------------------------------*/
+wchar_t* fakeUnicode(const char *ps, int *bytes)
+{
+ wchar_t *r, *pw;
+ int len = strlen(ps)+1;
+
+ pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len);
+ if (bytes)
+ *bytes = len * sizeof(wchar_t);
+
+ while (*ps) {
+ if (*ps == '\n')
+ *pw = (wchar_t)0x2028;
+ else if (*ps == '\r')
+ *pw = (wchar_t)0x2029;
+ else
+ *pw = (wchar_t)(unsigned char)*ps;
+ ps++; pw++;
+ }
+ *pw = (wchar_t)0;
+
+ return r;
+}
+
+int uStrLen(const wchar_t *u)
+{
+ int i = 0;
+ while (*u != (wchar_t)0) { u++; i++; }
+ return i;
+}
+
+char* fakeCString(const wchar_t *u)
+{
+ char *s, *t;
+ int len = uStrLen(u) + 1;
+ t = s = (char*)malloc(len+1);
+ while (*u) {
+ if (*u == (wchar_t)0x2028)
+ *t = '\n';
+ else if (*u == (wchar_t)0x2029)
+ *t = '\r';
+ else
+ *t = (char)*u;
+ u++; t++;
+ }
+ *t = 0;
+ return s;
+}
+
+/* end of source file vobject.c */
diff --git a/libkcal/versit/vobject.h b/libkcal/versit/vobject.h
new file mode 100644
index 0000000..0ec8b31
--- a/dev/null
+++ b/libkcal/versit/vobject.h
@@ -0,0 +1,384 @@
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+
+The vCard/vCalendar C interface is implemented in the set
+of files as follows:
+
+vcc.y, yacc source, and vcc.c, the yacc output you will use
+implements the core parser
+
+vobject.c implements an API that insulates the caller from
+the parser and changes in the vCard/vCalendar BNF
+
+port.h defines compilation environment dependent stuff
+
+vcc.h and vobject.h are header files for their .c counterparts
+
+vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
+which you may find useful.
+
+test.c is a standalone test driver that exercises some of
+the features of the APIs provided. Invoke test.exe on a
+VCARD/VCALENDAR input text file and you will see the pretty
+print output of the internal representation (this pretty print
+output should give you a good idea of how the internal
+representation looks like -- there is one such output in the
+following too). Also, a file with the .out suffix is generated
+to show that the internal representation can be written back
+in the original text format.
+
+For more information on this API see the readme.txt file
+which accompanied this distribution.
+
+ Also visit:
+
+ http://www.versit.com
+ http://www.ralden.com
+
+*/
+
+
+#ifndef __VOBJECT_H__
+#define __VOBJECT_H__ 1
+
+
+#include "port.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define VC7bitProp "7BIT"
+#define VC8bitProp "8BIT"
+#define VCAAlarmProp "AALARM"
+#define VCAdditionalNamesProp "ADDN"
+#define VCAdrProp "ADR"
+#define VCAgentProp "AGENT"
+#define VCAIFFProp "AIFF"
+#define VCAOLProp "AOL"
+#define VCAppleLinkProp "APPLELINK"
+#define VCAttachProp "ATTACH"
+#define VCAttendeeProp "ATTENDEE"
+#define VCATTMailProp "ATTMAIL"
+#define VCAudioContentProp "AUDIOCONTENT"
+#define VCAVIProp "AVI"
+#define VCBase64Prop "BASE64"
+#define VCBBSProp "BBS"
+#define VCBirthDateProp "BDAY"
+#define VCBMPProp "BMP"
+#define VCBodyProp "BODY"
+#define VCBusinessRoleProp "ROLE"
+#define VCCalProp "VCALENDAR"
+#define VCCaptionProp "CAP"
+#define VCCardProp "VCARD"
+#define VCCarProp "CAR"
+#define VCCategoriesProp "CATEGORIES"
+#define VCCellularProp "CELL"
+#define VCCGMProp "CGM"
+#define VCCharSetProp "CS"
+#define VCCIDProp "CID"
+#define VCCISProp "CIS"
+#define VCCityProp "L"
+#define VCClassProp "CLASS"
+#define VCCommentProp "NOTE"
+#define VCCompletedProp "COMPLETED"
+#define VCContentIDProp "CONTENT-ID"
+#define VCCountryNameProp "C"
+#define VCDAlarmProp "DALARM"
+#define VCDataSizeProp "DATASIZE"
+#define VCDayLightProp "DAYLIGHT"
+#define VCDCreatedProp "DCREATED"
+#define VCDeliveryLabelProp "LABEL"
+#define VCDescriptionProp "DESCRIPTION"
+#define VCDIBProp "DIB"
+#define VCDisplayStringProp "DISPLAYSTRING"
+#define VCDomesticProp "DOM"
+#define VCDTendProp "DTEND"
+#define VCDTstartProp "DTSTART"
+#define VCDueProp "DUE"
+#define VCEmailAddressProp "EMAIL"
+#define VCEncodingProp "ENCODING"
+#define VCEndProp "END"
+#define VCEventProp "VEVENT"
+#define VCEWorldProp "EWORLD"
+#define VCExNumProp "EXNUM"
+#define VCExDateProp "EXDATE"
+#define VCExpectProp "EXPECT"
+#define VCExtAddressProp "EXT ADD"
+#define VCFamilyNameProp "F"
+#define VCFaxProp "FAX"
+#define VCFullNameProp "FN"
+#define VCGeoProp "GEO"
+#define VCGeoLocationProp "GEO"
+#define VCGIFProp "GIF"
+#define VCGivenNameProp "G"
+#define VCGroupingProp "Grouping"
+#define VCHomeProp "HOME"
+#define VCIBMMailProp "IBMMail"
+#define VCInlineProp "INLINE"
+#define VCInternationalProp "INTL"
+#define VCInternetProp "INTERNET"
+#define VCISDNProp "ISDN"
+#define VCJPEGProp "JPEG"
+#define VCLanguageProp "LANG"
+#define VCLastModifiedProp "LAST-MODIFIED"
+#define VCLastRevisedProp "REV"
+#define VCLocationProp "LOCATION"
+#define VCLogoProp "LOGO"
+#define VCMailerProp "MAILER"
+#define VCMAlarmProp "MALARM"
+#define VCMCIMailProp "MCIMAIL"
+#define VCMessageProp "MSG"
+#define VCMETProp "MET"
+#define VCModemProp "MODEM"
+#define VCMPEG2Prop "MPEG2"
+#define VCMPEGProp "MPEG"
+#define VCMSNProp "MSN"
+#define VCNamePrefixesProp "NPRE"
+#define VCNameProp "N"
+#define VCNameSuffixesProp "NSUF"
+#define VCNoteProp "NOTE"
+#define VCOrgNameProp "ORGNAME"
+#define VCOrgProp "ORG"
+#define VCOrgUnit2Prop "OUN2"
+#define VCOrgUnit3Prop "OUN3"
+#define VCOrgUnit4Prop "OUN4"
+#define VCOrgUnitProp "OUN"
+#define VCPagerProp "PAGER"
+#define VCPAlarmProp "PALARM"
+#define VCParcelProp "PARCEL"
+#define VCPartProp "PART"
+#define VCPCMProp "PCM"
+#define VCPDFProp "PDF"
+#define VCPGPProp "PGP"
+#define VCPhotoProp "PHOTO"
+#define VCPICTProp "PICT"
+#define VCPMBProp "PMB"
+#define VCPostalBoxProp "BOX"
+#define VCPostalCodeProp "PC"
+#define VCPostalProp "POSTAL"
+#define VCPowerShareProp "POWERSHARE"
+#define VCPreferredProp "PREF"
+#define VCPriorityProp "PRIORITY"
+#define VCProcedureNameProp "PROCEDURENAME"
+#define VCProdIdProp "PRODID"
+#define VCProdigyProp "PRODIGY"
+#define VCPronunciationProp "SOUND"
+#define VCPSProp "PS"
+#define VCPublicKeyProp "KEY"
+#define VCQPProp "QP"
+#define VCQuickTimeProp "QTIME"
+#define VCQuotedPrintableProp "QUOTED-PRINTABLE"
+#define VCRDateProp "RDATE"
+#define VCRegionProp "R"
+#define VCRelatedToProp "RELATED-TO"
+#define VCRepeatCountProp "REPEATCOUNT"
+#define VCResourcesProp "RESOURCES"
+#define VCRNumProp "RNUM"
+#define VCRoleProp "ROLE"
+#define VCRRuleProp "RRULE"
+#define VCRSVPProp "RSVP"
+#define VCRunTimeProp "RUNTIME"
+#define VCSequenceProp "SEQUENCE"
+#define VCSnoozeTimeProp "SNOOZETIME"
+#define VCStartProp "START"
+#define VCStatusProp "STATUS"
+#define VCStreetAddressProp "STREET"
+#define VCSubTypeProp "SUBTYPE"
+#define VCSummaryProp "SUMMARY"
+#define VCTelephoneProp "TEL"
+#define VCTIFFProp "TIFF"
+#define VCTimeZoneProp "TZ"
+#define VCTitleProp "TITLE"
+#define VCTLXProp "TLX"
+#define VCTodoProp "VTODO"
+#define VCTranspProp "TRANSP"
+#define VCUniqueStringProp "UID"
+#define VCURLProp "URL"
+#define VCURLValueProp "URLVAL"
+#define VCValueProp "VALUE"
+#define VCVersionProp "VERSION"
+#define VCVideoProp "VIDEO"
+#define VCVoiceProp "VOICE"
+#define VCWAVEProp "WAVE"
+#define VCWMFProp "WMF"
+#define VCWorkProp "WORK"
+#define VCX400Prop "X400"
+#define VCX509Prop "X509"
+#define VCXRuleProp "XRULE"
+
+/* extensions for KOrganizer / KPilot */
+#define KPilotIdProp "X-PILOTID"
+#define KPilotStatusProp "X-PILOTSTAT"
+
+/* extensions for iMIP / iTIP */
+#define ICOrganizerProp "X-ORGANIZER"
+#define ICMethodProp "X-METHOD"
+#define ICRequestStatusProp "X-REQUEST-STATUS"
+
+typedef struct VObject VObject;
+
+typedef union ValueItem {
+ const char *strs;
+ const wchar_t *ustrs;
+ unsigned int i;
+ unsigned long l;
+ void *any;
+ VObject *vobj;
+ } ValueItem;
+
+struct VObject {
+ VObject *next;
+ const char *id;
+ VObject *prop;
+ unsigned short valType;
+ ValueItem val;
+ };
+
+typedef struct StrItem StrItem;
+
+struct StrItem {
+ StrItem *next;
+ const char *s;
+ unsigned int refCnt;
+ };
+
+typedef struct VObjectIterator {
+ VObject* start;
+ VObject* next;
+ } VObjectIterator;
+
+extern VObject* newVObject(const char *id);
+extern void deleteVObject(VObject *p);
+extern char* dupStr(const char *s, unsigned int size);
+extern void deleteStr(const char *p);
+extern void unUseStr(const char *s);
+
+extern void setVObjectName(VObject *o, const char* id);
+extern void setVObjectStringZValue(VObject *o, const char *s);
+extern void setVObjectStringZValue_(VObject *o, const char *s);
+extern void setVObjectUStringZValue(VObject *o, const wchar_t *s);
+extern void setVObjectUStringZValue_(VObject *o, const wchar_t *s);
+extern void setVObjectIntegerValue(VObject *o, unsigned int i);
+extern void setVObjectLongValue(VObject *o, unsigned long l);
+extern void setVObjectAnyValue(VObject *o, void *t);
+extern VObject* setValueWithSize(VObject *prop, void *val, unsigned int size);
+extern VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size);
+
+extern const char* vObjectName(VObject *o);
+extern const char* vObjectStringZValue(VObject *o);
+extern const wchar_t* vObjectUStringZValue(VObject *o);
+extern unsigned int vObjectIntegerValue(VObject *o);
+extern unsigned long vObjectLongValue(VObject *o);
+extern void* vObjectAnyValue(VObject *o);
+extern VObject* vObjectVObjectValue(VObject *o);
+extern void setVObjectVObjectValue(VObject *o, VObject *p);
+
+extern VObject* addVObjectProp(VObject *o, VObject *p);
+extern VObject* addProp(VObject *o, const char *id);
+extern VObject* addProp_(VObject *o, const char *id);
+extern VObject* addPropValue(VObject *o, const char *p, const char *v);
+extern VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
+extern VObject* addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
+extern VObject* addGroup(VObject *o, const char *g);
+extern void addList(VObject **o, VObject *p);
+
+extern VObject* isAPropertyOf(VObject *o, const char *id);
+
+extern VObject* nextVObjectInList(VObject *o);
+extern void initPropIterator(VObjectIterator *i, VObject *o);
+extern int moreIteration(VObjectIterator *i);
+extern VObject* nextVObject(VObjectIterator *i);
+
+extern char* writeMemVObject(char *s, int *len, VObject *o);
+extern char* writeMemVObjects(char *s, int *len, VObject *list);
+
+extern const char* lookupStr(const char *s);
+extern void cleanStrTbl();
+
+extern void cleanVObject(VObject *o);
+extern void cleanVObjects(VObject *list);
+
+extern const char* lookupProp(const char* str);
+extern const char* lookupProp_(const char* str);
+
+extern wchar_t* fakeUnicode(const char *ps, int *bytes);
+extern int uStrLen(const wchar_t *u);
+extern char* fakeCString(const wchar_t *u);
+
+extern void printVObjectToFile(char *fname,VObject *o);
+extern void printVObjectsToFile(char *fname,VObject *list);
+extern void writeVObjectToFile(char *fname, VObject *o);
+extern void writeVObjectsToFile(char *fname, VObject *list);
+
+extern int vObjectValueType(VObject *o);
+
+/* return type of vObjectValueType: */
+#define VCVT_NOVALUE 0
+ /* if the VObject has no value associated with it. */
+#define VCVT_STRINGZ 1
+ /* if the VObject has value set by setVObjectStringZValue. */
+#define VCVT_USTRINGZ 2
+ /* if the VObject has value set by setVObjectUStringZValue. */
+#define VCVT_UINT 3
+ /* if the VObject has value set by setVObjectIntegerValue. */
+#define VCVT_ULONG 4
+ /* if the VObject has value set by setVObjectLongValue. */
+#define VCVT_RAW 5
+ /* if the VObject has value set by setVObjectAnyValue. */
+#define VCVT_VOBJECT 6
+ /* if the VObject has value set by setVObjectVObjectValue. */
+
+extern const char** fieldedProp;
+
+extern void printVObject(FILE *fp,VObject *o);
+extern void writeVObject(FILE *fp, VObject *o);
+
+
+#if defined(__CPLUSPLUS__) || defined(__cplusplus)
+}
+#endif
+
+#endif /* __VOBJECT_H__ */
+
+