diff --git a/mailnews/addrbook/public/nsIMsgVCardService.idl b/mailnews/addrbook/public/nsIMsgVCardService.idl new file mode 100644 index 000000000000..cd4f37f40bf3 --- /dev/null +++ b/mailnews/addrbook/public/nsIMsgVCardService.idl @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is vCard service interface + * + * The Initial Developer of the Original Code is + * Seth Spitzer + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +%{C++ +#include "nsVCardObj.h" +#include "nsVCard.h" +%} + +[ptr] native VObject_ptr(VObject); +[ptr] native VObjectIterator_ptr(VObjectIterator); +[ptr] native const_char_ptr(const char); + +[uuid(45539703-94b4-47fb-afd0-14dfe174899f)] +interface nsIMsgVCardService : nsISupports { + [noscript, notxpcom] void cleanVObject(in VObject_ptr o); + [noscript, notxpcom] VObject_ptr nextVObjectInList(in VObject_ptr o); + [noscript, notxpcom] VObject_ptr parse_MIME(in string input, in unsigned long len); + [noscript, notxpcom] string fakeCString(in VObject_ptr o); + [noscript, notxpcom] VObject_ptr isAPropertyOf(in VObject_ptr o, in string id); + [noscript, notxpcom] string writeMemoryVObjects(in string s, out long len, in VObject_ptr list, in boolean expandSpaces); + [noscript, notxpcom] VObject_ptr nextVObject(in VObjectIterator_ptr i); + [noscript, notxpcom] void initPropIterator(in VObjectIterator_ptr i, in VObject_ptr o); + [noscript, notxpcom] long moreIteration(in VObjectIterator_ptr i); + [noscript, notxpcom] const_char_ptr vObjectName(in VObject_ptr o); + [noscript, notxpcom] string vObjectAnyValue(in VObject_ptr o); +}; diff --git a/mailnews/addrbook/src/nsMsgVCardService.cpp b/mailnews/addrbook/src/nsMsgVCardService.cpp new file mode 100644 index 000000000000..150b5a1555c5 --- /dev/null +++ b/mailnews/addrbook/src/nsMsgVCardService.cpp @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Seth Spitzer + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * The Original Code is vCard bridge code + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMsgVCardService.h" +#include "prmem.h" +#include "plstr.h" + +NS_IMPL_ISUPPORTS1(nsMsgVCardService, nsIMsgVCardService) + +nsMsgVCardService::nsMsgVCardService() +{ +} + +nsMsgVCardService::~nsMsgVCardService() +{ +} + +NS_IMETHODIMP_(void) nsMsgVCardService::CleanVObject(VObject * o) +{ + cleanVObject(o); +} + +NS_IMETHODIMP_(VObject *) nsMsgVCardService::NextVObjectInList(VObject * o) +{ + return nextVObjectInList(o); +} + +NS_IMETHODIMP_(VObject *) nsMsgVCardService::Parse_MIME(const char *input, PRUint32 len) +{ + return parse_MIME(input, (unsigned long)len); +} + +NS_IMETHODIMP_(char *) nsMsgVCardService::FakeCString(VObject * o) +{ + return fakeCString(vObjectUStringZValue(o)); +} + +NS_IMETHODIMP_(VObject *) nsMsgVCardService::IsAPropertyOf(VObject * o, const char *id) +{ + return isAPropertyOf(o,id); +} + +NS_IMETHODIMP_(char *) nsMsgVCardService::WriteMemoryVObjects(const char *s, PRInt32 *len, VObject * list, PRBool expandSpaces) +{ + return writeMemoryVObjects((char *)s, len, list, expandSpaces); +} + +NS_IMETHODIMP_(VObject *) nsMsgVCardService::NextVObject(VObjectIterator * i) +{ + return nextVObject(i); +} + +NS_IMETHODIMP_(void) nsMsgVCardService::InitPropIterator(VObjectIterator * i, VObject * o) +{ + initPropIterator(i,o); +} + +NS_IMETHODIMP_(PRInt32) nsMsgVCardService::MoreIteration(VObjectIterator * i) +{ + return ((PRInt32)moreIteration(i)); +} + +NS_IMETHODIMP_(const char *) nsMsgVCardService::VObjectName(VObject * o) +{ + return vObjectName(o); +} + +NS_IMETHODIMP_(char *) nsMsgVCardService::VObjectAnyValue(VObject * o) +{ + char *retval = (char *)PR_MALLOC(strlen((char *)vObjectAnyValue(o)) + 1); + if (retval) + PL_strcpy(retval, (char *) vObjectAnyValue(o)); + return retval; +} diff --git a/mailnews/addrbook/src/nsMsgVCardService.h b/mailnews/addrbook/src/nsMsgVCardService.h new file mode 100644 index 000000000000..e75ae7debdd9 --- /dev/null +++ b/mailnews/addrbook/src/nsMsgVCardService.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Seth Spitzer . + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * The Original Code is vCard bridge code + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsMsgVCardService_h___ +#define nsMsgVCardService_h___ + +#include "nsIMsgVCardService.h" +#include "nsISupports.h" + +class nsMsgVCardService : public nsIMsgVCardService +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMSGVCARDSERVICE + + nsMsgVCardService(); + virtual ~nsMsgVCardService(); +}; + +#endif /* nsMsgVCardService_h___ */ diff --git a/mailnews/addrbook/src/nsVCard.cpp b/mailnews/addrbook/src/nsVCard.cpp new file mode 100644 index 000000000000..519667a81ea2 --- /dev/null +++ b/mailnews/addrbook/src/nsVCard.cpp @@ -0,0 +1,1643 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/*************************************************************************** +(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 + * + * the vcc.y that _this_ vcc.c comes from is lost. + * I couldn't find it in the 4.x tree + * I bet we took it from IMC's original SDK, but the SDK has been taken down. + * see http://www.imc.org/imc-vcard/mail-archive/msg00460.html + * + * for what it's worth, see + * http://softwarestudio.org/libical/ + * http://lxr.mozilla.org/mozilla/source/other-licenses/libical/src/libicalvcal/vcc.y + * http://lxr.mozilla.org/mozilla/source/other-licenses/libical/src/libicalvcal/vcc.c + */ +#include "nsVCard.h" +#include "nsVCardObj.h" +#include "nsFileStream.h" +#include "prprf.h" + +#ifndef lint +char yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90"; +#endif +/*#line 2 "vcc.y" */ + +/* debugging utilities */ +#define DBG_(x) + +#ifndef _NO_LINE_FOLDING +#define _SUPPORT_LINE_FOLDING +#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 +#define YYPREFIX "mime_" + +#include "prmem.h" +#include "plstr.h" + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/**** Types, Constants ****/ + +#define YYDEBUG 0 /* 1 to compile in some debugging code */ +#define PR_MAXTOKEN 256 /* maximum token (line) length */ +#define YYSTACKSIZE 50 /* ~unref ?*/ +#define PR_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[PR_MAXLEVEL]; +static int ObjStackTop; + + +/* A helpful utility for the rest of the app. */ +#ifdef __cplusplus +extern "C" { +#endif + + extern void yyerror(char *s); + extern char** fieldedProp; + +#ifdef __cplusplus + }; +#endif + +int yyparse(); + +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(); +static int lexGeta(); +static int lexGetc_(); +static int lexGetc(); +static void lexSkipLookahead(); +static int lexLookahead(); +static void lexSkipWhite(); +static void lexClearToken(); +static char * lexStr(); +static char * lexGetDataFromBase64(); +static char * lexGetQuotedPrintable(); +static char * lexGet1Value(); +static char * lexGetWord(); +static void finiLex(); + +static VObject* parse_MIMEHelper(); + +/*static 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 mime_error_(char *s); + +/*#line 250 "vcc.y" */ +typedef union { + char *str; + VObject *vobj; + } YYSTYPE; +/*#line 253 "y_tab.c"*/ +#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 +#define YYERRCODE 256 +short yylhs[] = { -1, + 0, 7, 6, 6, 5, 5, 9, 3, 10, 3, + 8, 8, 14, 11, 11, 16, 12, 12, 15, 15, + 17, 18, 18, 1, 19, 13, 13, 2, 2, 21, + 4, 22, 4, 20, 20, 23, 23, 23, 26, 24, + 27, 24, 28, 25, 29, 25, +}; +short yylen[] = { 2, + 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, +}; +short yydefred[] = { 0, + 0, 0, 0, 5, 6, 0, 1, 0, 0, 0, + 0, 0, 15, 24, 0, 0, 0, 0, 10, 0, + 0, 38, 0, 0, 36, 37, 33, 3, 0, 8, + 11, 13, 0, 0, 0, 0, 31, 34, 0, 17, + 0, 0, 0, 42, 0, 46, 0, 21, 19, 28, + 0, 0, 40, 44, 0, 25, 14, 23, 0, 26, +}; +short yydgoto[] = { 3, + 15, 51, 4, 5, 6, 7, 12, 22, 8, 9, + 17, 18, 52, 42, 40, 29, 41, 48, 59, 23, + 10, 11, 24, 25, 26, 33, 34, 35, 36, +}; +short yysindex[] = { -227, + 0, 0, 0, 0, 0, 0, 0, -249, -262, -253, + -258, -227, 0, 0, 0, -234, -249, -215, 0, 0, + 0, 0, -223, -253, 0, 0, 0, 0, -247, 0, + 0, 0, -249, -222, -249, -225, 0, 0, -224, 0, + -247, -221, -220, 0, -218, 0, -206, 0, 0, 0, + -208, -207, 0, 0, -224, 0, 0, 0, -221, 0, +}; +short yyrindex[] = { 0, + -245, -254, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, -219, 0, -235, 0, 0, -244, + -250, 0, 0, -213, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -201, -255, 0, 0, 0, 0, -216, 0, 0, 0, + -205, 0, 0, 0, 0, 0, 0, 0, -255, 0, +}; +short yygindex[] = { 0, + -9, 0, 0, 0, 0, 47, 0, -8, 0, 0, + 0, 0, 2, 0, 19, 0, 0, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define YYTABLESIZE 268 +short yytable[] = { 16, + 4, 30, 13, 19, 29, 43, 13, 29, 31, 27, + 7, 39, 39, 32, 30, 20, 30, 21, 30, 14, + 9, 45, 43, 14, 43, 41, 45, 7, 39, 47, + 12, 30, 12, 12, 12, 12, 12, 1, 18, 2, + 16, 22, 32, 22, 37, 58, 46, 44, 14, 53, + 55, 56, 50, 54, 35, 57, 20, 27, 28, 49, + 60, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 2, +}; +short yycheck[] = { 8, + 0, 256, 256, 266, 260, 256, 256, 263, 17, 268, + 256, 256, 260, 268, 269, 269, 271, 271, 273, 273, + 266, 272, 273, 273, 33, 270, 35, 273, 273, 39, + 266, 266, 268, 269, 270, 271, 272, 265, 258, 267, + 260, 258, 258, 260, 268, 55, 272, 270, 273, 270, + 257, 260, 274, 272, 268, 263, 258, 263, 12, 41, + 59, 24, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 265, -1, 267, +}; +#define YYFINAL 3 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYPR_MAXTOKEN 274 +#if YYDEBUG +char *yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"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", +}; +char *yyrule[] = { +"$accept : mime", +"mime : vobjects", +"$$1 :", +"vobjects : vobject $$1 vobjects", +"vobjects : vobject", +"vobject : vcard", +"vobject : vcal", +"$$2 :", +"vcard : BEGIN_VCARD $$2 items END_VCARD", +"$$3 :", +"vcard : BEGIN_VCARD $$3 END_VCARD", +"items : item items", +"items : item", +"$$4 :", +"item : prop COLON $$4 values LINESEP", +"item : error", +"$$5 :", +"prop : name $$5 attr_params", +"prop : name", +"attr_params : attr_param attr_params", +"attr_params : attr_param", +"attr_param : SEMICOLON attr", +"attr : name", +"attr : name EQ name", +"name : ID", +"$$6 :", +"values : value SEMICOLON $$6 values", +"values : value", +"value : STRING", +"value :", +"$$7 :", +"vcal : BEGIN_VCAL $$7 calitems END_VCAL", +"$$8 :", +"vcal : BEGIN_VCAL $$8 END_VCAL", +"calitems : calitem calitems", +"calitems : calitem", +"calitem : eventitem", +"calitem : todoitem", +"calitem : items", +"$$9 :", +"eventitem : BEGIN_VEVENT $$9 items END_VEVENT", +"$$10 :", +"eventitem : BEGIN_VEVENT $$10 END_VEVENT", +"$$11 :", +"todoitem : BEGIN_VTODO $$11 items END_VTODO", +"$$12 :", +"todoitem : BEGIN_VTODO $$12 END_VTODO", +}; +#endif +#define yyclearin (yychar=(-1)) +#define yyerrok (yyerrflag=0) +#ifndef YYSTACKSIZE +#ifdef YYPR_MAXDEPTH +#define YYSTACKSIZE YYPR_MAXDEPTH +#else +#define YYSTACKSIZE 300 +#endif +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +#define yystacksize YYSTACKSIZE +short yyss[YYSTACKSIZE]; +YYSTYPE yyvs[YYSTACKSIZE]; +/*#line 444 "vcc.y"*/ +/******************************************************************************/ +static int pushVObject(const char *prop) + { + VObject *newObj; + if (ObjStackTop == PR_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; + } + +extern "C" void deleteString(char *p); + +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)); + } + } + deleteString((char *)value); + } + +static void enterProps(const char *s) + { + curProp = addGroup(curObj,s); + deleteString((char *)s); + } + +static void enterAttr(const char *s1, const char *s2) +{ + const char *p1, *p2 = nsnull; + p1 = lookupProp_(s1); + if (s2) { + VObject *a; + p2 = lookupProp_(s2); + a = addProp(curProp,p1); + setVObjectStringZValue(a,p2); + } + else + addProp(curProp,p1); + if (PL_strcasecmp(p1,VCBase64Prop) == 0 || (s2 && PL_strcasecmp(p2,VCBase64Prop)==0)) + lexPushMode(L_BASE64); + else if (PL_strcasecmp(p1,VCQuotedPrintableProp) == 0 + || (s2 && PL_strcasecmp(p2,VCQuotedPrintableProp)==0)) + lexPushMode(L_QUOTED_PRINTABLE); + deleteString((char *)s1); deleteString((char *)s2); +} + + +#define PR_MAX_LEX_LOOKAHEAD_0 32 +#define PR_MAX_LEX_LOOKAHEAD 64 +#define PR_MAX_LEX_MODE_STACK_SIZE 10 +#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) + +struct LexBuf { + /* input */ + nsInputFileStream *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[PR_MAX_LEX_LOOKAHEAD]; + unsigned long getPtr; + /* context stack */ + unsigned long lexModeStackTop; + enum LexMode lexModeStack[PR_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 == (PR_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;iread(&c, 1); + if (status != 1) + return -1; + else + return c; + } +} + +static int lexGeta() + { + ++lexBuf.len; + return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); + } + +static int lexGeta_(int i) + { + ++lexBuf.len; + return (lexBuf.buf[(lexBuf.getPtr+i)%PR_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) % PR_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)%PR_MAX_LEX_LOOKAHEAD]: + lexGeta_(1); + if (a == '\n') { + lexSkipLookahead(); + } + lexBuf.buf[lexBuf.getPtr] = c = '\n'; + } + else if (c == '\n') { + int a = (lexBuf.len>1)? + lexBuf.buf[lexBuf.getPtr+1]: + 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) % PR_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) % PR_MAX_LEX_LOOKAHEAD; + } + } + +static void lexClearToken() + { + lexBuf.strsLen = 0; + } + +static void lexAppendc(int c) + { + 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*) PR_Realloc(lexBuf.strs,lexBuf.maxToken); + } + } + +static char* lexStr() { + return dupStr(lexBuf.strs,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(); + while (c != EOF && !PL_strchr("\t\n ;:=",(char)c)) { + lexAppendc(c); + lexSkipLookahead(); + c = lexLookahead(); + } + lexAppendc(0); + return lexStr(); + } + +#if 0 +static void lexPushLookahead(char *s, int len) { + int putptr; + if (len == 0) len = PL_strlen(s); + putptr = lexBuf.getPtr - len; + /* this function assumes that length of word to push back + / is not greater than PR_MAX_LEX_LOOKAHEAD. + */ + if (putptr < 0) putptr += PR_MAX_LEX_LOOKAHEAD; + lexBuf.getPtr = putptr; + while (*s) { + lexBuf.buf[putptr] = *s++; + putptr = (putptr + 1) % PR_MAX_LEX_LOOKAHEAD; + } + lexBuf.len += len; + } +#endif + +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 += PR_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 PR_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 < (PR_MAX_LEX_LOOKAHEAD_0)) { + c = lexGetc(); + len++; + if (c == EOF || PL_strchr("\t\n ;:=", (char)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) { + /* support 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 size = 0; */ + 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 + + +#ifndef _SUPPORT_LINE_FOLDING +static char* lexGetStrUntil(char *termset) { + int c = lexLookahead(); + lexClearToken(); + while (c != EOF && !PL_strchr(termset,c)) { + lexAppendc(c); + lexSkipLookahead(); + c = lexLookahead(); + } + lexAppendc(0); + return c==EOF?0:lexStr(); + } +#endif /* ! _SUPPORT_LINE_FOLDING */ + +static int match_begin_name(int end) { + char *n = lexLookaheadWord(); + int token = ID; + if (n) { + if (!PL_strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; + else if (!PL_strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; + else if (!PL_strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; + else if (!PL_strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; + deleteString(n); + return token; + } + return 0; + } + +#if defined(XP_MAC) && defined(__MWERKS__) +#pragma warn_possunwant off +#pragma require_prototypes off +#endif + +void initLex(const char *inputstring, unsigned long inputlen, nsInputFileStream *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 = PR_MAXTOKEN; + lexBuf.strs = (char*)PR_CALLOC(PR_MAXTOKEN); + lexBuf.strsLen = 0; + + } + +static void finiLex() { + PR_FREEIF(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 */ + PR_FREEIF (bytes); + PR_FREEIF(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*)PR_CALLOC(bytesMax); + } + else { + bytesMax <<= 2; + oldBytes = bytes; + bytes = (unsigned char*)PR_Realloc(bytes,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); + PR_FREEIF(bytes); + } + else if (oldBytes) { + setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); + PR_FREEIF(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(); + deleteString(yylval.str); + DBG_(("db: begin/end %d\n", token)); + return token; + } + return 0; + } + +static char* lexGetQuotedPrintable() + { + char cur; +/* unsigned long len = 0; */ + + lexClearToken(); + do { + cur = lexGetc(); + switch (cur) { + case '=': { + int c = 0; + int next[2]; + int tab [1]; + 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') { + tab[0] = lexGetc(); + if (tab[0] == '\t') + lexSkipWhite(); + ++mime_lineNum; + } + else { + lexAppendc(cur); + /* 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 ';': { + lexPushLookaheadc(';'); + 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 token = 0; */ + + int lexmode = LEXMODE(); + if (lexmode == L_VALUES) { + int c = lexGetc(); + if (c == ';') { + DBG_(("db: SEMICOLON\n")); +#ifdef _SUPPORT_LINE_FOLDING + lexPushLookaheadc(c); + handleMoreRFC822LineBreak(c); + lexSkipLookahead(); +#endif + return SEMICOLON; + } + else if (PL_strchr("\n",(char)c)) { + ++mime_lineNum; + /* consume all line separator(s) adjacent to each other */ + c = lexLookahead(); + while (PL_strchr("\n",(char)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 (PL_strchr("\n",(char)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 whitespace in this mode */ + case '\t': + case ' ': continue; + case '\n': { + ++mime_lineNum; + continue; + } + case EOF: return 0; + break; + default: { + lexPushLookaheadc(c); + if (isalpha(c)) { + char *t = lexGetWord(); + yylval.str = t; + if (!PL_strcasecmp(t, "BEGIN")) { + return match_begin_end_name(0); + } + else if (!PL_strcasecmp(t,"END")) { + return match_begin_end_name(1); + } + else { + DBG_(("db: ID '%s'\n", t)); + return ID; + } + } + else { + /* unknow 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(nsInputFileStream *file) +{ + VObject *result; + long startPos; + + initLex(0,(unsigned long)-1,file); + startPos = file->tell(); + if (!(result = parse_MIMEHelper())) { + file->seek(startPos); + } + return result; +} + +VObject* parse_MIME_FromFileName(nsFileSpec *fname) +{ +#if !defined(MOZADDRSTANDALONE) + nsInputFileStream *fp = new nsInputFileStream(*fname); + if (fp) + { + VObject* o = parse_MIME_FromFile(fp); + fp->close(); + return o; + } + else { + char msg[80]; + PR_snprintf(msg, sizeof(msg), "Can't open file for reading\n"); + mime_error_(msg); + return 0; + } +#else + NS_ASSERTION(FALSE, "1.5 06 Jan 2000 08:00"); + return 0; +#endif +} + +static MimeErrorHandler mimeErrorHandler; + +void registerMimeErrorHandler(MimeErrorHandler me) + { + mimeErrorHandler = me; + } + +void mime_error(char *s) +{ + char msg[256]; + if (mimeErrorHandler) { + PR_snprintf(msg, sizeof(msg), "%s at line %d", s, mime_lineNum); + mimeErrorHandler(msg); + } +} + +void mime_error_(char *s) + { + if (mimeErrorHandler) { + mimeErrorHandler(s); + } + } + +/*#line 1221 "y_tab.c"*/ +#define YYABORT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +yyparse() +{ + register int yym, yyn, yystate; +#if YYDEBUG + register char *yys; + extern char *getenv(); + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if ((yyn = yydefred[yystate])) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", yystate, + yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, shifting to state %d\n", + yystate, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +/*yynewerror: */ + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, error recovery shifting\ + to state %d\n", *yyssp, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("yydebug: error recovery discarding state %d\n", + *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, error recovery discards token %d (%s)\n", + yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, reducing by rule %d (%s)\n", + yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 2: +/*#line 282 "vcc.y"*/ +{ addList(&vObjList, yyvsp[0].vobj ); curObj = 0; } +break; +case 4: +/*#line 285 "vcc.y"*/ +{ addList(&vObjList, yyvsp[0].vobj ); curObj = 0; } +break; +case 7: +/*#line 294 "vcc.y"*/ +{ + lexPushMode(L_VCARD); + if (!pushVObject(VCCardProp)) YYERROR; + } +break; +case 8: +/*#line 299 "vcc.y"*/ +{ + lexPopMode(0); + yyval.vobj = popVObject(); + } +break; +case 9: +/*#line 304 "vcc.y"*/ +{ + lexPushMode(L_VCARD); + if (!pushVObject(VCCardProp)) YYERROR; + } +break; +case 10: +/*#line 309 "vcc.y"*/ +{ + lexPopMode(0); + yyval.vobj = popVObject(); + } +break; +case 13: +/*#line 320 "vcc.y"*/ +{ + lexPushMode(L_VALUES); + } +break; +case 14: +/*#line 324 "vcc.y"*/ +{ + if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) + lexPopMode(0); + lexPopMode(0); + } +break; +case 16: +/*#line 332 "vcc.y"*/ +{ + enterProps(yyvsp[0].str ); + } +break; +case 18: +/*#line 337 "vcc.y"*/ +{ + enterProps(yyvsp[0].str ); + } +break; +case 22: +/*#line 350 "vcc.y"*/ +{ + enterAttr(yyvsp[0].str ,0); + } +break; +case 23: +/*#line 354 "vcc.y"*/ +{ + enterAttr(yyvsp[-2].str ,yyvsp[0].str ); + + } +break; +case 25: +/*#line 363 "vcc.y"*/ +{ enterValues(yyvsp[-1].str ); } +break; +case 27: +/*#line 365 "vcc.y"*/ +{ enterValues(yyvsp[0].str ); } +break; +case 29: +/*#line 370 "vcc.y"*/ +{ yyval.str = 0; } +break; +case 30: +/*#line 375 "vcc.y"*/ +{ if (!pushVObject(VCCalProp)) YYERROR; } +break; +case 31: +/*#line 378 "vcc.y"*/ +{ yyval.vobj = popVObject(); } +break; +case 32: +/*#line 380 "vcc.y"*/ +{ if (!pushVObject(VCCalProp)) YYERROR; } +break; +case 33: +/*#line 382 "vcc.y"*/ +{ yyval.vobj = popVObject(); } +break; +case 39: +/*#line 397 "vcc.y"*/ +{ + lexPushMode(L_VEVENT); + if (!pushVObject(VCEventProp)) YYERROR; + } +break; +case 40: +/*#line 403 "vcc.y"*/ +{ + lexPopMode(0); + popVObject(); + } +break; +case 41: +/*#line 408 "vcc.y"*/ +{ + lexPushMode(L_VEVENT); + if (!pushVObject(VCEventProp)) YYERROR; + } +break; +case 42: +/*#line 413 "vcc.y"*/ +{ + lexPopMode(0); + popVObject(); + } +break; +case 43: +/*#line 421 "vcc.y"*/ +{ + lexPushMode(L_VTODO); + if (!pushVObject(VCTodoProp)) YYERROR; + } +break; +case 44: +/*#line 427 "vcc.y"*/ +{ + lexPopMode(0); + popVObject(); + } +break; +case 45: +/*#line 432 "vcc.y"*/ +{ + lexPushMode(L_VTODO); + if (!pushVObject(VCTodoProp)) YYERROR; + } +break; +case 46: +/*#line 437 "vcc.y"*/ +{ + lexPopMode(0); + popVObject(); + } +break; +/*#line 1520 "y_tab.c"*/ + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state 0 to\ + state %d\n", YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", + YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state %d \ +to state %d\n", *yyssp, yystate); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/mailnews/addrbook/src/nsVCard.h b/mailnews/addrbook/src/nsVCard.h new file mode 100644 index 000000000000..0471e2b3835c --- /dev/null +++ b/mailnews/addrbook/src/nsVCard.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +/*************************************************************************** +(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 "prtypes.h" +#include "nsFileStream.h" +#include "nsFileSpec.h" +#include "nsVCardObj.h" + +PR_BEGIN_EXTERN_C + +VObject* parse_MIME(const char *input, unsigned long len); + +VObject* parse_MIME_FromFile(nsInputFileStream *file); + +VObject* parse_MIME_FromFileName(nsFileSpec * fname); + +typedef void (*MimeErrorHandler)(char *); + +void registerMimeErrorHandler(MimeErrorHandler); + +PR_END_EXTERN_C + +#endif /* __VCC_H__ */ diff --git a/mailnews/addrbook/src/nsVCardObj.cpp b/mailnews/addrbook/src/nsVCardObj.cpp new file mode 100644 index 000000000000..9ca856f9b688 --- /dev/null +++ b/mailnews/addrbook/src/nsVCardObj.cpp @@ -0,0 +1,1579 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/*************************************************************************** +(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. + +***************************************************************************/ + +/* + * doc: vobject and APIs to construct vobject, APIs pretty print + * vobject, and convert a vobject into its textual representation. + */ + +#include "prlog.h" +#include "nsVCard.h" +#include "nsVCardObj.h" +#include "prmem.h" +#include "plstr.h" +#include "msgCore.h" +#include "prprf.h" + +/* debugging utilities */ +#define DBG_(x) + +#ifdef __cplusplus +extern "C" { +#endif + + char **fieldedProp; + +#ifdef __cplusplus + }; +#endif + + + +static VObject* newVObject_(const char *id); +#if 0 +static int vObjectValueType(VObject *o); +static void initVObjectIterator(VObjectIterator *i, VObject *o); +#endif + +/*---------------------------------------------------------------------- + The following functions involve with memory allocation: + newVObject + deleteVObject + dupStr + deleteString + newStrItem + deleteStrItem + ----------------------------------------------------------------------*/ + +static PRBool needsQuotedPrintable (const char *s) +{ + const unsigned char *p = (const unsigned char *)s; + + while (*p) { + if (*p & 0x80 || *p == '\015' || *p == '\012') + return PR_TRUE; + p++; + } + + return PR_FALSE; +} + +VObject* newVObject_(const char *id) +{ + VObject *p = (VObject*) new(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) +{ + unUseStr(p->id); + delete (p); +} + +char* dupStr(const char *s, unsigned int size) +{ + char *t; + if (size == 0) { + size = PL_strlen(s); + } + t = (char*)PR_CALLOC(size+1); + if (t) { + memcpy(t,s,size); + t[size] = 0; + return t; + } + else { + return (char*)0; + } +} + +static StrItem* newStrItem(const char *s, StrItem *next) +{ + StrItem *p = (StrItem*)PR_CALLOC(sizeof(StrItem)); + p->next = next; + p->s = s; + p->refCnt = 1; + return p; +} + +extern "C" +void deleteString(char *p) +{ + if (p) + PR_Free ((void*)p); +} + +extern "C" +void deleteStrItem(StrItem *p) +{ + if (p) + PR_FREEIF (p); +} + + + +/*---------------------------------------------------------------------- + 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 vwchar_t* vObjectUStringZValue(VObject *o) +{ + return USTRINGZ_VALUE_OF(o); +} + +void setVObjectUStringZValue(VObject *o, const vwchar_t *s) +{ + USTRINGZ_VALUE_OF(o) = (vwchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); + VALUE_TYPE(o) = VCVT_USTRINGZ; +} + +void setVObjectUStringZValue_(VObject *o, const vwchar_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; +} + +#if 0 +int vObjectValueType(VObject *o) +{ + return VALUE_TYPE(o); +} +#endif + + +/*---------------------------------------------------------------------- + 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((const char *)val,size); + return setValueWithSize_(prop,p,p?size:0); +} + +void initPropIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->prop; + i->next = 0; +} + +#if 0 +void initVObjectIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->next; + i->next = 0; +} +#endif + +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 (!PL_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 = PL_strrchr(g,'.'); + if (dot) { + VObject *p, *t; + char *gs, *n = dot+1; + gs = dupStr(g,0); /* so we can write to it. */ + t = p = addProp_(o,lookupProp(n)); + dot = PL_strrchr(gs,'.'); + *dot = 0; + do { + dot = PL_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); + deleteString(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); + if (v) { + setVObjectUStringZValue_(prop, fakeUnicode(v,0)); + if (needsQuotedPrintable (v)) { + if (PL_strcasecmp (VCCardProp, vObjectName(o)) == 0) + addProp (prop, VCQuotedPrintableProp); + else + addProp (o, VCQuotedPrintableProp); + } + } + else + setVObjectUStringZValue_(prop, fakeUnicode("",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 indent(nsOutputFileStream *fp, int level) +{ + int i; + for (i=0;iwrite(" ", 1); + } +} + +static void printValue(nsOutputFileStream *fp, VObject *o, int level) +{ + char *buf = nsnull; + + switch (VALUE_TYPE(o)) { + case VCVT_USTRINGZ: { + char c; + char *t,*s; + s = t = fakeCString(USTRINGZ_VALUE_OF(o)); + fp->write("'",1); + while (c=*t,c) { + fp->write(&c,1); + if (c == '\n') indent(fp,level+2); + t++; + } + fp->write("'",1); + deleteString(s); + break; + } + case VCVT_STRINGZ: { + char c; + char *str = &c; + const char *s = STRINGZ_VALUE_OF(o); + fp->write("'",1); + while (c=*s,c) { + fp->write(str,1); + if (c == '\n') indent(fp,level+2); + s++; + } + fp->write("'",1); + break; + } + case VCVT_UINT: + buf = PR_smprintf("%d", INTEGER_VALUE_OF(o)); + if (buf) + { + fp->write(buf, strlen(buf)); + PR_FREEIF(buf); + } + break; + + case VCVT_ULONG: + buf = PR_smprintf("%ld", LONG_VALUE_OF(o)); + if (buf) + { + fp->write(buf, strlen(buf)); + PR_FREEIF(buf); + } + break; + + case VCVT_RAW: + fp->write("[raw data]", 10); + break; + + case VCVT_VOBJECT: + fp->write("[vobject]\n", 11); + printVObject_(fp,VOBJECT_VALUE_OF(o),level+1); + break; + + case 0: + fp->write("[none]", 6); + break; + default: + fp->write("[unknown]", 9); + break; + } +} + +static void printNameValue(nsOutputFileStream *fp,VObject *o, int level) +{ + char *buf; + + indent(fp,level); + if (NAME_OF(o)) + { + buf = PR_smprintf("%s", NAME_OF(o)); + if (buf) + { + fp->write(buf, strlen(buf)); + PR_FREEIF(buf); + } + } + + if (VALUE_TYPE(o)) + { + fp->write("=",1); + printValue(fp,o, level); + } + + fp->write("\n", 1); +} + +void printVObject_(nsOutputFileStream *fp, VObject *o, int level) +{ + VObjectIterator t; + if (o == 0) { + fp->write("[NULL]\n", 7); + return; + } + + printNameValue(fp,o,level); + initPropIterator(&t,o); + + while (moreIteration(&t)) + { + VObject *eachProp = nextVObject(&t); + printVObject_(fp,eachProp,level+1); + } +} + +void printVObject(nsOutputFileStream *fp,VObject *o) +{ + printVObject_(fp,o,0); +} + +void printVObjectToFile(nsFileSpec *fname, VObject *o) +{ +#if !defined(MOZADDRSTANDALONE) + nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600); + + if (fp) { + printVObject(fp,o); + fp->close(); + } +#else + NS_ASSERTION(PR_FALSE, "1.10 06 Jan 2000 08:01"); +#endif +} + +void printVObjectsToFile(nsFileSpec *fname,VObject *list) +{ +#if !defined(MOZADDRSTANDALONE) + nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600); + if (fp) { + while (list) { + printVObject(fp,list); + list = nextVObjectInList(list); + } + fp->close(); + } +#else + NS_ASSERTION(PR_FALSE, "1.10 06 Jan 2000 08:01"); +#endif +} + + +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. */ + if ((char*) STRINGZ_VALUE_OF(o)) + PR_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; +} + +void unUseStr(const char *s) +{ + StrItem *t, *p; + unsigned int h = hashStr(s); + if ((t = strTbl[h]) != 0) { + p = t; + do { + if (PL_strcasecmp(t->s,s) == 0) { + t->refCnt--; + if (t->refCnt == 0) { + if (t == strTbl[h]) { + strTbl[h] = t->next; + } + else { + p->next = t->next; + } + deleteString((char *)t->s); + deleteStrItem(t); + return; + } + } + p = t; + t = t->next; + } while (t); + } +} + +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 + }; + +static const char *coolTalkFields[] = { + VCCooltalkAddress, + VCUseServer, + 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 }, + { VCExpDateProp, 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 }, + { VCCooltalk, 0, coolTalkFields, 0 }, + { VCCooltalkAddress, 0, 0, 0 }, + { VCUseServer, 0, 0, 0 }, + { VCUseHTML, 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 (PL_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 (PL_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 (PL_strcasecmp(str, propNames[i].name) == 0) { + const char *s; + fieldedProp = (char **)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 { + nsOutputFileStream *fp; + char *s; + int len; + int limit; + int alloc:1; + int fail:1; + } OFile; */ + +static void appendcOFile_(OFile *fp, char c) +{ + if (fp->fail) + return; + if (fp->fp) { + fp->fp->write(&c,1); + } + 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 = (char *)PR_Realloc(fp->s,fp->limit); + if (fp->s) goto stuff; + } + if (fp->alloc) + PR_FREEIF(fp->s); + fp->s = 0; + fp->fail = 1; + } +} + +static void appendcOFile(OFile *fp, char c) +{ +/* int i = 0; */ + if (c == '\n') { + /* write out as */ + /* for (i = 0; i < LINEBREAK_LEN; i++) + appendcOFile_(fp,LINEBREAK [ i ]); */ + appendcOFile_(fp,0xd); + appendcOFile_(fp,0xa); + } + else + appendcOFile_(fp,c); +} + +static void appendsOFile(OFile *fp, const char *s) +{ + int i, slen; + slen = PL_strlen (s); + for (i=0; ifp = 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 PR_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==PR_MAXQUADS-1?"\n" : ""))); + numQuads = (numQuads + 1) % PR_MAXQUADS; + } + appendcOFile(fp,'\n'); + + return 1; +} + +static void writeQPString(OFile *fp, const char *s) +{ + const unsigned char *p = (const unsigned char *)s; + int current_column = 0; + static const char hexdigits[] = "0123456789ABCDEF"; + PRBool white = PR_FALSE; + PRBool contWhite = PR_FALSE; + PRBool mb_p = PR_FALSE; + + if (needsQuotedPrintable (s)) + { + while (*p) { + if (*p == nsCRT::CR || *p == nsCRT::LF) + { + /* Whitespace cannot be allowed to occur at the end of the line. + So we encode " \n" as " =\n\n", that is, the whitespace, a + soft line break, and then a hard line break. + */ + + if (white) + { + appendcOFile(fp,'='); + appendcOFile(fp,'\n'); + appendcOFile(fp,'\t'); + appendsOFile(fp,"=0D"); + appendsOFile(fp,"=0A"); + appendcOFile(fp,'='); + appendcOFile(fp,'\n'); + appendcOFile(fp,'\t'); + } + else + { + appendsOFile(fp,"=0D"); + appendsOFile(fp,"=0A"); + appendcOFile(fp,'='); + appendcOFile(fp,'\n'); + appendcOFile(fp,'\t'); + contWhite = PR_FALSE; + } + + /* If its CRLF, swallow two chars instead of one. */ + if (*p == nsCRT::CR && *(p+1) == nsCRT::LF) + p++; + white = PR_FALSE; + current_column = 0; + } + else + { + if ((*p >= 33 && *p <= 60) || /* safe printing chars */ + (*p >= 62 && *p <= 126) || + (mb_p && (*p == 61 || *p == 127 || *p == 0x1B))) + { + appendcOFile(fp,*p); + current_column++; + white = PR_FALSE; + contWhite = PR_FALSE; + } + else if (*p == ' ' || *p == '\t') /* whitespace */ + { + if (contWhite) + { + appendcOFile(fp,'='); + appendcOFile(fp,hexdigits[*p >> 4]); + appendcOFile(fp,hexdigits[*p & 0xF]); + current_column += 3; + contWhite = PR_FALSE; + } + else + { + appendcOFile(fp,*p); + current_column++; + } + white = PR_TRUE; + } + else /* print as =FF */ + { + appendcOFile(fp,'='); + appendcOFile(fp,hexdigits[*p >> 4]); + appendcOFile(fp,hexdigits[*p & 0xF]); + current_column += 3; + white = PR_FALSE; + contWhite = PR_FALSE; + } + + NS_ASSERTION(current_column <= 76, "1.10 06 Jan 2000 08:01"); /* Hard limit required by spec */ + + if (current_column >= 73 || ((*(p+1) == ' ') && (current_column + 3 >= 73))) /* soft line break: "=\r\n" */ + { + appendcOFile(fp,'='); + appendcOFile(fp,'\n'); + appendcOFile(fp,'\t'); + current_column = 0; + if (white) + contWhite = PR_TRUE; + else + contWhite = PR_FALSE; + white = PR_FALSE; + } + } + p++; + } /* while */ + } /* if */ + else + { + while (*p) { + appendcOFile(fp,*p); + p++; + } + } +} + + +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)); + writeQPString(fp, s); + deleteString(s); + break; + } + case VCVT_STRINGZ: { + writeQPString(fp, STRINGZ_VALUE_OF(o)); + 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, int* length) +{ + int ilen = 0; + if (NAME_OF(o)) { + struct PreDefProp *pi; + pi = lookupPropInfo(NAME_OF(o)); + if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; + appendcOFile(fp,';'); + if (*length != -1) + (*length)++; + appendsOFile(fp,NAME_OF(o)); + if (*length != -1) + (*length) += PL_strlen (NAME_OF(o)); + } + else { + appendcOFile(fp,';'); + (*length)++; + } + if (VALUE_TYPE(o)) { + appendcOFile(fp,'='); + if (*length != -1) { + (*length)++; + for (ilen = 0; ilen < MAXMOZPROPNAMESIZE - (*length); ilen++) + appendcOFile(fp,' '); + } + writeValue(fp,o,0); + } +} + +static void writeGroup(OFile *fp, VObject *o) +{ + char buf1[256]; + char buf2[256]; + PL_strcpy(buf1,NAME_OF(o)); + while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { + PL_strcpy(buf2,STRINGZ_VALUE_OF(o)); + PL_strcat(buf2,"."); + PL_strcat(buf2,buf1); + PL_strcpy(buf1,buf2); + } + appendsOFile(fp,buf1); +} + +static int inList(const char **list, const char *s) +{ + if (list == 0) return 0; + while (*list) { + if (PL_strcasecmp(*list,s) == 0) return 1; + list++; + } + return 0; +} + +static void writeProp(OFile *fp, VObject *o) +{ + int length = -1; + //int ilen = 0; + + 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 (PL_strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) + writeAttrValue(fp,eachProp, &length); + } + if (fields_) { + int i = 0, n = 0; + const char** fields = fields_; + /* output prop as fields */ + appendcOFile(fp,':'); + while (*fields) { + VObject *tt = isAPropertyOf(o,*fields); + i++; + if (tt) n = i; + fields++; + } + fields = fields_; + for (i=0;iflags & 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(nsOutputFileStream *fp, VObject *o) +{ + OFile ofp; + initOFile(&ofp,fp); + writeVObject_(&ofp,o); +} + +void writeVObjectToFile(nsFileSpec *fname, VObject *o) +{ +#if !defined(MOZADDRSTANDALONE) + nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600); + + if (fp) { + writeVObject(fp,o); + fp->close(); + } +#else + NS_ASSERTION(PR_FALSE, "1.10 06 Jan 2000 08:01"); +#endif +} + +void writeVObjectsToFile(nsFileSpec *fname, VObject *list) +{ +#if !defined(MOZADDRSTANDALONE) + nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600); + if (fp) { + while (list) { + writeVObject(fp,list); + list = nextVObjectInList(list); + } + fp->close(); + } +#else + NS_ASSERTION(PR_FALSE, "1.10 06 Jan 2000 08:01"); +#endif +} + +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; +} + +extern "C" +char * writeMemoryVObjects(char *s, int *len, VObject *list, PRBool expandSpaces) +{ + 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. + ----------------------------------------------------------------------*/ +vwchar_t* fakeUnicode(const char *ps, int *bytes) +{ + vwchar_t *r, *pw; + int len = strlen(ps)+1; + + pw = r = (vwchar_t*)PR_CALLOC(sizeof(vwchar_t)*len); + if (bytes) + *bytes = len * sizeof(vwchar_t); + + while (*ps) { + if (*ps == '\n') + *pw = (vwchar_t)0x2028; + else if (*ps == '\r') + *pw = (vwchar_t)0x2029; + else + *pw = (vwchar_t)(unsigned char)*ps; + ps++; pw++; + } + *pw = (vwchar_t)0; + + return r; +} + +int uStrLen(const vwchar_t *u) +{ + int i = 0; + while (*u != (vwchar_t)0) { u++; i++; } + return i; +} + +char* fakeCString(const vwchar_t *u) +{ + char *s, *t; + int len = uStrLen(u) + 1; + t = s = (char*)PR_CALLOC(len); + while (*u) { + if (*u == (vwchar_t)0x2028) + *t = '\n'; + else if (*u == (vwchar_t)0x2029) + *t = '\r'; + else + *t = (char)*u; + u++; t++; + } + *t = 0; + return s; +} + +const char* lookupStr(const char *s) +{ + StrItem *t; + unsigned int h = hashStr(s); + if ((t = strTbl[h]) != 0) { + do { + if (PL_strcasecmp(t->s,s) == 0) { + t->refCnt++; + return t->s; + } + t = t->next; + } while (t); + } + s = dupStr(s,0); + strTbl[h] = newStrItem(s,strTbl[h]); + return s; +} diff --git a/mailnews/addrbook/src/nsVCardObj.h b/mailnews/addrbook/src/nsVCardObj.h new file mode 100644 index 000000000000..9dab7d499b3b --- /dev/null +++ b/mailnews/addrbook/src/nsVCardObj.h @@ -0,0 +1,443 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/*************************************************************************** +(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 + +/* +Unfortunately, on the Mac (and possibly other platforms) with our current, out-dated +libraries (Plauger), |wchar_t| is defined incorrectly, which breaks vcards. + +We can't fix Plauger because it doesn't come with source. Later, when we +upgrade to MSL, we can make this evil hack go away. In the mean time, +vcards are not allowed to use the (incorrectly defined) |wchar_t| type. Instead, +they will use an appropriately defined local type |vwchar_t|. +*/ + +#ifdef XP_MAC + typedef uint16 vwchar_t; +#else + typedef wchar_t vwchar_t; +#endif + +#include "prtypes.h" +#include "nsFileSpec.h" + +class nsOutputFileStream; + +PR_BEGIN_EXTERN_C + +#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 VCExpDateProp "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" +#define VCCooltalk "x-mozilla-cpt" +#define VCCooltalkAddress "x-moxilla-cpadr" +#define VCUseServer "x-mozilla-cpsrv" +#define VCUseHTML "x-mozilla-html" + +/* 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. */ + +#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 + +typedef struct VObject VObject; + +typedef union ValueItem { + const char *strs; + const vwchar_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 OFile { + nsOutputFileStream *fp; + char *s; + int len; + int limit; + int alloc:1; + int fail:1; + } OFile; + +typedef struct VObjectIterator { + VObject* start; + VObject* next; + } VObjectIterator; + +VObject* newVObject(const char *id); +void deleteVObject(VObject *p); +char* dupStr(const char *s, unsigned int size); +extern "C" void deleteString(char *p); +void unUseStr(const char *s); + +void setVObjectName(VObject *o, const char* id); +void setVObjectStringZValue(VObject *o, const char *s); +void setVObjectStringZValue_(VObject *o, const char *s); +void setVObjectUStringZValue(VObject *o, const vwchar_t *s); +void setVObjectUStringZValue_(VObject *o, const vwchar_t *s); +void setVObjectIntegerValue(VObject *o, unsigned int i); +void setVObjectLongValue(VObject *o, unsigned long l); +void setVObjectAnyValue(VObject *o, void *t); +VObject* setValueWithSize(VObject *prop, void *val, unsigned int size); +VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size); + +const char* vObjectName(VObject *o); +const char* vObjectStringZValue(VObject *o); +const vwchar_t* vObjectUStringZValue(VObject *o); +unsigned int vObjectIntegerValue(VObject *o); +unsigned long vObjectLongValue(VObject *o); +void* vObjectAnyValue(VObject *o); +VObject* vObjectVObjectValue(VObject *o); +void setVObjectVObjectValue(VObject *o, VObject *p); + +VObject* addVObjectProp(VObject *o, VObject *p); +VObject* addProp(VObject *o, const char *id); +VObject* addProp_(VObject *o, const char *id); +VObject* addPropValue(VObject *o, const char *p, const char *v); +VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size); +VObject* addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size); +VObject* addGroup(VObject *o, const char *g); +void addList(VObject **o, VObject *p); + +VObject* isAPropertyOf(VObject *o, const char *id); + +VObject* nextVObjectInList(VObject *o); +void initPropIterator(VObjectIterator *i, VObject *o); +int moreIteration(VObjectIterator *i); +VObject* nextVObject(VObjectIterator *i); + +extern void printVObject(nsOutputFileStream *fp,VObject *o); +void printVObject_(nsOutputFileStream *fp, VObject *o, int level); +extern void writeVObject(nsOutputFileStream *fp, VObject *o); + +void writeVObject_(OFile *fp, VObject *o); +char* writeMemVObject(char *s, int *len, VObject *o); +extern "C" char* writeMemoryVObjects(char *s, int *len, VObject *list, PRBool expandSpaces); + +const char* lookupStr(const char *s); + +void cleanVObject(VObject *o); +void cleanVObjects(VObject *list); + +const char* lookupProp(const char* str); +const char* lookupProp_(const char* str); + +vwchar_t* fakeUnicode(const char *ps, int *bytes); +int uStrLen(const vwchar_t *u); +char* fakeCString(const vwchar_t *u); + +void printVObjectToFile(nsFileSpec *fname,VObject *o); +void printVObjectsToFile(nsFileSpec *fname,VObject *list); +void writeVObjectToFile(nsFileSpec *fname, VObject *o); +void writeVObjectsToFile(nsFileSpec *fname, VObject *list); + +#define MAXPROPNAMESIZE 256 +#define MAXMOZPROPNAMESIZE 16 + +PR_END_EXTERN_C + +#endif /* __VOBJECT_H__ */ + +