From 706dcd2d190b01e62f7299a71bb0bcfa4358983e Mon Sep 17 00:00:00 2001 From: "rhp%netscape.com" Date: Mon, 25 Jan 1999 13:29:16 +0000 Subject: [PATCH] Changes for external content type handlers. git-svn-id: svn://10.0.0.236/trunk@18485 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/mailnews/mime/Makefile.in | 2 +- .../mime/cthandlers/calendar/mimecal.c | 3 +- .../mime/cthandlers/vcard/comi18n.cpp | 1327 ++++++++++++ .../mime/cthandlers/vcard/makefile.win | 10 +- .../mime/cthandlers/vcard/mimect-vcard.def | 2 + .../mailnews/mime/cthandlers/vcard/mimevcrd.c | 1770 +++++++++++++++++ .../mailnews/mime/cthandlers/vcard/mimevcrd.h | 42 + .../mailnews/mime/cthandlers/vcard/oldi18n.c | 95 + .../mailnews/mime/cthandlers/vcard/oldnet.c | 1346 +++++++++++++ .../mailnews/mime/cthandlers/vcard/oldvcc.c | 1617 +++++++++++++++ .../mailnews/mime/cthandlers/vcard/oldvobj.c | 1590 +++++++++++++++ .../mailnews/mime/cthandlers/vcard/oldxp.c | 254 +++ mozilla/mailnews/mime/makefile.win | 2 +- 13 files changed, 8054 insertions(+), 6 deletions(-) create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/comi18n.cpp create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.c create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.h create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/oldi18n.c create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/oldnet.c create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/oldvcc.c create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/oldvobj.c create mode 100644 mozilla/mailnews/mime/cthandlers/vcard/oldxp.c diff --git a/mozilla/mailnews/mime/Makefile.in b/mozilla/mailnews/mime/Makefile.in index ba62a4536be..26db5e3ec78 100644 --- a/mozilla/mailnews/mime/Makefile.in +++ b/mozilla/mailnews/mime/Makefile.in @@ -22,7 +22,7 @@ srcdir = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = public src tests +DIRS = public src cthandlers tests include $(topsrcdir)/config/config.mk diff --git a/mozilla/mailnews/mime/cthandlers/calendar/mimecal.c b/mozilla/mailnews/mime/cthandlers/calendar/mimecal.c index c25690138ca..7a1cdf36422 100644 --- a/mozilla/mailnews/mime/cthandlers/calendar/mimecal.c +++ b/mozilla/mailnews/mime/cthandlers/calendar/mimecal.c @@ -47,13 +47,14 @@ MIME_GetContentType(void) } PUBLIC MimeObjectClass * -MIME_CreateContentTypeHandlerClass(const char *content_type) +MIME_CreateContentTypeHandlerClass(const char *content_type, PRBool *forceInline) { MimeObjectClass *class = (MimeObjectClass *)&mimeInlineTextCalendarClass; /* * Must set the superclass by hand. */ class->superclass = (MimeObjectClass *)MIME_GetmimeInlineTextClass(); + *forceInline = PR_FALSE; return class; } diff --git a/mozilla/mailnews/mime/cthandlers/vcard/comi18n.cpp b/mozilla/mailnews/mime/cthandlers/vcard/comi18n.cpp new file mode 100644 index 00000000000..9e2f36da8e3 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/comi18n.cpp @@ -0,0 +1,1327 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#include +#include +#include +#include + +#include "prtypes.h" +#include "prmem.h" +#include "prlog.h" +#include "plstr.h" + + +// BEGIN EXTERNAL DEPENDANCY +#define XP_MEMCPY memcpy + +#define INTL_NextChar(a,b) ((b)+1) +#define INTL_DefaultMailCharSetID(a) (a) +#define XP_WordWrapWithPrefix(a,b,c,d,e,f) strdup((const char *) (b)) +#define INTL_CreateCharCodeConverter() NULL +#define INTL_GetCharCodeConverter(wincsid, mail_csid, obj) +#define INTL_GetSendHankakuKana() 0 +#define INTL_SetCCCCvtflag_SendHankakuKana(a,b) +#define INTL_GetCCCCvtfunc(a) NULL +#define MSG_UnquotePhraseOrAddr_Intl(a,b,c) (*c = strdup(b)) +#define MIME_StripContinuations(a) (a) +#define CS_UNKNOWN -1 +#define CS_JIS 0 +#define CS_UTF7 0 +#define CS_UTF8 0 +#define CS_GB_8BIT 0 +#define STATEFUL 0 +#define MULTIBYTE 0 +#define TAB '\t' +#define CR '\015' +#define LF '\012' +#define MAX_CSNAME 64 + +/* RICHIE - These are needed by other libmime functions */ +extern "C" PRInt16 INTL_DefaultWinCharSetID(char a) { return a; } +extern "C" char *INTL_CsidToCharsetNamePt(PRInt16 id) { return "iso-8859-1"; } +extern "C" PRInt16 INTL_CharSetNameToID(char *charset) { return 0; } + + +typedef void* CCCDataObject; +typedef unsigned char *(*CCCFunc)(CCCDataObject, const unsigned char +*,PRInt32); + +/* Very similar to strdup except it free's too + */ +char * +NET_SACopy (char **destination, const char *source) +{ + if(*destination) + { + PR_Free(*destination); + *destination = 0; + } + if (! source) + { + *destination = NULL; + } + else + { + *destination = (char *) PR_Malloc (PL_strlen(source) + 1); + if (*destination == NULL) + return(NULL); + + PL_strcpy (*destination, source); + } + return *destination; +} + +#define StrAllocCopy(dest, src) NET_SACopy (&(dest), src) + +// END EXTERNAL DEPENDANCY + + +#define MAXLINELEN 72 +#define IS_MAIL_SEPARATOR(p) ((*(p) == ',' || *(p) == ' ' || *(p) == '\"' || *(p) == ':' || \ + *(p) == '(' || *(p) == ')' || *(p) == '\\' || (unsigned char)*p < 0x20)) + +#define CHARSET_NAME_MAX_LEN 40 +#define MAX_CHARSET_PREF 10 + + +/* + Prototype for Private Function +*/ +static void intlmime_init_csidmap(); +static PRBool intlmime_only_ascii_str(const char *s); +static char * intlmime_encode_mail_address(int wincsid, const char *src, +CCCDataObject obj, + + +int maxLineLen); +static char * intlmime_encode_next8bitword(int wincsid, char *src); +//static int16 intlmime_get_outgoing_mime_csid(int16); +#define intlmime_get_outgoing_mime_csid(a) 0 + +/* we should consider replace this base64 decodeing and encoding +function with a better one */ +static int intlmime_decode_base64 (const char *in, char +*out); +static char * intlmime_decode_qp(char *in); +static int intlmime_encode_base64 (const char *in, char +*out); +static char * intlmime_decode_base64_buf(char *subject); +static char * intlmime_encode_base64_buf(char *subject, size_t size); +static char * intlmime_encode_qp_buf(char *subject); + + +static PRBool intlmime_is_hz(const char *header); +static PRBool intlmime_is_mime_part2_header(const char *header); +static PRBool intlmime_is_iso_2022_xxx(const char *, int16 ); +static char * intl_decode_mime_part2_str(const char *, int , PRBool ); +static char * intl_DecodeMimePartIIStr(const char *, int16 , PRBool ); +static char * intl_EncodeMimePartIIStr(char *subject, int16 wincsid, +PRBool bUseMime, int maxLineLen); + + +/* We probably should change these into private instead of PUBLIC */ +static char *DecodeBase64Buffer(char *subject); +static char *EncodeBase64Buffer(char *subject, size_t size); + + + +/* 4.0: Made Encode & Decode public for use by libpref; added size param. + */ +static char *EncodeBase64Buffer(char *subject, size_t size) +{ + /* This function should be obsolete */ + /* We should not make this public in libi18n */ + /* We should use the new Base64 Encoder wrote by jwz in libmime */ + return intlmime_encode_base64_buf(subject, size); +} + +static char *DecodeBase64Buffer(char *subject) +{ + /* This function should be obsolete */ + /* We should not make this public in libi18n */ + /* We should use the new Base64 Decoder wrote by jwz in libmime */ + return intlmime_decode_base64_buf(subject); +} + +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int intlmime_encode_base64 (const char *in, char *out) +{ + unsigned char c1, c2, c3; + c1 = in[0]; + c2 = in[1]; + c3 = in[2]; + + *out++ = basis_64[c1>>2]; + *out++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; + + *out++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; + *out++ = basis_64[c3 & 0x3F]; + return 1; +} + +static char *intlmime_encode_base64_buf(char *subject, size_t size) +{ + char *output = 0; + char *pSrc, *pDest ; + int i ; + + output = (char *)PR_Malloc(size * 4 / 3 + 4); + if (output == NULL) + return NULL; + + pSrc = subject; + pDest = output ; + for (i = size; i >= 3; i -= 3) + { + if (intlmime_encode_base64(pSrc, pDest) == 0) /* error */ + { + pSrc += 3; + pDest += 3; + } + else + { + pSrc += 3; + pDest += 4; + } + } + /* in case (i % 3 ) == 1 or 2 */ + if(i > 0) + { + char in[3]; + int j; + in[0] = in[1] = in[2] ='\0'; + for(j=0;j= 'A' && in[j] <= 'Z') c = in[j] - 'A'; + else if (in[j] >= 'a' && in[j] <= 'z') c = in[j] - ('a' - 26); + else if (in[j] >= '0' && in[j] <= '9') c = in[j] - ('0' - 52); + else if (in[j] == '+') c = 62; + else if (in[j] == '/') c = 63; + else if (in[j] == '=') c = 0; + else + { + /* abort (); */ + strcpy(out, in); /* I hate abort */ + return 0; + } + num = (num << 6) | c; + } + + *out++ = (unsigned char) (num >> 16); + *out++ = (unsigned char) ((num >> 8) & 0xFF); + *out++ = (unsigned char) (num & 0xFF); + return 1; +} + +static char *intlmime_decode_base64_buf(char *subject) +{ + char *output = 0; + char *pSrc, *pDest ; + int i ; + + StrAllocCopy(output, subject); /* Assume converted text are always +less than source text */ + + pSrc = subject; + pDest = output ; + for (i = PL_strlen(subject); i > 3; i -= 4) + { + if (intlmime_decode_base64(pSrc, pDest) == 0) + { + pSrc += 4; + pDest += 4; + } + else + { + pSrc += 4; + pDest += 3; + } + } + + *pDest = '\0'; + return output; +} + +static char *intlmime_encode_qp_buf(char *subject) +{ + char *output = 0; + unsigned char *p, *pDest ; + int i, n, len ; + + if (subject == NULL || *subject == '\0') + return NULL; + len = PL_strlen(subject); + output = (char *) PR_Malloc(len * 3 + 1); + if (output == NULL) + return NULL; + + p = (unsigned char*)subject; + pDest = (unsigned char*)output ; + + for (i = 0; i < len; i++) + { + /* XP_IS_ALPHA(*p) || XP_IS_DIGIT(*p)) */ + if ((*p < 0x80) && + (((*p >= 'a') && (*p <= 'z')) || + ((*p >= 'A') && (*p <= 'Z')) || + ((*p >= '0') && (*p <= '9'))) + ) + *pDest = *p; + else + { + *pDest++ = '='; + n = (*p & 0xF0) >> 4; /* high byte */ + if (n < 10) + *pDest = '0' + n; + else + *pDest = 'A' + n - 10; + pDest ++ ; + + n = *p & 0x0F; /* low byte */ + if (n < 10) + *pDest = '0' + n; + else + *pDest = 'A' + n - 10; + } + + p ++; + pDest ++; + } + + *pDest = '\0'; + return output; +} + +static char *intlmime_encode_next8bitword(int wincsid, char *src) +{ + char *p; + PRBool non_ascii = PR_FALSE; + if (src == NULL) + return NULL; + p = src; + while (*p == ' ') + p ++ ; + while ( *p ) + { + if ((unsigned char) *p > 0x7F) + non_ascii = PR_TRUE; + if ( IS_MAIL_SEPARATOR(p) ) + { + break; + } + p = INTL_NextChar(wincsid, p); + } + + if (non_ascii) + return p; + else + return NULL; +} + +/* some utility function used by this file */ +static PRBool intlmime_only_ascii_str(const char *s) +{ + for(; *s; s++) + if(*s & 0x80) + return PR_FALSE; + return PR_TRUE; +} + +/* +lock then length of input buffer, so the return value is less than +iThreshold bytes +*/ +static int ResetLen( int iThreshold, const char* buffer, int16 wincsid ) +{ + const char *begin, *end, *tmp; + + tmp = begin = end = buffer; + PR_ASSERT( iThreshold > 1 ); + PR_ASSERT( buffer != NULL ); + while( ( end - begin ) <= iThreshold ){ + tmp = end; + if (!(*end)) + break; + end = INTL_NextChar( wincsid, (char*)end ); + } + + PR_ASSERT( tmp > begin ); + return tmp - begin; +} + + +static char * intlmime_encode_mail_address(int wincsid, const char *src, +CCCDataObject obj, + + +int maxLineLen) +{ + char *begin, *end; + char *retbuf = NULL, *srcbuf = NULL; + char sep = '\0'; + char *sep_p = NULL; + char *name; + int retbufsize; + int line_len = 0; + int srclen; + int default_iThreshold; + int iThreshold; /* how many bytes we can convert from the +src */ + int iEffectLen; /* the maximum length we can convert from +the src */ + PRBool bChop = PR_FALSE; + PRBool is_being_used_in_email_summary_file = (maxLineLen > 120); + CCCFunc cvtfunc = NULL; + + if (obj) + cvtfunc = INTL_GetCCCCvtfunc(obj); + + if (src == NULL || *src == '\0') + return NULL; + /* make a copy, so don't need touch original buffer */ + MSG_UnquotePhraseOrAddr_Intl(wincsid, src, &srcbuf); + if (srcbuf == NULL) + return NULL; + begin = srcbuf; + + name = (char +*)INTL_CsidToCharsetNamePt(intlmime_get_outgoing_mime_csid +((int16)wincsid)); + default_iThreshold = iEffectLen = ( maxLineLen - PL_strlen( name ) +- 7 ) * 3 / 4; + iThreshold = default_iThreshold; + + + /* allocate enough buffer for conversion, this way it can avoid + do another memory allocation which is expensive + */ + + retbufsize = PL_strlen(srcbuf) * 3 + MAX_CSNAME + 8; + retbuf = (char *) PR_Malloc(retbufsize); + if (retbuf == NULL) /* Give up if not enough memory */ + { + PR_Free(srcbuf); + return NULL; + } + + *retbuf = '\0'; + + srclen = PL_strlen(srcbuf); + while (begin < (srcbuf + srclen)) + { /* get block of data between commas */ + char *p, *q; + char *buf1, *buf2; + int len, newsize, convlen, retbuflen; + PRBool non_ascii; + + retbuflen = PL_strlen(retbuf); + end = NULL; + if (is_being_used_in_email_summary_file) { + } else { + /* scan for separator, conversion happens on 8bit + word between separators + */ + if (IS_MAIL_SEPARATOR(begin)) + { /* skip white spaces and separator */ + q = begin; + while ( IS_MAIL_SEPARATOR(q) ) + q ++ ; + sep = *(q - 1); + sep_p = (q - 1); + *(q - 1) = '\0'; + end = q - 1; + } + else + { + sep = '\0'; + /* scan for next separator */ + non_ascii = PR_FALSE; + for (q = begin; *q;) + { + if ((unsigned char) *q > 0x7F) + non_ascii = PR_TRUE; + if ( IS_MAIL_SEPARATOR(q) ) + { + if ((*q == ' ') && (non_ascii == +PR_TRUE)) + { + while ((p = +intlmime_encode_next8bitword(wincsid, q)) != NULL) + { + if (p == NULL) + break; + q = p; + if (*p != ' ') + break; + } + } + sep = *q; + sep_p = q; + *q = '\0'; + end = q; + break; + } + q = INTL_NextChar(wincsid, q); + } + } + } + + /* get the to_be_converted_buffer's len */ + len = PL_strlen(begin); + + if ( !intlmime_only_ascii_str(begin) ) + { + if (obj && cvtfunc) + { + /* + the 30 lenght is calculated as +follows (I think) + total: 30 = 7 + 11 + 8 ++ 4 + +-------------------------------------- + Mime Part II tags: 7 = +"=?...?B?...?=" + Charset name: 11 = +"iso-2022-jp" + JIS excape seq. 8 = "$B" ++ "(B" * 4/3 + space for one char 4 = 2 * 4/3 +rounded up to nearest 4 + Brian Stell 10/97 + */ + if ( ( maxLineLen - line_len < 30 ) || +bChop ) { + /* chop first, then continue */ + buf1 = retbuf + retbuflen; + *buf1++ = CR; *buf1++ = LF; +*buf1++ = '\t'; + line_len = 0; + retbuflen += 3; + *buf1 = '\0'; + bChop = PR_FALSE; + iThreshold = default_iThreshold; + } + /* iEffectLen - the max byte-string +length of JIS ( converted form S-JIS ) + name - such as "iso-2022-jp", the +encoding name, MUST be shorter than 23 bytes + 7 - is the "=?:?:?=" */ + iEffectLen = ( maxLineLen - line_len - +PL_strlen( name ) - 7 ) * 3 / 4; + while ( PR_TRUE ) { + int iBufLen; /* converted +buffer's length, not BASE64 */ + if ( len > iThreshold ) + len = ResetLen( +iThreshold, begin, (int16)wincsid ); + + if ( iThreshold <= 1 ) + { + /* Certain trashed +mailboxes were causing an + ** infinite loop at this +point, so we need a way of + ** getting out of trouble. + ** + ** BEFORE: iThreshold +was becoming 1, then 0, and + ** we were +looping indefinitely. + ** AFTER: Now, first +there will be + ** an assert in +the previous call to ResetLen, + ** then we'll +do that again on the repeat pass, + ** then we'll +exit more or less gracefully. + ** - bug #83204, an +oldie but goodie. + ** - jrm 98/03/25 + */ + return NULL; + } + buf1 = (char *) cvtfunc(obj, +(unsigned char *)begin, len); + iBufLen = PL_strlen( buf1 ); + PR_ASSERT( iBufLen > 0 ); + + /* recal iThreshold each time +based on last experience */ + iThreshold = len * iEffectLen / +iBufLen; + if ( iBufLen > iEffectLen ){ + /* the converted buffer is +too large, we have to + 1. free the +buffer; + 2. redo again +based on the new iThreshold + */ + bChop = PR_TRUE; /* +append CRLFTAB */ + if (buf1 && (buf1 != +begin)){ + PR_Free(buf1); + buf1 = NULL; + } + } else { + end = begin + len - 1; + break; + } + } + if (bChop && (NULL!=sep_p)) { + *sep_p = sep; /* we are length +limited so we do not need this */ + sep = '\0'; /* +artifical terminator. So, restore the original character */ + sep_p = NULL; + } + + if (!buf1) + { + PR_Free(srcbuf); + PR_Free(retbuf); + return NULL; + } + } + else + { + buf1 = (char *) PR_Malloc(len + 1); + if (!buf1) + { + PR_Free(srcbuf); + PR_Free(retbuf); + return NULL; + } + XP_MEMCPY(buf1, begin, len); + *(buf1 + len) = '\0'; + } + + if (wincsid & MULTIBYTE) + { + /* converts to Base64 Encoding */ + buf2 = (char +*)intlmime_encode_base64_buf(buf1, PL_strlen(buf1)); + } + else + { + /* Converts to Quote Printable Encoding */ + buf2 = (char +*)intlmime_encode_qp_buf(buf1); + } + + + if (buf1 && (buf1 != begin)) + PR_Free(buf1); + + if (buf2 == NULL) /* QUIT if memory allocation +failed */ + { + PR_Free(srcbuf); + PR_Free(retbuf); + return NULL; + } + + /* realloc memory for retbuff if necessary, + 7: =?...?B?..?=, 3: CR LF TAB */ + convlen = PL_strlen(buf2) + PL_strlen(name) + 7; + newsize = convlen + retbuflen + 3 + 2; /* 2:SEP +'\0', 3:CRLFTAB */ + + if (newsize > retbufsize) + { + char *tempbuf; + tempbuf = (char *) PR_Realloc(retbuf, +newsize); + if (tempbuf == NULL) /* QUIT, if not +enough memory left */ + { + PR_Free(buf2); + PR_Free(srcbuf); + PR_Free(retbuf); + return NULL; + } + retbuf = tempbuf; + retbufsize = newsize; + } + /* buf1 points to end of current retbuf */ + buf1 = retbuf + retbuflen; + + if ((line_len > 10) && + ((line_len + convlen) > maxLineLen)) + { + *buf1++ = CR; + *buf1++ = LF; + *buf1++ = '\t'; + line_len = 0; + iThreshold = default_iThreshold; + } + *buf1 = '\0'; + + /* Add encoding tag for base62 and QP */ + PL_strcat(buf1, "=?"); + PL_strcat(buf1, name ); + if(wincsid & MULTIBYTE) + PL_strcat(buf1, "?B?"); + else + PL_strcat(buf1, "?Q?"); + PL_strcat(buf1, buf2); + PL_strcat(buf1, "?="); + + line_len += convlen + 1; /* 1: SEP */ + + PR_Free(buf2); /* free base64 buffer */ + } + else /* if no 8bit data in the block */ + { + newsize = retbuflen + len + 2 + 3; /* 2: ',''\0', +3: CRLFTAB */ + if (newsize > retbufsize) + { + char *tempbuf; + tempbuf = (char *) PR_Realloc(retbuf, +newsize); + if (tempbuf == NULL) + { + PR_Free(srcbuf); + PR_Free(retbuf); + return NULL; + } + retbuf = tempbuf; + retbufsize = newsize; + } + buf1 = retbuf + retbuflen; + + if ((line_len > 10) && + ((line_len + len) > maxLineLen)) + { + *buf1++ = CR; + *buf1++ = LF; + *buf1++ = '\t'; + line_len = 0; + iThreshold = default_iThreshold; + } + /* copy buffer from begin to buf1 stripping +CRLFTAB */ + for (p = begin; *p; p++) + { + if (*p == CR || *p == LF || *p == TAB) + len --; + else + *buf1++ = *p; + } + *buf1 = '\0'; + line_len += len + 1; /* 1: SEP */ + } + + buf1 = buf1 + PL_strlen(buf1); + if (sep == CR || sep == LF || sep == TAB) /* strip +CR,LF,TAB */ + *buf1 = '\0'; + else + { + *buf1 = sep; + *(buf1+1) = '\0'; + } + + if (end == NULL) + break; + begin = end + 1; + } + if (srcbuf) + PR_Free(srcbuf); + return retbuf; +} + +/* + Latin1, latin2: + Source --> Quote Printable --> Encoding Info + Japanese: + EUC,JIS,SJIS --> JIS --> Base64 --> Encoding Info + Others: + No conversion + flag: 0: 8bit on + 1: mime_use_quoted_printable_p + return: NULL if no conversion occured + +*/ + +static +char *intl_EncodeMimePartIIStr(char *subject, int16 wincsid, PRBool +bUseMime, int maxLineLen) +{ + int iSrcLen; + unsigned char *buf = NULL; /* Initial to NULL */ + int16 mail_csid; + CCCDataObject obj = NULL; + char *name; + CCCFunc cvtfunc = NULL; + + if (subject == NULL || *subject == '\0') + return NULL; + + + iSrcLen = PL_strlen(subject); + if (wincsid == 0) + wincsid = INTL_DefaultWinCharSetID(0) ; + + mail_csid = intlmime_get_outgoing_mime_csid ((int16)wincsid); + name = (char *)INTL_CsidToCharsetNamePt(mail_csid); + + /* check to see if subject are all ascii or not */ + if(intlmime_only_ascii_str(subject)) + return (char *) XP_WordWrapWithPrefix(mail_csid, (unsigned +char *) + + +subject, maxLineLen, 0, " ", 1); + + if (mail_csid != wincsid) + { + obj = INTL_CreateCharCodeConverter(); + if (obj == NULL) + return 0; + /* setup converter from wincsid --> mail_csid */ + INTL_GetCharCodeConverter((int16)wincsid, mail_csid, obj) +; + /* If we are sending JIS then check the pref setting and + * decide if we should convert hankaku (1byte) to zenkaku +(2byte) kana. + * This flag to be referenced in the converters in euc2jis +and sjis2jis. + */ + if (CS_JIS == mail_csid && INTL_GetSendHankakuKana()) + { + INTL_SetCCCCvtflag_SendHankakuKana(obj, PR_TRUE); + } + cvtfunc = INTL_GetCCCCvtfunc(obj); + } + /* Erik said in the case of STATEFUL mail encoding, we should +FORCE it to use */ + /* MIME Part2 to get ride of ESC in To: and CC: field, which may +introduce more trouble */ + if((bUseMime) || (mail_csid & STATEFUL))/* call +intlmime_encode_mail_address */ + { + buf = (unsigned char +*)intlmime_encode_mail_address(wincsid, subject, obj, maxLineLen); + if(buf == (unsigned char*)subject) /* no encoding, +set return value to NULL */ + buf = NULL; + } + else + { /* 8bit, just do conversion if necessary */ + /* In this case, since the conversion routine may reuse +the origional buffer */ + /* We better allocate one first- We don't want to reuse +the origional buffer */ + + if ((mail_csid != wincsid) && (cvtfunc)) + { + char* newbuf = NULL; + /* Copy buf to newbuf */ + StrAllocCopy(newbuf, subject); + if(newbuf != NULL) + { + buf = (unsigned char *)cvtfunc(obj, +(unsigned char*)newbuf, iSrcLen); + if(buf != (unsigned char*)newbuf) + PR_Free(newbuf); + /* time for wrapping long line */ + if (buf) + { + newbuf = (char*) buf; + buf = (unsigned char *) +XP_WordWrapWithPrefix(mail_csid, (unsigned char *) + + +newbuf, maxLineLen, 0, " ", 1); + + if (buf != (unsigned char*) +newbuf) + PR_Free(newbuf); + } + } + } + } + if (obj) + PR_Free(obj); + return (char*)buf; + + /* IMPORTANT NOTE: */ + /* Return NULL in this interface only mean ther are no conversion +*/ + /* It does not mean the conversion is store in the origional +buffer */ + /* and the length is not change. This is differ from other +conversion routine */ +} + +static char *intlmime_decode_qp(char *in) +{ + int i = 0, length; + char token[3]; + char *out, *dest = 0; + + out = dest = (char *)PR_Malloc(PL_strlen(in)+1); + if (dest == NULL) + return NULL; + memset(out, 0, PL_strlen(in)+1); + length = PL_strlen(in); + while (length > 0 || i != 0) + { + while (i < 3 && length > 0) + { + token [i++] = *in; + in++; + length--; + } + + if (i < 3) + { + /* Didn't get enough for a complete token. + If it might be a token, unread it. + Otherwise, just dump it. + */ + strncpy (out, token, i); + break; + } + i = 0; + + if (token [0] == '=') + { + unsigned char c = 0; + if (token[1] >= '0' && token[1] <= '9') + c = token[1] - '0'; + else if (token[1] >= 'A' && token[1] <= 'F') + c = token[1] - ('A' - 10); + else if (token[1] >= 'a' && token[1] <= 'f') + c = token[1] - ('a' - 10); + else if (token[1] == CR || token[1] == LF) + { + /* =\n means ignore the newline. */ + if (token[1] == CR && token[2] == LF) + ; /* swallow all +three chars */ + else + { + in--; /* put the third char back +*/ + length++; + } + continue; + } + else + { + /* = followed by something other than hex +or newline - + pass it through unaltered, I guess. +(But, if + this bogus token happened to occur over a +buffer + boundary, we can't do this, since we +don't have + space for it. Oh well. Screw it.) */ + if (in > out) *out++ = token[0]; + if (in > out) *out++ = token[1]; + if (in > out) *out++ = token[2]; + continue; + } + + /* Second hex digit */ + c = (c << 4); + if (token[2] >= '0' && token[2] <= '9') + c += token[2] - '0'; + else if (token[2] >= 'A' && token[2] <= 'F') + c += token[2] - ('A' - 10); + else if (token[2] >= 'a' && token[2] <= 'f') + c += token[2] - ('a' - 10); + else + { + /* We got =xy where "x" was hex and "y" +was not, so + treat that as a literal "=", x, and y. +(But, if + this bogus token happened to occur over a +buffer + boundary, we can't do this, since we +don't have + space for it. Oh well. Screw it.) */ + if (in > out) *out++ = token[0]; + if (in > out) *out++ = token[1]; + if (in > out) *out++ = token[2]; + continue; + } + + *out++ = (char) c; + } + else + { + *out++ = token [0]; + + token[0] = token[1]; + token[1] = token[2]; + i = 2; + } + } + /* take care of special underscore case */ + for (out = dest; *out; out++) + if (*out == '_') *out = ' '; + return dest; +} + +/* + intlmime_is_hz: it is CS_HZ +*/ +static PRBool intlmime_is_hz(const char *header) +{ + return (PL_strstr(header, "~{") ? PR_TRUE : PR_FALSE); +} +/* + intlmime_is_iso_2022_xxx: it is statefule encoding with esc +*/ +static PRBool intlmime_is_iso_2022_xxx(const char *header, int16 +mailcsid) +{ + return (((mailcsid & STATEFUL) && (PL_strchr(header, '\033'))) ? +PR_TRUE : PR_FALSE); +} +/* + intlmime_is_mime_part2_header: +*/ +static PRBool intlmime_is_mime_part2_header(const char *header) +{ + return (( + PL_strstr(header, "=?") && + ( + PL_strstr(header, "?q?") || + PL_strstr(header, "?Q?") || + PL_strstr(header, "?b?") || + PL_strstr(header, "?B?") + ) + ) ? PR_TRUE : PR_FALSE ); +} + + +static char *intlmime_convert_but_no_decode(const char *header, int16 +mailcsid, int16 wincsid) +{ + char* tmpbuf = NULL, *convbuf = NULL; + CCCDataObject obj; + CCCFunc cvtfunc; + /* Copy buf to tmpbuf, this guarantee the convresion won't +overwrite the origional buffer and */ + /* It will always return something it any conversion occcur */ + StrAllocCopy(tmpbuf, header); + + if(tmpbuf == NULL) + return NULL; + + obj = INTL_CreateCharCodeConverter(); + if (obj == NULL) + return NULL; + INTL_GetCharCodeConverter(mailcsid, wincsid, obj); + convbuf = NULL; + cvtfunc = INTL_GetCCCCvtfunc(obj); + if (cvtfunc) + convbuf = (char*)cvtfunc(obj, (unsigned char*)tmpbuf, +(PRInt32)PL_strlen((char*)tmpbuf)); + PR_Free(obj); + + /* if the conversion which use the origional buffer + them we return the tmpbuf */ + if(convbuf == NULL) + return tmpbuf; + + /* if the conversion return a different buffer, we free the + origional one and return the one return from conversion */ + if(convbuf != tmpbuf) + PR_Free(tmpbuf); + return convbuf; +} + +static +char *intl_decode_mime_part2_str(const char *header, int wincsid, PRBool +dontConvert) +{ + char *work_buf = NULL; + char *output_p = NULL; + char *retbuff = NULL; + char *p, *q, *decoded_text; + char *begin; /* tracking pointer for where we are in the work +buffer */ + int16 csid = 0; + int ret = 0; + + + StrAllocCopy(work_buf, header); /* temporary buffer */ + StrAllocCopy(retbuff, header); + + if (work_buf == NULL || retbuff == NULL) + return NULL; + + output_p = retbuff; + begin = work_buf; + + while (*begin != '\0') + { + char * output_text; + + /* GetCharset(); */ + p = strstr(begin, "=?"); + if (p == NULL) + break; /* exit the loop +because the rest are not encoded */ + *p = '\0'; + /* skip strings don't need conversion */ + strncpy(output_p, begin, p - begin); + output_p += p - begin; + + p += 2; + begin = p; + + q = strchr(p, '?'); /* Get charset info */ + if (q == NULL) + break; /* exit the loop +because there are no charset info */ + *q++ = '\0'; + csid = INTL_CharSetNameToID(p); + if (csid == CS_UNKNOWN) + { + /* + * @@@ may want to use context's default doc_csid +in the future + */ + break; /* exit the loop +because we don't know the charset */ + } + + if (*(q+1) == '?' && + (*q == 'Q' || *q == 'q' || *q == 'B' || *q == 'b')) + { + p = strstr(q+2, "?="); + if(p != NULL) + *p = '\0'; + if(*q == 'Q' || *q == 'q') + decoded_text = intlmime_decode_qp(q+2); + else + decoded_text = +intlmime_decode_base64_buf(q+2); + } + else + break; /* exit the loop +because we don't know the encoding method */ + + begin = (p != NULL) ? p + 2 : (q + PL_strlen(q)); + + if (decoded_text == NULL) + break; /* exit the loop +because we have problem to decode */ + + ret = 1; + if ((! dontConvert) && (csid != wincsid)) + output_text = (char +*)intlmime_convert_but_no_decode(decoded_text, csid, (int16)wincsid); + else + output_text = (char *)decoded_text; + + PR_ASSERT(output_text != NULL); + PL_strcpy(output_p, (char *)output_text); + output_p += PL_strlen(output_text); + + if (output_text != decoded_text) + PR_Free(output_text); + PR_Free(decoded_text); + } + PL_strcpy(output_p, (char *)begin); /* put the tail back */ + + if (work_buf) + PR_Free(work_buf); + + if (ret) + { + return retbuff; + } + else + { + PR_Free(retbuff); + return NULL; /* null means no conversion */ + } +} + +/* IMPORTANT NOTE: */ +/* Return NULL in this interface only mean ther are no conversion */ +/* It does not mean the conversion is store in the origional buffer */ +/* and the length is not change. This is differ from other conversion +routine */ + + +static +char *intl_DecodeMimePartIIStr(const char *header, int16 wincsid, PRBool +dontConvert) +{ + int16 mailcsid = INTL_DefaultMailCharSetID(wincsid); + PRBool no8bitdata = PR_TRUE; + + if (header == 0 || *header == '\0') + return NULL; + if (wincsid == 0) /* Use global if undefined */ + wincsid = INTL_DefaultWinCharSetID(0); + + no8bitdata = intlmime_only_ascii_str(header); + + /* Start Special Case Handling */ + if(! dontConvert) + { + /* Need to do conversion in here if necessary */ + if(! no8bitdata) + { + /* Special Case 1: 8 Bit */ + /* then we assume it is not mime part 2 encoding, +we convert from the internet encoding to wincsid */ + if(wincsid == CS_UTF8) + return +MIME_StripContinuations(intlmime_convert_but_no_decode(header, CS_UTF8, +(int16)wincsid)); + else + return +MIME_StripContinuations(intlmime_convert_but_no_decode(header, mailcsid, +(int16)wincsid)); + } + else + { + /* 7bit- It could be MIME Part 2 Header */ + if ((wincsid == CS_GB_8BIT) && +(intlmime_is_hz(header)) ) + { + /* Special Case 2: HZ */ + /* for subject list pane, if it's GB, +we only do HZ conversion */ + return +MIME_StripContinuations(intlmime_convert_but_no_decode(header, CS_GB_8BIT, +CS_GB_8BIT)); + } + else if((wincsid == CS_UTF8) && + (! +intlmime_is_mime_part2_header(header))) + { + /* Special Case 3: UTF7 and UTF8 */ + return +MIME_StripContinuations(intlmime_convert_but_no_decode(header, CS_UTF7, +CS_UTF8)); + } + else if(intlmime_is_iso_2022_xxx(header, mailcsid) +&& + (! +intlmime_is_mime_part2_header(header))) + { + return +MIME_StripContinuations(intlmime_convert_but_no_decode(header, mailcsid, +wincsid)); + } + } + } + /* Handle only Mime Part 2 after this point */ + return MIME_StripContinuations(intl_decode_mime_part2_str(header, +wincsid, dontConvert)); +} + + +// BEGIN PUBLIC INTERFACE +extern "C" { +#define PUBLIC +PUBLIC char *INTL_DecodeMimePartIIStr(const char *header, int16 wincsid, +PRBool dontConvert) +{ + return intl_DecodeMimePartIIStr(header, wincsid, dontConvert); +} +PUBLIC char *INTL_EncodeMimePartIIStr(char *subject, int16 wincsid, +PRBool bUseMime) +{ + return intl_EncodeMimePartIIStr(subject, wincsid, bUseMime, +MAXLINELEN); +} +/* This is a routine used to re-encode subject lines for use in the +summary file. + The reason why we specify a different length here is because we +are not encoding + the string for use in a mail message, but rather want to stuff as +much content + into the subject string as possible. */ +PUBLIC char *INTL_EncodeMimePartIIStr_VarLen(char *subject, int16 wincsid, +PRBool bUseMime, int encodedWordSize) +{ + return intl_EncodeMimePartIIStr(subject, wincsid, bUseMime, +encodedWordSize); +} + +PUBLIC char *IntlDecodeMimePartIIStr(const char *header, int wincsid, +PRBool dontConvert) +{ + /* We change IntlDecodeMimePartIIStr to +INTL_DecodeMimePartIIStr */ + return intl_DecodeMimePartIIStr(header, (int16)wincsid, +dontConvert); +} +PUBLIC char *IntlEncodeMimePartIIStr(char *subject, int wincsid, PRBool +bUseMime) +{ + /* We change IntlEncodeMimePartIIStr to +INTL_EncodeMimePartIIStr */ + return intl_EncodeMimePartIIStr(subject, (int16)wincsid, bUseMime, +MAXLINELEN); +} + +} /* end of extern "C" */ +// END PUBLIC INTERFACE + +main() +{ + char *encoded, *decoded; + printf("mime\n"); + encoded = intl_EncodeMimePartIIStr("hello worldÉ", 0, PR_TRUE, +MAXLINELEN); + printf("%s\n", encoded); + decoded = intl_DecodeMimePartIIStr((const char *) encoded, +PL_strlen(encoded), PR_TRUE); + + return 0; +} + diff --git a/mozilla/mailnews/mime/cthandlers/vcard/makefile.win b/mozilla/mailnews/mime/cthandlers/vcard/makefile.win index f8ecf1af72f..dd1a392d937 100644 --- a/mozilla/mailnews/mime/cthandlers/vcard/makefile.win +++ b/mozilla/mailnews/mime/cthandlers/vcard/makefile.win @@ -55,7 +55,10 @@ OBJS= \ .\$(OBJDIR)\mimevcrd.obj \ .\$(OBJDIR)\oldvcc.obj \ .\$(OBJDIR)\oldvobj.obj \ - .\$(OBJDIR)\mimeobj.obj \ + .\$(OBJDIR)\oldxp.obj \ + .\$(OBJDIR)\oldi18n.obj \ + .\$(OBJDIR)\comi18n.obj \ + .\$(OBJDIR)\oldnet.obj \ $(NULL) #//------------------------------------------------------------------------ @@ -101,6 +104,7 @@ LLIBS= \ $(DIST)\lib\xplib.lib \ $(DIST)\lib\raptorbase.lib \ $(DIST)\lib\xpcom32.lib \ + $(DIST)\lib\mime.lib \ $(NULL) LINCS=$(LINCS) -I. \ @@ -110,7 +114,7 @@ LINCS=$(LINCS) -I. \ -I$(PUBLIC)\netlib \ -I$(PUBLIC)\xpcom \ -I$(PUBLIC)\raptor \ - -I..\src \ + -I..\..\src \ $(NULL) #//------------------------------------------------------------------------ @@ -121,7 +125,7 @@ LINCS=$(LINCS) -I. \ include <$(DEPTH)/config/rules.mak> install:: $(DLL) - $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME) $(DIST)\bin + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME) $(DIST)\bin\mimeplugins clobber:: rm -f $(DIST)\bin\$(DLLNAME) diff --git a/mozilla/mailnews/mime/cthandlers/vcard/mimect-vcard.def b/mozilla/mailnews/mime/cthandlers/vcard/mimect-vcard.def index 144b1f41566..b61e259b7de 100644 --- a/mozilla/mailnews/mime/cthandlers/vcard/mimect-vcard.def +++ b/mozilla/mailnews/mime/cthandlers/vcard/mimect-vcard.def @@ -16,3 +16,5 @@ LIBRARY mimect-vcard.dll EXPORTS + MIME_GetContentType + MIME_CreateContentTypeHandlerClass \ No newline at end of file diff --git a/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.c b/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.c new file mode 100644 index 00000000000..af419ff0b45 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.c @@ -0,0 +1,1770 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#include "mimevcrd.h" +#include "xpgetstr.h" +#include "xp_core.h" +#include "xp_mem.h" +#include "vcc.h" +#include "vobject.h" +#include "libi18n.h" +#include "mimecth.h" + +#include "prmem.h" +#include "plstr.h" + +static int MimeInlineTextVCard_parse_line (char *, PRInt32, MimeObject *); +static int MimeInlineTextVCard_parse_eof (MimeObject *, PRBool); +static int MimeInlineTextVCard_parse_begin (MimeObject *obj); + +static int unique = 0; + +extern int MK_OUT_OF_MEMORY; + +extern int MK_LDAP_COMMON_NAME; +extern int MK_LDAP_FAX_NUMBER; +extern int MK_LDAP_GIVEN_NAME; +extern int MK_LDAP_LOCALITY; +extern int MK_LDAP_PHOTOGRAPH; +extern int MK_LDAP_EMAIL_ADDRESS; +extern int MK_LDAP_MANAGER; +extern int MK_LDAP_ORGANIZATION; +extern int MK_LDAP_OBJECT_CLASS; +extern int MK_LDAP_ORG_UNIT; +extern int MK_LDAP_POSTAL_ADDRESS; +extern int MK_LDAP_SECRETARY; +extern int MK_LDAP_SURNAME; +extern int MK_LDAP_STREET; +extern int MK_LDAP_PHONE_NUMBER; +extern int MK_LDAP_CAR_LICENSE; +extern int MK_LDAP_BUSINESS_CAT; +extern int MK_LDAP_DEPT_NUMBER; +extern int MK_LDAP_DESCRIPTION; +extern int MK_LDAP_EMPLOYEE_TYPE; +extern int MK_LDAP_POSTAL_CODE; +extern int MK_LDAP_TITLE; +extern int MK_LDAP_REGION; +extern int MK_LDAP_DOM_TYPE; +extern int MK_LDAP_INTL_TYPE; +extern int MK_LDAP_POSTAL_TYPE; +extern int MK_LDAP_PARCEL_TYPE; +extern int MK_LDAP_WORK_TYPE; +extern int MK_LDAP_HOME_TYPE; +extern int MK_LDAP_PREF_TYPE; +extern int MK_LDAP_VOICE_TYPE; +extern int MK_LDAP_FAX_TYPE; +extern int MK_LDAP_MSG_TYPE; +extern int MK_LDAP_CELL_TYPE; +extern int MK_LDAP_PAGER_TYPE; +extern int MK_LDAP_BBS_TYPE; +extern int MK_LDAP_MODEM_TYPE; +extern int MK_LDAP_CAR_TYPE; +extern int MK_LDAP_ISDN_TYPE; +extern int MK_LDAP_VIDEO_TYPE; +extern int MK_LDAP_AOL_TYPE; +extern int MK_LDAP_APPLELINK_TYPE; +extern int MK_LDAP_ATTMAIL_TYPE; +extern int MK_LDAP_CSI_TYPE; +extern int MK_LDAP_EWORLD_TYPE; +extern int MK_LDAP_INTERNET_TYPE; +extern int MK_LDAP_IBMMAIL_TYPE; +extern int MK_LDAP_MCIMAIL_TYPE; +extern int MK_LDAP_POWERSHARE_TYPE; +extern int MK_LDAP_PRODIGY_TYPE; +extern int MK_LDAP_TLX_TYPE; +extern int MK_LDAP_MIDDLE_NAME; +extern int MK_LDAP_NAME_PREFIX; +extern int MK_LDAP_NAME_SUFFIX; +extern int MK_LDAP_TZ; +extern int MK_LDAP_GEO; +extern int MK_LDAP_SOUND; +extern int MK_LDAP_REVISION; +extern int MK_LDAP_VERSION; +extern int MK_LDAP_KEY; +extern int MK_LDAP_LOGO; +extern int MK_LDAP_X400; +extern int MK_LDAP_BIRTHDAY; +extern int MK_LDAP_ADDRESS; +extern int MK_LDAP_LABEL; +extern int MK_LDAP_MAILER; +extern int MK_LDAP_ROLE; +extern int MK_LDAP_UPDATEURL; +extern int MK_LDAP_COOLTALKADDRESS; +extern int MK_LDAP_USEHTML; +extern int MK_ADDR_VIEW_COMPLETE_VCARD; +extern int MK_ADDR_VIEW_CONDENSED_VCARD; +extern int MK_MSG_ADD_TO_ADDR_BOOK; +extern int MK_ADDR_DEFAULT_DLS; +extern int MK_ADDR_SPECIFIC_DLS; +extern int MK_ADDR_HOSTNAMEIP; +extern int MK_ADDR_CONFINFO; +extern int MK_ADDR_ADDINFO; + +static int BeginVCard (MimeObject *obj); +static int EndVCard (MimeObject *obj); +static int WriteOutVCard (MimeObject *obj, VObject* v); +static int WriteOutEachVCardProperty (MimeObject *obj, VObject* v, int* numEmail); +static int WriteOutVCardProperties (MimeObject *obj, VObject* v, int* numEmail); +static int WriteLineToStream (MimeObject *obj, const char *line); + +static void GetEmailProperties (VObject* o, char ** attribName); +static void GetTelephoneProperties (VObject* o, char ** attribName); +static void GetAddressProperties (VObject* o, char ** attribName); +static int WriteValue (MimeObject *obj, const char *); +static int WriteAttribute (MimeObject *obj, const char *); +static int WriteOutVCardPhoneProperties (MimeObject *obj, VObject* v); +static int WriteOutEachVCardPhoneProperty (MimeObject *obj, VObject* o); + +typedef struct + { + const char *attributeName; + int resourceId; + } AttributeName; + +#define kNumAttributes 12 + +/* + * These functions are the public interface for this content type + * handler and will be called in by the mime component. + */ +#define VCARD_CONTENT_TYPE "text/x-vcard" + + /* This is the object definition. Note: we will set the superclass + to NULL and manually set this on the class creation */ +MimeDefClass(MimeInlineTextVCard, MimeInlineTextVCardClass, + mimeInlineTextVCardClass, NULL); + +PUBLIC char * +MIME_GetContentType(void) +{ + return VCARD_CONTENT_TYPE; +} + +PUBLIC MimeObjectClass * +MIME_CreateContentTypeHandlerClass(const char *content_type, PRBool *forceInline) +{ + MimeObjectClass *class = (MimeObjectClass *)&mimeInlineTextVCardClass; + /* + * Must set the superclass by hand. + */ + class->superclass = (MimeObjectClass *)MIME_GetmimeInlineTextClass(); + *forceInline = PR_TRUE; + return class; +} + +/* + * Implementation of VCard class + */ +static int +MimeInlineTextVCardClassInitialize(MimeInlineTextVCardClass *class) +{ + MimeObjectClass *oclass = (MimeObjectClass *) class; + PR_ASSERT(!oclass->class_initialized); + oclass->parse_begin = MimeInlineTextVCard_parse_begin; + oclass->parse_line = MimeInlineTextVCard_parse_line; + oclass->parse_eof = MimeInlineTextVCard_parse_eof; + +return 0; +} + +static int +MimeInlineTextVCard_parse_begin (MimeObject *obj) +{ +// int status = ((MimeObjectClass*)&mimeLeafClass)->parse_begin(obj); + int status = ((MimeObjectClass*)MIME_GetmimeLeafClass())->parse_begin(obj); + MimeInlineTextVCardClass *class; + if (status < 0) return status; + + if (!obj->output_p) return 0; + if (!obj->options || !obj->options->write_html_p) return 0; + + /* This is a fine place to write out any HTML before the real meat begins. + In this sample code, we tell it to start a table. */ + + class = ((MimeInlineTextVCardClass *) obj->class); + /* initialize vcard string to empty; */ + StrAllocCopy(class->vCardString, ""); + + return 0; +} + + +static int +MimeInlineTextVCard_parse_line (char *line, PRInt32 length, MimeObject *obj) +{ + /* This routine gets fed each line of data, one at a time. In my + sample, I spew it out as a table row, putting everything + between colons in its own table cell.*/ + + char* linestring; + MimeInlineTextVCardClass *class = ((MimeInlineTextVCardClass *) obj->class); + + if (!obj->output_p) return 0; + if (!obj->options || !obj->options->output_fn) return 0; + if (!obj->options->write_html_p) { + return MIME_MimeObject_write(obj, line, length, PR_TRUE); + } + + linestring = (char *) PR_MALLOC (length + 1); + + if (linestring) { + XP_STRNCPY_SAFE((char *)linestring, line, length + 1); + StrAllocCat (class->vCardString, linestring); + PR_Free (linestring); + } + + return 0; +} + + +static int +MimeInlineTextVCard_parse_eof (MimeObject *obj, PRBool abort_p) +{ + int status = 0; + MimeInlineTextVCardClass *class = ((MimeInlineTextVCardClass *) obj->class); + VObject *t, *v; + + if (obj->closed_p) return 0; + + /* Run parent method first, to flush out any buffered data. */ +// status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p); + status = ((MimeObjectClass*)MIME_GetmimeInlineTextClass())->parse_eof(obj, abort_p); + if (status < 0) return status; + + if (!class->vCardString) return 0; + + v = Parse_MIME(class->vCardString, PL_strlen(class->vCardString)); + + if (class->vCardString) { + PR_Free ((char*) class->vCardString); + class->vCardString = NULL; + } + + if (obj->output_p && obj->options && obj->options->write_html_p && + obj->options->headers != MimeHeadersCitation) { + /* This is a fine place to write any closing HTML. In fact, you may + want all the writing to be here, and all of the above would just + collect data into datastructures, though that isn't very + "streaming". */ + t = v; + while (v && status >= 0) { + /* write out html */ + status = WriteOutVCard (obj, v); + /* parse next vcard incase they're embedded */ + v = nextVObjectInList(v); + } + + cleanVObject(t); + } + if (status < 0) return status; + + return 0; +} + +static int WriteEachLineToStream (MimeObject *obj, const char *line) +{ + int status = 0; + char *htmlLine; + int htmlLen = PL_strlen(line) + 1; + + htmlLine = (char *) PR_MALLOC (htmlLen); + if (htmlLine) + { + htmlLine[0] = '\0'; + PL_strcat (htmlLine, line); + status = MIME_MimeObject_write(obj, htmlLine, PL_strlen(htmlLine), PR_TRUE); + PR_Free ((void*) htmlLine); + } + else + status = MK_OUT_OF_MEMORY; + + return status; +} + +static int OutputTable (MimeObject *obj, PRBool endTable, PRBool border, char *cellspacing, char *cellpadding, char *bgcolor) +{ + int status = 0; + char * htmlLine = NULL; + + if (endTable) + { + status = WriteEachLineToStream (obj, ""); + } + else + { + int htmlLen = PL_strlen("") + 1; + if (border) + htmlLen += PL_strlen (" BORDER"); + if (cellspacing) + htmlLen += PL_strlen(" CELLSPACING=") + PL_strlen(cellspacing); + if (cellpadding) + htmlLen += PL_strlen(" CELLPADDING=") + PL_strlen(cellpadding); + if (bgcolor) + htmlLen += PL_strlen(" BGCOLOR=") + PL_strlen(bgcolor); + if (border || cellspacing || cellpadding || bgcolor) + htmlLen++; + + htmlLine = (char *) PR_MALLOC (htmlLen); + if (htmlLine) + { + htmlLine[0] = '\0'; + PL_strcat (htmlLine, ""); + + status = MIME_MimeObject_write(obj, htmlLine, PL_strlen(htmlLine), PR_TRUE); + PR_Free ((void*) htmlLine); + } + else + status = MK_OUT_OF_MEMORY; + } + return status; +} + +static int OutputTableRowOrData(MimeObject *obj, PRBool outputRow, + PRBool end, char * align, + char* valign, char* colspan, + char* width) +{ + int status = 0; + char * htmlLine = NULL; + + if (end) + if (outputRow) + status = WriteEachLineToStream (obj, ""); + else + status = WriteEachLineToStream (obj, ""); + else + { + int htmlLen = PL_strlen("") + 1; + if (align) + htmlLen += PL_strlen(" ALIGN=") + PL_strlen(align); + if (colspan) + htmlLen += PL_strlen(" COLSPAN=") + PL_strlen(colspan); + if (width) + htmlLen += PL_strlen(" WIDTH=") + PL_strlen(width); + if (valign) + htmlLen += PL_strlen(" VALIGN=") + PL_strlen(valign); + if (align || valign || colspan || width) + htmlLen++; + + htmlLine = (char *) PR_MALLOC (htmlLen); + if (htmlLine) + { + htmlLine[0] = '\0'; + if (outputRow) + PL_strcat (htmlLine, ""); + + status = MIME_MimeObject_write(obj, htmlLine, PL_strlen(htmlLine), PR_TRUE); + PR_Free ((void*) htmlLine); + } + else + status = MK_OUT_OF_MEMORY; + } + + return status; +} + + +static int OutputFont(MimeObject *obj, PRBool endFont, char * size, char* color) +{ + int status = 0; + char * htmlLine = NULL; + + if (endFont) + status = WriteEachLineToStream (obj, ""); + else + { + int htmlLen = PL_strlen("") + 1; + if (size) + htmlLen += PL_strlen(" SIZE=") + PL_strlen(size); + if (color) + htmlLen += PL_strlen(" COLOR=") + PL_strlen(color); + if (size || color) + htmlLen++; + + htmlLine = (char *) PR_MALLOC (htmlLen); + if (htmlLine) + { + htmlLine[0] = '\0'; + PL_strcat (htmlLine, ""); + + status = MIME_MimeObject_write(obj, htmlLine, PL_strlen(htmlLine), PR_TRUE); + PR_Free ((void*) htmlLine); + } + else + status = MK_OUT_OF_MEMORY; + } + + return status; +} + +static int OutputVcardAttribute(MimeObject *obj, VObject *v, const char* id) +{ + int status = 0; + VObject *prop = NULL; + char *string = NULL; + + prop = isAPropertyOf(v, id); + if (prop) + if (VALUE_TYPE(prop)) + { + if (VALUE_TYPE(prop) != VCVT_RAW) + string = fakeCString (vObjectUStringZValue(prop)); + else + { + string = PR_MALLOC(PL_strlen((char *) vObjectAnyValue(prop)) + 1); + if (string) + PL_strcpy(string, (char *) vObjectAnyValue(prop)); + } + if (string) { + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) { + PR_FREEIF (string); + return status; + } + status = WriteLineToStream (obj, string); + PR_FREEIF (string); + if (status < 0) return status; + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) return status; + } + } + + return 0; +} + + +static int OutputBasicVcard(MimeObject *obj, VObject *v) +{ + int status = 0; + char * htmlLine1 = NULL; + char * htmlLine2 = NULL; + char * htmlLine = NULL; + VObject *prop = NULL; + VObject* prop2 = NULL; + char * urlstring = NULL; + char * namestring = NULL; + char * emailstring = NULL; + + /* get the name and email */ + prop = isAPropertyOf(v, VCFullNameProp); + if (prop) + { + if (VALUE_TYPE(prop)) + { + if (VALUE_TYPE(prop) != VCVT_RAW) + namestring = fakeCString (vObjectUStringZValue(prop)); + else + { + namestring = PR_MALLOC(PL_strlen((char *) vObjectAnyValue(prop)) + 1); + if (namestring) + PL_strcpy(namestring, (char *) vObjectAnyValue(prop)); + } + if (namestring) + { + prop = isAPropertyOf(v, VCURLProp); + if (prop) + { + urlstring = fakeCString (vObjectUStringZValue(prop)); + if (urlstring) + htmlLine1 = PR_smprintf ("%s ", urlstring, namestring); + else + htmlLine1 = PR_smprintf ("%s ", namestring); + PR_FREEIF (urlstring); + } + else + htmlLine1 = PR_smprintf ("%s ", namestring); + + /* get the email address */ + prop = isAPropertyOf(v, VCEmailAddressProp); + if (prop) + { + emailstring = fakeCString (vObjectUStringZValue(prop)); + if (emailstring) + { + /* if its an internet address prepend the mailto url */ + prop2 = isAPropertyOf(prop, VCInternetProp); + if (prop2) + htmlLine2 = PR_smprintf ("<%s>", emailstring, emailstring); + else + htmlLine2 = PR_smprintf ("%s", emailstring); + PR_FREEIF (emailstring); + } + } + + if (!htmlLine1 && !htmlLine2) + { + PR_FREEIF (htmlLine1); + PR_FREEIF (htmlLine2); + return MK_OUT_OF_MEMORY; + } + else + { + htmlLine = StrAllocCat (htmlLine, htmlLine1); + htmlLine = StrAllocCat (htmlLine, htmlLine2); + } + + PR_FREEIF (htmlLine1); + PR_FREEIF (htmlLine2); + PR_FREEIF (namestring); + } + } + } + + status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL); + if (status < 0) { + PR_FREEIF (htmlLine); + return status; + } + if (htmlLine) + { + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) { + PR_Free (htmlLine); + return status; + } + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) { + PR_Free (htmlLine); + return status; + } + + status = WriteLineToStream (obj, htmlLine); + PR_Free (htmlLine); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + } + else + status = MK_OUT_OF_MEMORY; + + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + /* output the title */ + status = OutputVcardAttribute (obj, v, VCTitleProp); + if (status < 0) return status; + /* write out the org name and company name */ + prop = isAPropertyOf(v, VCOrgProp); + if (prop) + { + status = OutputVcardAttribute (obj, prop, VCOrgNameProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnitProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnit2Prop); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnit3Prop); + if (status < 0) return status; + } + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + + return 0; +} + +static int OutputAdvancedVcard(MimeObject *obj, VObject *v) +{ + int status = 0; + char * htmlLine1 = NULL; + char * htmlLine2 = NULL; + VObject *prop = NULL; + VObject* prop2 = NULL; + char * urlstring = NULL; + char * namestring = NULL; + char * emailstring = NULL; + int numEmail = 0; + + status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL); + if (status < 0) return status; + /* beginning of first row */ + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "3", NULL); + if (status < 0) return status; + + /* get the name and email */ + prop = isAPropertyOf(v, VCFullNameProp); + if (prop) + { + if (VALUE_TYPE(prop)) + { + if (VALUE_TYPE(prop) != VCVT_RAW) + namestring = fakeCString (vObjectUStringZValue(prop)); + else + { + namestring = PR_MALLOC(PL_strlen((char *) vObjectAnyValue(prop)) + 1); + if (namestring) + PL_strcpy(namestring, (char *) vObjectAnyValue(prop)); + } + if (namestring) + { + prop = isAPropertyOf(v, VCURLProp); + if (prop) + { + urlstring = fakeCString (vObjectUStringZValue(prop)); + if (urlstring) + htmlLine1 = PR_smprintf ("%s ", urlstring, namestring); + else + htmlLine1 = PR_smprintf ("%s ", namestring); + PR_FREEIF (urlstring); + } + else + htmlLine1 = PR_smprintf ("%s ", namestring); + + PR_FREEIF (namestring); + } + if (!htmlLine1) + { + return MK_OUT_OF_MEMORY; + } + } + } + /* output the name if there was one */ + if (htmlLine1) + { + status = WriteLineToStream (obj, htmlLine1); + PR_FREEIF (htmlLine1); + if (status < 0) return status; + } + + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* beginning of second row */ + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + /* output the title */ + status = OutputVcardAttribute (obj, v, VCTitleProp); + if (status < 0) return status; + /* write out the org name and company name */ + prop = isAPropertyOf(v, VCOrgProp); + if (prop) + { + status = OutputVcardAttribute (obj, prop, VCOrgNameProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnitProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnit2Prop); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCOrgUnit3Prop); + if (status < 0) return status; + } + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE , "LEFT", "TOP", NULL, "\"10\""); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + + /* get the email address */ + prop = isAPropertyOf(v, VCEmailAddressProp); + if (prop) + { + emailstring = fakeCString (vObjectUStringZValue(prop)); + if (emailstring) + { + numEmail++; + /* if its an internet address prepend the mailto url */ + prop2 = isAPropertyOf(prop, VCInternetProp); + if (prop2) + htmlLine2 = PR_smprintf ("<%s>", emailstring, emailstring); + else + htmlLine2 = PR_smprintf ("%s", emailstring); + + PR_FREEIF (emailstring); + } + if (!htmlLine2) + { + return MK_OUT_OF_MEMORY; + } + } + /* output email address */ + if (htmlLine2) + { + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) { + PR_FREEIF (htmlLine2); + return status; + } + status = WriteLineToStream (obj, htmlLine2); + PR_FREEIF (htmlLine2); + if (status < 0) return status; + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) return status; + /* output html mail setting only if its true */ + prop = isAPropertyOf(v, VCUseHTML); + if (prop) + { + if (VALUE_TYPE(prop)) + { + namestring = fakeCString (vObjectUStringZValue(prop)); + if (namestring) + if (PL_strcasecmp (namestring, "PR_TRUE") == 0) + { + PR_FREEIF (namestring); + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) return status; + status = WriteLineToStream (obj, XP_GetString (MK_LDAP_USEHTML)); + if (status < 0) return status; + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) return status; + } + else + PR_FREEIF (namestring); + } + } + } + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* beginning of third row */ + /* write out address information if we have any */ + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + /* first column */ + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + prop = isAPropertyOf(v, VCAdrProp); + if (prop) + { + status = OutputVcardAttribute (obj, prop, VCPostalBoxProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCExtAddressProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCStreetAddressProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCCityProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCRegionProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCPostalCodeProp); + if (status < 0) return status; + status = OutputVcardAttribute (obj, prop, VCCountryNameProp); + if (status < 0) return status; + } + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* second column */ + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE , NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* third column */ + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + /* output telephone fields */ + status = WriteOutVCardPhoneProperties (obj, v); + if (status < 0) return status; + /* output conference fields */ + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) return status; + prop = isAPropertyOf(v, VCCooltalk); + if (prop) + { + WriteLineToStream (obj, XP_GetString (MK_ADDR_CONFINFO)); + if (status < 0) return status; + prop2 = isAPropertyOf(prop, VCUseServer); + if (prop2) + { + if (VALUE_TYPE(prop2)) { + namestring = fakeCString (vObjectUStringZValue(prop2)); + if (PL_strcmp (namestring, "0") == 0) + status = WriteLineToStream (obj, XP_GetString (MK_ADDR_DEFAULT_DLS)); + else { + if (PL_strcmp (namestring, "1") == 0) + status = WriteLineToStream (obj, XP_GetString (MK_ADDR_SPECIFIC_DLS)); + else + if (PL_strcmp (namestring, "2") == 0) + status = WriteLineToStream (obj, XP_GetString (MK_ADDR_HOSTNAMEIP)); + } + PR_FREEIF (namestring); + if (status < 0) return status; + } + } + status = OutputVcardAttribute (obj, prop, VCCooltalkAddress); + if (status < 0) return status; + } + + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* beginning of last row */ + /* output notes field */ + prop = isAPropertyOf(v, VCCommentProp); + if (prop) + { + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "3", NULL); + if (status < 0) return status; + status = OutputVcardAttribute (obj, v, VCCommentProp); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + } + + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + + /* output second table containing all the additional info */ + status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL); + if (status < 0) return status; + /* beginning of first row */ + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "2", NULL); + if (status < 0) return status; + /* output the additional info header */ + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) return status; + status = WriteLineToStream (obj, XP_GetString (MK_ADDR_ADDINFO)); + if (status < 0) return status; + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + /* beginning of remaining rows */ + status = WriteOutVCardProperties (obj, v, &numEmail); + if (status < 0) return status; + + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + + return 0; +} + +static int OutputButtons(MimeObject *obj, PRBool basic, VObject *v) +{ + int status = 0; + char * htmlLine = NULL; + char * htmlLine1 = NULL; + char * htmlLine2 = NULL; + char* vCard = NULL; + char* vEscCard = NULL; + int len = 0; + char* charset = NULL; + char* rsrcString = NULL; + char* converted = NULL; + PRInt16 fromCharsetID, toCharsetID; + + if (!obj->options->output_vcard_buttons_p) + return status; + + vCard = writeMemVObjects(0, &len, v); + + if (!vCard) + return MK_OUT_OF_MEMORY; + + vEscCard = NET_Escape (vCard, URL_XALPHAS); + + PR_FREEIF (vCard); + + if (!vEscCard) + return MK_OUT_OF_MEMORY; + + /* parse a content type for the charset */ + fromCharsetID = INTL_CharSetNameToID(INTL_ResourceCharSet()); + charset = PL_strstr(obj->content_type, "charset="); + toCharsetID = (charset != NULL) ? INTL_CharSetNameToID(charset+8) : INTL_DocToWinCharSetID(fromCharsetID); + + if (basic) + { + rsrcString = XP_GetString(MK_ADDR_VIEW_COMPLETE_VCARD); + /* convert from the resource charset. */ + converted = (fromCharsetID != toCharsetID) ? + (char *) INTL_ConvertLineWithoutAutoDetect( + fromCharsetID, toCharsetID, (unsigned char *) rsrcString, (PRUint32) PL_strlen(rsrcString)) : rsrcString; + if (converted == NULL) + converted = rsrcString; + + htmlLine1 = PR_smprintf ("
", + converted, unique); + } + else + { + rsrcString = XP_GetString(MK_ADDR_VIEW_CONDENSED_VCARD); + converted = (fromCharsetID != toCharsetID) ? + (char *) INTL_ConvertLineWithoutAutoDetect( + fromCharsetID, toCharsetID, (unsigned char *) rsrcString, (PRUint32) PL_strlen(rsrcString)) : rsrcString; + if (converted == NULL) + converted = rsrcString; + + htmlLine1 = PR_smprintf ("
", + converted, unique); + } + if (converted != rsrcString) + PR_FREEIF(converted); + + rsrcString = XP_GetString(MK_MSG_ADD_TO_ADDR_BOOK); + converted = (fromCharsetID != toCharsetID) ? + (char *) INTL_ConvertLineWithoutAutoDetect( + fromCharsetID, toCharsetID, (unsigned char *) rsrcString, (PRUint32) PL_strlen(rsrcString)) : rsrcString; + if (converted == NULL) + converted = rsrcString; + + htmlLine2 = PR_smprintf ("
", + vEscCard, converted); + if (converted != rsrcString) + PR_FREEIF(converted); + + + if (!htmlLine1 && !htmlLine2) + { + PR_FREEIF (vEscCard); + PR_FREEIF (htmlLine1); + PR_FREEIF (htmlLine2); + return MK_OUT_OF_MEMORY; + } + + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) goto FAIL; + + /* + * WARNING: This HTML is written to the stream using JavaScript, + * because we don't want this button to be displayed when JS has + * been switched off (in the whole client or just in email). The + * button won't work when JS is switched off (since it calls a JS + * function), so then we don't want the button to be displayed. + * -- erik (and jfriend) + */ + status = WriteEachLineToStream (obj, ""); + if (status < 0) goto FAIL; + + status = WriteLineToStream (obj, htmlLine2); + if (status < 0) goto FAIL; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) goto FAIL; + + FAIL: + PR_FREEIF (vEscCard); + PR_FREEIF (htmlLine1); + PR_FREEIF (htmlLine2); + + return status; +} + +static int BeginLayer(MimeObject *obj, PRBool basic) +{ + int status = 0; + char * captionLine = NULL; + + if (basic) + { +//RICHIECSS captionLine = PR_smprintf ("", unique); + captionLine = PR_smprintf ("
", unique); + } + else + { +//RICHIECSS captionLine = PR_smprintf ("", unique); + captionLine = PR_smprintf ("
", unique); + } + + if (captionLine) + { + status = WriteEachLineToStream (obj, captionLine); + PR_Free(captionLine); + if (status < 0) return status; + status = OutputTable (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTable (obj, PR_FALSE, PR_TRUE, "0", "0", "#FFFFFF"); + if (status < 0) return status; + if (basic) + { + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL); + if (status < 0) return status; + } + else + { + status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData(obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + } + + status = OutputTable (obj, PR_FALSE, PR_FALSE, "4", NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + } + else + status = MK_OUT_OF_MEMORY; + + return status; +} + +static int EndLayer(MimeObject *obj, PRBool basic, VObject* v) +{ + int status = 0; + char * captionLine = NULL; + + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + + status = OutputButtons(obj, basic, v); + if (status < 0) return status; + + status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL); + if (status < 0) return status; + status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL); + if (status < 0) return status; + + if (!basic) + { +//RICHIECSS status = WriteEachLineToStream (obj, ""); + status = WriteEachLineToStream (obj, "
"); + if (status < 0) return status; + status = WriteEachLineToStream (obj, "

"); + } + else { +//RICHIECSS status = WriteEachLineToStream (obj, ""); + status = WriteEachLineToStream (obj, "
"); + } + + if (status < 0) return status; + return 0; +} + +static int EndVCard (MimeObject *obj) +{ + int status = 0; + + /* Scribble HTML-ending stuff into the stream */ + char htmlFooters[32]; + PR_snprintf (htmlFooters, sizeof(htmlFooters), "%s%s", LINEBREAK, LINEBREAK); + status = MIME_MimeObject_write(obj, htmlFooters, PL_strlen(htmlFooters), PR_FALSE); + + if (status < 0) return status; + + if (obj->options && obj->options->set_html_state_fn) { + status = obj->options->set_html_state_fn(obj->options->stream_closure, + PR_TRUE, /* layer_encapulate_p */ + PR_FALSE, /* start_p */ + PR_FALSE); /* abort_p */ + if (status < 0) return status; + } + + return 0; +} + +static int BeginVCard (MimeObject *obj) +{ + int status = 0; + + /* Scribble HTML-starting stuff into the stream */ + char htmlHeaders[32]; + + if (obj->options && obj->options->set_html_state_fn) { + status = obj->options->set_html_state_fn(obj->options->stream_closure, + PR_TRUE, /* layer_encapulate_p */ + PR_TRUE, /* start_p */ + PR_FALSE); /* abort_p */ + if (status < 0) return status; + } + + unique++; + PR_snprintf (htmlHeaders, sizeof(htmlHeaders), "%s%s", LINEBREAK, LINEBREAK); + status = MIME_MimeObject_write(obj, htmlHeaders, PL_strlen(htmlHeaders), PR_TRUE); + + if (status < 0) return status; + + return 0; +} + +static int WriteOutVCard (MimeObject *obj, VObject* v) +{ + int status = 0; + + status = BeginVCard (obj); + if (status < 0) return status; + + /* write out basic layer */ + status = BeginLayer(obj, PR_TRUE); + if (status < 0) return status; + status = OutputBasicVcard(obj, v); + if (status < 0) return status; + status = EndLayer(obj, PR_TRUE, v); + if (status < 0) return status; + + /* write out advanced layer */ + status = BeginLayer(obj, PR_FALSE); + if (status < 0) return status; + status = OutputAdvancedVcard(obj, v); + if (status < 0) return status; + status = EndLayer(obj, PR_FALSE, v); + if (status < 0) return status; + + status = EndVCard (obj); + if (status < 0) return status; + + return 0; +} + +static void GetAddressProperties (VObject* o, char ** attribName) +{ + VObject* domProp = isAPropertyOf(o, VCDomesticProp); + VObject* intlProp = isAPropertyOf(o, VCInternationalProp); + VObject* postal = isAPropertyOf(o, VCPostalProp); + VObject* parcel = isAPropertyOf(o, VCParcelProp); + VObject* home = isAPropertyOf(o, VCHomeProp); + VObject* work = isAPropertyOf(o, VCWorkProp); + if (domProp) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_DOM_TYPE)); + } + if (intlProp) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_INTL_TYPE)); + } + if (postal) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_POSTAL_TYPE)); + } + if (parcel) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_PARCEL_TYPE)); + } + if (home) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_HOME_TYPE)); + } + if (work) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_WORK_TYPE)); + } +} + + +static void GetTelephoneProperties (VObject* o, char ** attribName) +{ + VObject* prefProp = isAPropertyOf(o, VCPreferredProp); + VObject* home = isAPropertyOf(o, VCHomeProp); + VObject* work = isAPropertyOf(o, VCWorkProp); + VObject* voiceProp = isAPropertyOf(o, VCVoiceProp); + VObject* fax = isAPropertyOf(o, VCFaxProp); + VObject* msg = isAPropertyOf(o, VCMessageProp); + VObject* cell = isAPropertyOf(o, VCCellularProp); + VObject* pager = isAPropertyOf(o, VCPagerProp); + VObject* bbs = isAPropertyOf(o, VCBBSProp); + if (prefProp) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_PREF_TYPE)); + } + if (home) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_HOME_TYPE)); + } + if (work) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_WORK_TYPE)); + } + if (voiceProp) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_VOICE_TYPE)); + } + if (fax) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_FAX_TYPE)); + } + if (msg) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_MSG_TYPE)); + } + if (cell) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_CELL_TYPE)); + } + if (pager) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_PAGER_TYPE)); + } + if (bbs) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_BBS_TYPE)); + } +} + +static void GetEmailProperties (VObject* o, char ** attribName) +{ + + VObject* prefProp = isAPropertyOf(o, VCPreferredProp); + VObject* home = isAPropertyOf(o, VCHomeProp); + VObject* work = isAPropertyOf(o, VCWorkProp); + VObject* aol = isAPropertyOf(o, VCAOLProp); + VObject* applelink = isAPropertyOf(o, VCAppleLinkProp); + VObject* att = isAPropertyOf(o, VCATTMailProp); + VObject* cis = isAPropertyOf(o, VCCISProp); + VObject* eworld = isAPropertyOf(o, VCEWorldProp); + VObject* internet = isAPropertyOf(o, VCInternetProp); + VObject* ibmmail = isAPropertyOf(o, VCIBMMailProp); + VObject* mcimail = isAPropertyOf(o, VCMCIMailProp); + VObject* powershare = isAPropertyOf(o, VCPowerShareProp); + VObject* prodigy = isAPropertyOf(o, VCProdigyProp); + VObject* telex = isAPropertyOf(o, VCTLXProp); + VObject* x400 = isAPropertyOf(o, VCX400Prop); + if (prefProp) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_PREF_TYPE)); + } + if (home) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_HOME_TYPE)); + } + if (work) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_WORK_TYPE)); + } + if (aol) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_AOL_TYPE)); + } + if (applelink) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_APPLELINK_TYPE)); + } + if (att) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_ATTMAIL_TYPE)); + } + if (cis) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_CSI_TYPE)); + } + if (eworld) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_EWORLD_TYPE)); + } + if (internet) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_INTERNET_TYPE)); + } + if (ibmmail) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_IBMMAIL_TYPE)); + } + if (mcimail) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_MCIMAIL_TYPE)); + } + if (powershare) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_POWERSHARE_TYPE)); + } + if (prodigy) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_PRODIGY_TYPE)); + } + if (telex) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_TLX_TYPE)); + } + if (x400) { + StrAllocCat ((*attribName), " "); + StrAllocCat ((*attribName), XP_GetString (MK_LDAP_X400)); + } + +} + +static int WriteOutEachVCardPhoneProperty (MimeObject *obj, VObject* o) +{ + char *attribName = NULL; + char *value = NULL; + int status = 0; + + if (vObjectName(o)) + { + if (PL_strcasecmp (VCTelephoneProp, vObjectName(o)) == 0) + { + if (VALUE_TYPE(o)) + { + GetTelephoneProperties(o, &attribName); + if (!attribName) + attribName = PL_strdup (XP_GetString (MK_LDAP_PHONE_NUMBER)); + attribName = StrAllocCat(attribName, ": "); + value = fakeCString (vObjectUStringZValue(o)); + if (value) + { + attribName = StrAllocCat (attribName, value); + PR_FREEIF (value); + if (attribName) + { + status = OutputFont(obj, PR_FALSE, "-1", NULL); + if (status < 0) { + PR_FREEIF (attribName); + return status; + } + status = WriteLineToStream (obj, attribName); + if (status < 0) { + PR_FREEIF (attribName); + return status; + } + status = OutputFont(obj, PR_TRUE, NULL, NULL); + if (status < 0) { + PR_FREEIF (attribName); + return status; + } + } + PR_FREEIF (attribName); + } + } + } + } + return status; +} + +static int WriteOutVCardPhoneProperties (MimeObject *obj, VObject* v) +{ + int status = 0; + VObjectIterator t; + VObject *eachProp; + + WriteOutEachVCardPhoneProperty (obj, v); + initPropIterator(&t,v); + while (moreIteration(&t) && status >= 0) + { + eachProp = nextVObject(&t); + status = WriteOutEachVCardPhoneProperty (obj, eachProp); + } + + if (status < 0) return status; + + return 0; +} + +static int WriteOutEachVCardProperty (MimeObject *obj, VObject* o, int* numEmail) +{ + char *attribName = NULL; + char * url = NULL; + char *value = NULL; + char *ptr = NULL; + int status = 0; + + if (vObjectName(o)) { + + if (PL_strcasecmp (VCPhotoProp, vObjectName(o)) == 0) { + VObject* urlProp = isAPropertyOf(o, VCURLProp); + if (urlProp) { + attribName = PL_strdup (XP_GetString (MK_LDAP_PHOTOGRAPH)); + /* format the value string to the url */ + value = fakeCString (vObjectUStringZValue(o)); + if (value) + url = PR_smprintf ("= 0) + { + eachProp = nextVObject(&t); + status = WriteOutVCardProperties (obj, eachProp, numEmail); + } + + if (status < 0) return status; + + return 0; +} + +static int WriteLineToStream (MimeObject *obj, const char *line) +{ + int status = 0; + char *htmlLine; + int htmlLen = PL_strlen(line) + PL_strlen("
") + 1;; + + htmlLine = (char *) PR_MALLOC (htmlLen); + if (htmlLine) + { + htmlLine[0] = '\0'; +// RICHIECSS - TEMPORARY FIX FOR A LAYOUT PROBLEM +// PL_strcat (htmlLine, "
"); + PL_strcat (htmlLine, line); +// RICHIECSS - TEMPORARY FIX FOR A LAYOUT PROBLEM +// PL_strcat (htmlLine, "
"); + status = MIME_MimeObject_write(obj, htmlLine, PL_strlen(htmlLine), PR_TRUE); + PR_Free ((void*) htmlLine); + } + else + status = MK_OUT_OF_MEMORY; + + return status; +} + +static int WriteAttribute (MimeObject *obj, const char *attrib) +{ + int status = 0; + OutputFont(obj, PR_FALSE, "-1", NULL); + status = WriteLineToStream (obj, attrib); + OutputFont(obj, PR_TRUE, NULL, NULL); + return status; +} + + +static int WriteValue (MimeObject *obj, const char *value) +{ + int status = 0; + OutputFont(obj, PR_FALSE, "-1", NULL); + status = WriteLineToStream (obj, value); + OutputFont(obj, PR_TRUE, NULL, NULL); + return status; +} + + diff --git a/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.h b/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.h new file mode 100644 index 00000000000..ad159f329e6 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/mimevcrd.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _MIMEVCRD_H_ +#define _MIMEVCRD_H_ + +#include "mimetext.h" + +/* The MimeInlineTextHTML class implements the text/x-vcard and (maybe? + someday?) the application/directory MIME content types. + */ + +typedef struct MimeInlineTextVCardClass MimeInlineTextVCardClass; +typedef struct MimeInlineTextVCard MimeInlineTextVCard; + +struct MimeInlineTextVCardClass { + MimeInlineTextClass text; + char* vCardString; +}; + +extern MimeInlineTextVCardClass mimeInlineTextVCardClass; + +struct MimeInlineTextVCard { + MimeInlineText text; +}; + +#endif /* _MIMEVCRD_H_ */ diff --git a/mozilla/mailnews/mime/cthandlers/vcard/oldi18n.c b/mozilla/mailnews/mime/cthandlers/vcard/oldi18n.c new file mode 100644 index 00000000000..7ca7a32cb1e --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/oldi18n.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#include "xp.h" +#include "prmem.h" +#include "plstr.h" +#include "intl_csi.h" + +INTL_CharSetInfo +LO_GetDocumentCharacterSetInfo(MWContext *context) +{ + /* MOZ_FUNCTION_STUB; */ + return NULL; +} + +void +INTL_CharSetIDToName(int16 csid, char *charset) +{ + if (charset) { + PR_ASSERT(INTL_CsidToCharsetNamePt(csid)); + if (INTL_CsidToCharsetNamePt(csid)) + PL_strcpy(charset,(char *)INTL_CsidToCharsetNamePt(csid)); + else + charset = NULL; + } +} + + +/* INTL_ResourceCharSet(void) */ +char *INTL_ResourceCharSet(void) +{ + return ("iso-8859-1"); +} + +/* ----------- CSI CSID ----------- */ +void +INTL_SetCSIDocCSID (INTL_CharSetInfo c, int16 doc_csid) +{ + return; +} + +int16 +INTL_GetCSIDocCSID(INTL_CharSetInfo c) +{ + return 0; +} + +unsigned char *INTL_ConvertLineWithoutAutoDetect( + int16 fromcsid, + int16 tocsid, + unsigned char *pSrc, + PRUint32 block_size) +{ + return NULL; +} + +/* + * INTL_DocToWinCharSetID, + * Based on DefaultDocCSID, it determines which Win CSID to use for Display + */ +int16 +INTL_DocToWinCharSetID(int16 csid) +{ + /* MOZ_FUNCTION_STUB; */ + return CS_FE_ASCII; +} + +int16 +INTL_DefaultDocCharSetID(iDocumentContext context) +{ + return CS_DEFAULT; +} + +unsigned char *INTL_ConvMailToWinCharCode( + iDocumentContext context, + unsigned char *bit7buff, + PRUint32 block_size +) +{ + return NULL; +} diff --git a/mozilla/mailnews/mime/cthandlers/vcard/oldnet.c b/mozilla/mailnews/mime/cthandlers/vcard/oldnet.c new file mode 100644 index 00000000000..c808c33e0c5 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/oldnet.c @@ -0,0 +1,1346 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + * netlib.c - external dependencies on the old netlib + */ + +#include "xp.h" +#include "rosetta.h" + +#include "prmem.h" +#include "plstr.h" + +#define CONST const + +extern int MK_OUT_OF_MEMORY; + +/* from libnet/mkutils.c */ +PUBLIC char * +NET_EscapeHTML(const char * string) +{ + char *rv = (char *) PR_MALLOC(PL_strlen(string)*4 + 1); /* The +1 is for + the trailing + null! */ + char *ptr = rv; + + if(rv) + { + for(; *string != '\0'; string++) + { + if(*string == '<') + { + *ptr++ = '&'; + *ptr++ = 'l'; + *ptr++ = 't'; + *ptr++ = ';'; + } + else if(*string == '>') + { + *ptr++ = '&'; + *ptr++ = 'g'; + *ptr++ = 't'; + *ptr++ = ';'; + } + else if(*string == '&') + { + *ptr++ = '&'; + *ptr++ = 'a'; + *ptr++ = 'm'; + *ptr++ = 'p'; + *ptr++ = ';'; + } + else + { + *ptr++ = *string; + } + } + *ptr = '\0'; + } + + return(rv); +} + + +/* from libnet/mkutils.c */ +# define MSG_FONT int +# define MSG_PlainFont 0 +# define MSG_BoldFont 1 +# define MSG_ItalicFont 2 +# define MSG_BoldItalicFont 3 +# define MSG_CITATION_SIZE int +# define MSG_NormalSize 4 +# define MSG_Bigger 5 +# define MSG_Smaller 6 +static int MSG_CitationFont = MSG_ItalicFont; +static int MSG_CitationSize = MSG_NormalSize; +static const char *MSG_CitationColor = 0; + +#ifndef MOZILLA_30 +# define MSG_Prefs void +# define MSG_GetCitationStyle(w,x,y,z) do{}while(0) +# define MSG_GetPrefs(x) 0 +#endif + +/* from libnet/mkutils.c */ +PUBLIC int +NET_ScanForURLs( +#ifndef MOZILLA_30 + MSG_Pane* pane, +#endif /* !MOZILLA_30 */ + const char *input, PRInt32 input_size, + char *output, int output_size, XP_Bool urls_only) +{ + int col = 0; + const char *cp; + const char *end = input + input_size; + char *output_ptr = output; + char *end_of_buffer = output + output_size - 40; /* add safty zone :( */ + Bool line_is_citation = PR_FALSE; + const char *cite_open1, *cite_close1; + const char *cite_open2, *cite_close2; +#ifndef MOZILLA_30 + const char* color = NULL; +#else /* MOZILLA_30 */ + const char* color = MSG_CitationColor; +#endif /* MOZILLA_30 */ + + if (urls_only) + { + cite_open1 = cite_close1 = ""; + cite_open2 = cite_close2 = ""; + } + else + { +#ifdef MOZILLA_CLIENT +# ifdef MOZILLA_30 + MSG_FONT font = MSG_CitationFont; + MSG_CITATION_SIZE size = MSG_CitationSize; +# else /* !MOZILLA_30 */ + MSG_Prefs* prefs; + MSG_FONT font = MSG_ItalicFont; + MSG_CITATION_SIZE size = MSG_NormalSize; + + if (pane) { + prefs = MSG_GetPrefs(pane); + MSG_GetCitationStyle(prefs, &font, &size, &color); + } +#endif /* !MOZILLA_30 */ + switch (font) + { + case MSG_PlainFont: + cite_open1 = "", cite_close1 = ""; + break; + case MSG_BoldFont: + cite_open1 = "", cite_close1 = ""; + break; + case MSG_ItalicFont: + cite_open1 = "", cite_close1 = ""; + break; + case MSG_BoldItalicFont: + cite_open1 = "", cite_close1 = ""; + break; + default: + PR_ASSERT(0); + cite_open1 = cite_close1 = ""; + break; + } + switch (size) + { + case MSG_NormalSize: + cite_open2 = "", cite_close2 = ""; + break; + case MSG_Bigger: + cite_open2 = "", cite_close2 = ""; + break; + case MSG_Smaller: + cite_open2 = "", cite_close2 = ""; + break; + default: + PR_ASSERT(0); + cite_open2 = cite_close2 = ""; + break; + } +#else /* !MOZILLA_CLIENT */ + PR_ASSERT(0); +#endif /* !MOZILLA_CLIENT */ + } + + if (!urls_only) + { + /* Decide whether this line is a quotation, and should be italicized. + This implements the following case-sensitive regular expression: + + ^[ \t]*[A-Z]*[]>] + + Which matches these lines: + + > blah blah blah + > blah blah blah + LOSER> blah blah blah + LOSER] blah blah blah + */ + const char *s = input; + while (s < end && XP_IS_SPACE (*s)) s++; + while (s < end && *s >= 'A' && *s <= 'Z') s++; + + if (s >= end) + ; + else if (input_size >= 6 && *s == '>' && + !PL_strncmp (input, ">From ", 6)) /* #$%^ing sendmail... */ + ; + else if (*s == '>' || *s == ']') + { + line_is_citation = PR_TRUE; + PL_strcpy(output_ptr, cite_open1); + output_ptr += PL_strlen(cite_open1); + PL_strcpy(output_ptr, cite_open2); + output_ptr += PL_strlen(cite_open2); + if (color && + output_ptr + PL_strlen(color) + 20 < end_of_buffer) { + PL_strcpy(output_ptr, ""); + output_ptr += PL_strlen(output_ptr); + } + } + } + + /* Normal lines are scanned for buried references to URL's + Unfortunately, it may screw up once in a while (nobody's perfect) + */ + for(cp = input; cp < end && output_ptr < end_of_buffer; cp++) + { + /* if NET_URL_Type returns true then it is most likely a URL + But only match protocol names if at the very beginning of + the string, or if the preceeding character was not alphanumeric; + this lets us match inside "---HTTP://XXX" but not inside of + things like "NotHTTP://xxx" + */ + int type = 0; + if(!XP_IS_SPACE(*cp) && + (cp == input || (!XP_IS_ALPHA(cp[-1]) && !XP_IS_DIGIT(cp[-1]))) && + (type = NET_URL_Type(cp)) != 0) + { + const char *cp2; +#if 0 + Bool commas_ok = (type == MAILTO_TYPE_URL); +#endif + + for(cp2=cp; cp2 < end; cp2++) + { + /* These characters always mark the end of the URL. */ + if (XP_IS_SPACE(*cp2) || + *cp2 == '<' || *cp2 == '>' || + *cp2 == '`' || *cp2 == ')' || + *cp2 == '\'' || *cp2 == '"' || + *cp2 == ']' || *cp2 == '}' +#if 0 + || *cp2 == '!' +#endif + ) + break; + +#if 0 + /* But a "," marks the end of the URL only if there was no "?" + earlier in the URL (this is so we can do imagemaps, like + "foo.html?300,400".) + */ + else if (*cp2 == '?') + commas_ok = PR_TRUE; + else if (*cp2 == ',' && !commas_ok) + break; +#endif + } + + /* Check for certain punctuation characters on the end, and strip + them off. */ + while (cp2 > cp && + (cp2[-1] == '.' || cp2[-1] == ',' || cp2[-1] == '!' || + cp2[-1] == ';' || cp2[-1] == '-' || cp2[-1] == '?' || + cp2[-1] == '#')) + cp2--; + + col += (cp2 - cp); + + /* if the url is less than 7 characters then we screwed up + * and got a "news:" url or something which is worthless + * to us. Exclude the A tag in this case. + * + * Also exclude any URL that ends in a colon; those tend + * to be internal and magic and uninteresting. + * + * And also exclude the builtin icons, whose URLs look + * like "internal-gopher-binary". + */ + if (cp2-cp < 7 || + (cp2 > cp && cp2[-1] == ':') || + !PL_strncmp(cp, "internal-", 9)) + { + XP_MEMCPY(output_ptr, cp, cp2-cp); + output_ptr += (cp2-cp); + *output_ptr = 0; + } + else + { + char *quoted_url; + PRInt32 size_left = output_size - (output_ptr-output); + + if(cp2-cp > size_left) + return MK_OUT_OF_MEMORY; + + XP_MEMCPY(output_ptr, cp, cp2-cp); + output_ptr[cp2-cp] = 0; + quoted_url = NET_EscapeHTML(output_ptr); + if (!quoted_url) return MK_OUT_OF_MEMORY; + PR_snprintf(output_ptr, size_left, + "%s", + quoted_url, + quoted_url); + output_ptr += PL_strlen(output_ptr); + PR_Free(quoted_url); + output_ptr += PL_strlen(output_ptr); + } + + cp = cp2-1; /* go to next word */ + } + else + { + /* Make sure that special symbols don't screw up the HTML parser + */ + if(*cp == '<') + { + PL_strcpy(output_ptr, "<"); + output_ptr += 4; + col++; + } + else if(*cp == '>') + { + PL_strcpy(output_ptr, ">"); + output_ptr += 4; + col++; + } + else if(*cp == '&') + { + PL_strcpy(output_ptr, "&"); + output_ptr += 5; + col++; + } + else + { + *output_ptr++ = *cp; + col++; + } + } + } + + *output_ptr = 0; + + if (line_is_citation) /* Close off the highlighting */ + { + if (color) { + PL_strcpy(output_ptr, ""); + output_ptr += PL_strlen(output_ptr); + } + + PL_strcpy(output_ptr, cite_close2); + output_ptr += PL_strlen (cite_close2); + PL_strcpy(output_ptr, cite_close1); + output_ptr += PL_strlen (cite_close1); + } + + return 0; +} + + +/* from libnet/mkutils.c */ +PUBLIC int +NET_URL_Type (CONST char *URL) +{ + /* Protect from SEGV */ + if (!URL || (URL && *URL == '\0')) + return(0); + + switch(*URL) { + case 'a': + case 'A': + if(!PL_strncasecmp(URL,"about:security", 14)) + return(SECURITY_TYPE_URL); + else if(!PL_strncasecmp(URL,"about:",6)) + return(ABOUT_TYPE_URL); + break; + case 'f': + case 'F': + if(!PL_strncasecmp(URL,"ftp:",4)) + return(FTP_TYPE_URL); + else if(!PL_strncasecmp(URL,"file:",5)) + return(FILE_TYPE_URL); + break; + case 'g': + case 'G': + if(!PL_strncasecmp(URL,"gopher:",7)) + return(GOPHER_TYPE_URL); + break; + case 'h': + case 'H': + if(!PL_strncasecmp(URL,"http:",5)) + return(HTTP_TYPE_URL); + else if(!PL_strncasecmp(URL,"https:",6)) + return(SECURE_HTTP_TYPE_URL); + break; + case 'i': + case 'I': + if(!PL_strncasecmp(URL,"internal-gopher-",16)) + return(INTERNAL_IMAGE_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-news-",14)) + return(INTERNAL_IMAGE_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-edit-",14)) + return(INTERNAL_IMAGE_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-attachment-",20)) + return(INTERNAL_IMAGE_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-dialog-handler",23)) + return(HTML_DIALOG_HANDLER_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-panel-handler",22)) + return(HTML_PANEL_HANDLER_TYPE_URL); + else if(!PL_strncasecmp(URL,"internal-security-",18)) + return(INTERNAL_SECLIB_TYPE_URL); + else if(!PL_strncasecmp(URL,"IMAP:",5)) + return(IMAP_TYPE_URL); + break; + case 'j': + case 'J': + if(!PL_strncasecmp(URL, "javascript:",11)) + return(MOCHA_TYPE_URL); + break; + case 'l': + case 'L': + if(!PL_strncasecmp(URL, "livescript:",11)) + return(MOCHA_TYPE_URL); + break; + case 'm': + case 'M': + if(!PL_strncasecmp(URL,"mailto:",7)) + return(MAILTO_TYPE_URL); + else if(!PL_strncasecmp(URL,"mailbox:",8)) + return(MAILBOX_TYPE_URL); + else if(!PL_strncasecmp(URL, "mocha:",6)) + return(MOCHA_TYPE_URL); + break; + case 'n': + case 'N': + if(!PL_strncasecmp(URL,"news:",5)) + return(NEWS_TYPE_URL); +#ifdef NFS_TYPE_URL + else if(!PL_strncasecmp(URL,"nfs:",4)) + return(NFS_TYPE_URL); +#endif /* NFS_TYPE_URL */ + break; + case 'p': + case 'P': + if(!PL_strncasecmp(URL,"pop3:",5)) + return(POP3_TYPE_URL); + break; + case 'r': + case 'R': + if(!PL_strncasecmp(URL,"rlogin:",7)) + return(RLOGIN_TYPE_URL); + break; + case 's': + case 'S': + if(!PL_strncasecmp(URL,"snews:",6)) + return(NEWS_TYPE_URL); + case 't': + case 'T': + if(!PL_strncasecmp(URL,"telnet:",7)) + return(TELNET_TYPE_URL); + else if(!PL_strncasecmp(URL,"tn3270:",7)) + return(TN3270_TYPE_URL); + break; + case 'v': + case 'V': + if(!PL_strncasecmp(URL, VIEW_SOURCE_URL_PREFIX, + sizeof(VIEW_SOURCE_URL_PREFIX)-1)) + return(VIEW_SOURCE_TYPE_URL); + break; + case 'w': + case 'W': + if(!PL_strncasecmp(URL,"wais:",5)) + return(WAIS_TYPE_URL); + break; + case 'u': + case 'U': + if(!PL_strncasecmp(URL,"URN:",4)) + return(URN_TYPE_URL); + break; + + } + + /* no type match :( */ + return(0); +} + + + +/* from libnet/mkparse.c */ +PRIVATE CONST +int netCharType[256] = +/* Bit 0 xalpha -- the alphas +** Bit 1 xpalpha -- as xalpha but +** converts spaces to plus and plus to %20 +** Bit 3 ... path -- as xalphas but doesn't escape '/' +*/ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */ + 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */ + 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */ + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */ + 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */ + 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */ + 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */ + 0, }; + +#define IS_OK(C) (netCharType[((unsigned int) (C))] & (mask)) + + +#define HEX_ESCAPE '%' + + +PUBLIC char * +NET_Escape (const char * str, int mask) +{ + register CONST unsigned char *src; + register unsigned char *dst; + char *result; + PRInt32 extra = 0; + char *hexChars = "0123456789ABCDEF"; + + if(!str) + return(0); + + for(src=((unsigned char *)str); *src; src++) + { + if (!IS_OK(*src)) + extra+=2; /* the escape, plus an extra byte for each nibble */ + } + + if(!(result = (char *) PR_MALLOC((PRInt32) (src - ((unsigned char *)str)) + extra + 1))) + return(0); + + dst = (unsigned char *) result; + for(src=((unsigned char *)str); *src; src++) + if (IS_OK((unsigned char) (*src))) + { + *dst++ = *src; + } + else if(mask == URL_XPALPHAS && *src == ' ') + { + *dst++ = '+'; /* convert spaces to pluses */ + } + else + { + *dst++ = HEX_ESCAPE; + *dst++ = hexChars[(*src >> 4) & 0x0f]; /* high nibble */ + *dst++ = hexChars[*src & 0x0f]; /* low nibble */ + } + + *dst++ = '\0'; /* tack on eos */ + return result; +} + +XP_List * ExternalURLTypeList=0; + +#define EXTERNAL_TYPE_URL 999 /* a special external URL type */ + +/* check the passed in url to see if it is an + * external type url + */ +PRIVATE int +net_CheckForExternalURLType(char * url) +{ + XP_List * list_ptr = ExternalURLTypeList; + char * reg_type; + int len; + + while((reg_type = (char *)XP_ListNextObject(list_ptr))) + { + len = PL_strlen(reg_type); + if(!PL_strncasecmp(reg_type, url, len) && url[len] == ':') + { + /* found it */ + return EXTERNAL_TYPE_URL; /* done */ + } + } + + return(0); +} + +/* modifies a url of the form /foo/../foo1 -> /foo1 + * + * it only operates on "file" "ftp" and "http" url's all others are returned + * unmodified + * + * returns the modified passed in URL string + */ +PRIVATE char * +net_ReduceURL (char *url) +{ + int url_type = NET_URL_Type(url); + char * fwd_ptr; + char * url_ptr; + char * path_ptr; + + if(!url) + return(url); + + if(url_type == HTTP_TYPE_URL || url_type == FILE_TYPE_URL || + url_type == FTP_TYPE_URL || + url_type == SECURE_HTTP_TYPE_URL) + { + + /* find the path so we only change that and not the host + */ + path_ptr = PL_strchr(url, '/'); + + if(!path_ptr) + return(url); + + if(*(path_ptr+1) == '/') + path_ptr = PL_strchr(path_ptr+2, '/'); + + if(!path_ptr) + return(url); + + fwd_ptr = path_ptr; + url_ptr = path_ptr; + + for(; *fwd_ptr != '\0'; fwd_ptr++) + { + + if(*fwd_ptr == '/' && *(fwd_ptr+1) == '.' && *(fwd_ptr+2) == '/') + { + /* remove ./ + */ + fwd_ptr += 1; + } + else if(*fwd_ptr == '/' && *(fwd_ptr+1) == '.' && *(fwd_ptr+2) == '.' && + (*(fwd_ptr+3) == '/' || *(fwd_ptr+3) == '\0')) + { + /* remove foo/.. + */ + /* reverse the url_ptr to the previous slash + */ + if(url_ptr != path_ptr) + url_ptr--; /* we must be going back at least one */ + for(;*url_ptr != '/' && url_ptr != path_ptr; url_ptr--) + ; /* null body */ + + /* forward the fwd_prt past the ../ + */ + fwd_ptr += 2; + } + else + { + /* copy the url incrementaly + */ + *url_ptr++ = *fwd_ptr; + } + } + *url_ptr = '\0'; /* terminate the url */ + } + + return(url); +} + + +/* Makes a relative URL into an absolute one. + * + * If an absolute url is passed in it will be copied and returned. + * + * Always returns a malloc'd string or NULL on out of memory error + */ +PUBLIC char * +NET_MakeAbsoluteURL(char * absolute_url, char * relative_url) +{ + char * ret_url=0; + int new_length; + char * cat_point=0; + char cat_point_char; + int url_type=0; + int base_type; + + /* if either is NULL + */ + if(!absolute_url || !relative_url) + { + StrAllocCopy(ret_url, relative_url); + return(ret_url); + } + + /* use the URL_Type function to figure + * out if it's a recognized URL method + */ + url_type = NET_URL_Type(relative_url); + + /* there are some extra cases we need to catch + */ + if(!url_type) + { + switch(*relative_url) + { + case 'i': + if(!PL_strncmp(relative_url,"internal-icon-", 14) + || !PL_strncmp(relative_url,"internal-external-reconnect:", 28) + || !PL_strcmp(relative_url,"internal-external-plugin")) + url_type = INTERNAL_IMAGE_TYPE_URL; + break; + case '/': + if(!PL_strncasecmp(relative_url, "/mc-icons/", 10) || + !PL_strncasecmp(relative_url, "/ns-icons/", 10)) + { + if(!PL_strcmp(relative_url+10, "menu.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "unknown.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "text.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "image.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "sound.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "binary.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + else if(!PL_strcmp(relative_url+10, "movie.gif")) + url_type = INTERNAL_IMAGE_TYPE_URL; + } + break; + } + } + else if(url_type == ABOUT_TYPE_URL) + { + /* don't allow about:cache in a document */ + if(!PL_strncasecmp(relative_url, "about:cache", 11) + || !PL_strncasecmp(relative_url, "about:global", 12) + || !PL_strncasecmp(relative_url, "about:image-cache", 17) + || !PL_strncasecmp(relative_url, "about:memory-cache", 18)) + { + return PL_strdup(""); + } + } + + if(!url_type) + url_type = net_CheckForExternalURLType(relative_url); + + if(url_type) + { + /* it's either an absolute url + * or a messed up one of the type proto:/path + * but notice the missing host. + */ + char * colon = PL_strchr(relative_url, ':'); /* must be there */ + + if( (colon && *(colon+1) == '/' && *(colon+2) == '/') || + (url_type != GOPHER_TYPE_URL + && url_type != FTP_TYPE_URL + && url_type != HTTP_TYPE_URL + && url_type != SECURE_HTTP_TYPE_URL + && url_type != RLOGIN_TYPE_URL + && url_type != TELNET_TYPE_URL + && url_type != TN3270_TYPE_URL + && url_type != WAIS_TYPE_URL) ) + { + /* it appears to have all it's parts. Assume it's completely + * absolute + */ + StrAllocCopy(ret_url, relative_url); + return(ret_url); + } + else + { + /* it's a screwed up relative url of the form http:[relative url] + * remove the stuff before and at the colon and treat it as a normal + * relative url + */ + char * colon = PL_strchr(relative_url, ':'); + + relative_url = colon+1; + } + } + + + /* At this point, we know that `relative_url' is not absolute. + If the base URL, `absolute_url', is a "mailbox:" URL, then + we should not allow relative expansion: that is, + NET_MakeAbsoluteURL("mailbox:/A/B/C", "YYY") should not + return "mailbox:/A/B/YYY". + + However, expansion of "#" and "?" parameters should work: + NET_MakeAbsoluteURL("mailbox:/A/B/C?id=XXX", "#part2") + should be allowed to expand to "mailbox:/A/B/C?id=XXX#part2". + + If you allow random HREFs in attached HTML to mail messages to + expand to mailbox URLs, then bad things happen -- among other + things, an entry will be automatically created in the folders + list for each of these bogus non-files. + + It's an open question as to whether relative expansion should + be allowed for news: and snews: URLs. + + Reasons to allow it: + + = ClariNet has been using it + + = (Their reason:) it's the only way for an HTML news message + to refer to another HTML news message in a way which + doesn't make assumptions about the name of the news host, + and which also doesn't assume that the message is on the + default news host. + + Reasons to disallow it: + + = Consistency with "mailbox:" + + = If there is a news message which has type text/html, and + which has a relative URL like in it, + but which has no tag, then we would expand that + image to "news:foo.gif". Which would fail, of course, + but which might annoy news admins by generating bogus + references. + + So for now, let's allow + NET_MakeAbsoluteURL("news:123@4", "456@7") => "news:456@7"; and + NET_MakeAbsoluteURL("news://h/123@4", "456@7") => "news://h/456@7". + */ + base_type = NET_URL_Type(absolute_url); + if ((base_type == MAILBOX_TYPE_URL || base_type == IMAP_TYPE_URL) && + *relative_url != '#' && + *relative_url != '?') + { + return PL_strdup(""); + } + + if(relative_url[0] == '/' && relative_url[1] == '/') + { + /* a host absolute URL + */ + + /* find the colon after the protocol + */ + cat_point = PL_strchr(absolute_url, ':'); + if (cat_point && base_type == WYSIWYG_TYPE_URL) + cat_point = PL_strchr(cat_point + 1, ':'); + + /* append after the colon + */ + if(cat_point) + cat_point++; + + } + else if(relative_url[0] == '/') + { + /* a path absolute URL + * append at the slash after the host part + */ + + /* find the colon after the protocol + */ + char *colon = PL_strchr(absolute_url, ':'); + if (colon && base_type == WYSIWYG_TYPE_URL) + colon = PL_strchr(colon + 1, ':'); + + if(colon) + { + if(colon[1] == '/' && colon[2] == '/') + { + /* find the next slash + */ + cat_point = PL_strchr(colon+3, '/'); + + if(!cat_point) + { + /* if there isn't another slash then the cat point is the very end + */ + cat_point = &absolute_url[PL_strlen(absolute_url)]; + } + } + else + { + /* no host was given so the cat_point is right after the colon + */ + cat_point = colon+1; + } + +#if defined(XP_WIN) || defined(XP_OS2) + /* this will allow drive letters to work right on windows + */ + if(XP_IS_ALPHA(*cat_point) && *(cat_point+1) == ':') + cat_point += 2; +#endif /* XP_WIN */ + + } + } + else if(relative_url[0] == '#') + { + /* a positioning within the same document relative url + * + * add teh relative url to the full text of the absolute url minus + * any # punctuation the url might have + * + */ + char * hash = PL_strchr(absolute_url, '#'); + + if(hash) + { + char * ques_mark = PL_strchr(absolute_url, '?'); + + if(ques_mark) + { + /* this is a hack. + * copy things to try and make them more correct + */ + *hash = '\0'; + + StrAllocCopy(ret_url, absolute_url); + StrAllocCat(ret_url, relative_url); + StrAllocCat(ret_url, ques_mark); + + *hash = '#'; + + return(net_ReduceURL(ret_url)); + } + + cat_point = hash; + } + else + { + cat_point = &absolute_url[PL_strlen(absolute_url)]; /* the end of the URL */ + } + } + else + { + /* a completely relative URL + * + * append after the last slash + */ + char * ques = PL_strchr(absolute_url, '?'); + char * hash = PL_strchr(absolute_url, '#'); + + if(ques) + *ques = '\0'; + + if(hash) + *hash = '\0'; + + cat_point = PL_strrchr(absolute_url, '/'); + + /* if there are no slashes then append right after the colon after the protocol + */ + if(!cat_point) + cat_point = PL_strchr(absolute_url, ':'); + + /* set the value back + */ + if(ques) + *ques = '?'; + + if(hash) + *hash = '#'; + + if(cat_point) + cat_point++; /* append right after the slash or colon not on it */ + } + + if(cat_point) + { + cat_point_char = *cat_point; /* save the value */ + *cat_point = '\0'; + new_length = PL_strlen(absolute_url) + PL_strlen(relative_url) + 1; + ret_url = (char *) PR_MALLOC(new_length); + if(!ret_url) + return(NULL); /* out of memory */ + + PL_strcpy(ret_url, absolute_url); + PL_strcat(ret_url, relative_url); + *cat_point = cat_point_char; /* set the absolute url back to its original state */ + } + else + { + /* something went wrong. just return a copy of the relative url + */ + StrAllocCopy(ret_url, relative_url); + } + + return(net_ReduceURL(ret_url)); +} + +/* Very similar to strdup except it free's too + */ +PUBLIC char * +NET_SACopy (char **destination, const char *source) +{ + if(*destination) + { + PR_Free(*destination); + *destination = 0; + } + if (! source) + { + *destination = NULL; + } + else + { + *destination = (char *) PR_Malloc (PL_strlen(source) + 1); + if (*destination == NULL) + return(NULL); + + PL_strcpy (*destination, source); + } + return *destination; +} + +/* Again like strdup but it concatinates and free's and uses Realloc +*/ +PUBLIC char * +NET_SACat (char **destination, const char *source) +{ + if (source && *source) + { + if (*destination) + { + int length = PL_strlen (*destination); + *destination = (char *) PR_Realloc (*destination, length + PL_strlen(source) + 1); + if (*destination == NULL) + return(NULL); + + PL_strcpy (*destination + length, source); + } + else + { + *destination = (char *) PR_Malloc (PL_strlen(source) + 1); + if (*destination == NULL) + return(NULL); + + PL_strcpy (*destination, source); + } + } + return *destination; +} + +/* decode % escaped hex codes into character values + */ +#define UNHEX(C) \ + ((C >= '0' && C <= '9') ? C - '0' : \ + ((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \ + ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0))) + +PUBLIC int +NET_UnEscapeCnt (char * str) +{ + register char *src = str; + register char *dst = str; + + while(*src) + if (*src != HEX_ESCAPE) + { + *dst++ = *src++; + } + else + { + src++; /* walk over escape */ + if (*src) + { + *dst = UNHEX(*src) << 4; + src++; + } + if (*src) + { + *dst = (*dst + UNHEX(*src)); + src++; + } + dst++; + } + + *dst = 0; + + return (int)(dst - str); + +} /* NET_UnEscapeCnt */ + +PUBLIC char * +NET_UnEscape(char * str) +{ + (void)NET_UnEscapeCnt(str); + + return str; +} + +#define ISHEX(c) ( ((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F') ) +#define NONHEX(c) (!ISHEX(c)) + +PUBLIC char * +escape_unescaped_percents(const char *incomingURL) +{ + const char *inC; + char *outC; + char *result = (char *) PR_Malloc(PL_strlen(incomingURL)*3+1); + + if (result) + { + for(inC = incomingURL, outC = result; *inC != '\0'; inC++) + { + if (*inC == '%') + { + // Check if either of the next two characters are non-hex. + if ( !*(inC+1) || NONHEX(*(inC+1)) || !*(inC+2) || NONHEX(*(inC+2)) ) + { + // Hex characters don't follow, escape the + // percent char + *outC++ = '%'; *outC++ = '2'; *outC++ = '5'; + } + else + { + // Hex characters follow, so assume the percent + // is escaping something else + *outC++ = *inC; + } + } + else + *outC++ = *inC; + } + *outC = '\0'; + } + + return result; +} + +#define INITIAL_MAX_ALL_HEADERS 10 + +/* malloc, init, and set the URL structure used + * for the network library + */ +PUBLIC URL_Struct * +NET_CreateURLStruct (CONST char *url, NET_ReloadMethod force_reload) +{ + PRUint32 all_headers_size; + URL_Struct * URL_s = PR_NEW(URL_Struct); + + if(!URL_s) + { + return NULL; + } + + /* zap the whole structure */ + memset (URL_s, 0, sizeof (URL_Struct)); + + URL_s->SARCache = NULL; + + /* we haven't modified the address at all (since we are just creating it)*/ + URL_s->address_modified=NO; + + URL_s->method = URL_GET_METHOD; + + URL_s->force_reload = force_reload; + + URL_s->load_background = PR_FALSE; + + URL_s->ref_count = 1; + + /* Allocate space for pointers to hold message (http, news etc) headers */ + all_headers_size = + INITIAL_MAX_ALL_HEADERS * sizeof (URL_s->all_headers.key[0]); + URL_s->all_headers.key = (char **) PR_Malloc(all_headers_size); + if(!URL_s->all_headers.key) + { + NET_FreeURLStruct(URL_s); + return NULL; + } + memset (URL_s->all_headers.key, 0, all_headers_size); + + all_headers_size = + INITIAL_MAX_ALL_HEADERS * sizeof (URL_s->all_headers.value[0]); + URL_s->all_headers.value = (char **) PR_Malloc(all_headers_size); + if(!URL_s->all_headers.value) + { + NET_FreeURLStruct(URL_s); + return NULL; + } + memset (URL_s->all_headers.value, 0, all_headers_size); + + URL_s->all_headers.max_index = INITIAL_MAX_ALL_HEADERS; + + URL_s->owner_data = NULL; + URL_s->owner_id = 0; + + /* set the passed in value */ + StrAllocCopy(URL_s->address, url); + if (!URL_s->address) { + /* out of memory, clean up previously allocated objects */ + NET_FreeURLStruct(URL_s); + URL_s = NULL; + } + +#ifdef TRUST_LABELS + /* add the newly minted URL_s struct to the list of the same so + * that when cookie to trust label matching occurs I can find the + * associated trust list */ + if ( URL_s && net_URL_sList ) { + LIBNET_LOCK(); + XP_ListAddObjectToEnd( net_URL_sList, URL_s ); + LIBNET_UNLOCK(); + } +#endif + + return(URL_s); +} + +/* free the contents of AllHeader structure that is part of URL_Struct + */ +PRIVATE void +net_FreeURLAllHeaders (URL_Struct * URL_s) +{ + PRUint32 i=0; + + /* Free all memory associated with header information */ + for (i = 0; i < URL_s->all_headers.empty_index; i++) { + if (URL_s->all_headers.key) { + PR_FREEIF(URL_s->all_headers.key[i]); + } + if (URL_s->all_headers.value) { + PR_FREEIF(URL_s->all_headers.value[i]); + } + } + URL_s->all_headers.empty_index = URL_s->all_headers.max_index = 0; + + PR_FREEIF(URL_s->all_headers.key); + PR_FREEIF(URL_s->all_headers.value); + URL_s->all_headers.key = URL_s->all_headers.value = NULL; +} + + +/* free the contents and the URL structure when finished + */ +PUBLIC void +NET_FreeURLStruct (URL_Struct * URL_s) +{ + if(!URL_s) + return; + + /* if someone is holding onto a pointer to us don't die */ + PR_ASSERT(URL_s->ref_count > 0); + URL_s->ref_count--; + if(URL_s->ref_count > 0) + return; + +#ifdef TRUST_LABELS + /* remove URL_s struct from the list of the same */ + if ( URL_s && net_URL_sList ) { + LIBNET_LOCK(); + XP_ListRemoveObject( net_URL_sList, URL_s ); + LIBNET_UNLOCK(); + } +#endif + + PR_FREEIF(URL_s->address); + PR_FREEIF(URL_s->username); + PR_FREEIF(URL_s->password); + PR_FREEIF(URL_s->IPAddressString); + PR_FREEIF(URL_s->referer); + PR_FREEIF(URL_s->post_data); + PR_FREEIF(URL_s->post_headers); + PR_FREEIF(URL_s->content_type); + PR_FREEIF(URL_s->content_encoding); + PR_FREEIF(URL_s->x_mac_type); + PR_FREEIF(URL_s->x_mac_creator); + PR_FREEIF(URL_s->charset); + PR_FREEIF(URL_s->boundary); + PR_FREEIF(URL_s->redirecting_url); + PR_FREEIF(URL_s->authenticate); + PR_FREEIF(URL_s->protection_template); + PR_FREEIF(URL_s->http_headers); + PR_FREEIF(URL_s->cache_file); + PR_FREEIF(URL_s->window_target); + PR_FREEIF(URL_s->window_chrome); + PR_FREEIF(URL_s->refresh_url); + PR_FREEIF(URL_s->wysiwyg_url); + PR_FREEIF(URL_s->etag); + PR_FREEIF(URL_s->origin_url); + PR_FREEIF(URL_s->error_msg); + + HG87376 + + /* Free all memory associated with header information */ + net_FreeURLAllHeaders(URL_s); + + if(URL_s->files_to_post) + { + /* free a null terminated array of filenames + */ + int i=0; + for(i=0; URL_s->files_to_post[i] != NULL; i++) + { + PR_FREEIF(URL_s->files_to_post[i]); /* free the filenames */ + } + PR_FREEIF(URL_s->files_to_post); /* free the array */ + } + + /* Like files_to_post. */ + if(URL_s->post_to) + { + /* free a null terminated array of filenames + */ + int i=0; + for(i=0; URL_s->post_to[i] != NULL; i++) + { + PR_FREEIF(URL_s->post_to[i]); /* free the URLs */ + } + PR_FREEIF(URL_s->post_to); /* free the array */ + } + + + /* free the array */ + PR_FREEIF(URL_s->add_crlf); + + PR_FREEIF(URL_s->page_services_url); + + if (URL_s->privacy_policy_url != (char*)(-1)) { + PR_FREEIF(URL_s->privacy_policy_url); + } else { + URL_s->privacy_policy_url = NULL; + } + +#ifdef TRUST_LABELS + /* delete the entries and the trust list, if the list was created then there + * are entries on it. */ + if ( URL_s->TrustList != NULL ) { + /* delete each trust list entry then delete the list */ + TrustLabel *ALabel; + XP_List *tempList = URL_s->TrustList; + while ( (ALabel = XP_ListRemoveEndObject( tempList )) != NULL ) { + TL_Destruct( ALabel ); + } + XP_ListDestroy( URL_s->TrustList ); + URL_s->TrustList = NULL; + } +#endif + + PR_Free(URL_s); +} + + diff --git a/mozilla/mailnews/mime/cthandlers/vcard/oldvcc.c b/mozilla/mailnews/mime/cthandlers/vcard/oldvcc.c new file mode 100644 index 00000000000..fd6abf3bb89 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/oldvcc.c @@ -0,0 +1,1617 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/*************************************************************************** +(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 + */ + +#ifndef lint +char yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90"; +#endif +/*#line 2 "vcc.y" */ + +/* debugging utilities */ +#ifdef DEBUG_mwatkins +#define DBG_(x) /* PR_LogPrint x */ +#else +#define DBG_(x) +#endif + +#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 "xp.h" +#include "vcc.h" + +#include "plstr.h" +#include "prmem.h" + +#ifndef PR_FALSE +#define PR_FALSE 0 +#endif +#ifndef PR_TRUE +#define PR_TRUE 1 +#endif + +/**** Types, Constants ****/ + +#define YYDEBUG 0 /* 1 to compile in some debugging code */ +#define MAXTOKEN 256 /* maximum token (line) length */ +#define YYSTACKSIZE 50 /* ~unref ?*/ +#define MAXLEVEL 10 /* max # of nested objects parseable */ + /* (includes outermost) */ + + +/**** Global Variables ****/ +int mime_lineNum, mime_numErrors; /* yyerror() can use these */ +static VObject* vObjList; +static VObject *curProp; +static VObject *curObj; +static VObject* ObjStack[MAXLEVEL]; +static int ObjStackTop; + + +/* A helpful utility for the rest of the app. */ +#ifdef XP_CPLUSPLUS +extern "C" { +#endif + + extern void yyerror(char *s); + extern const char** fieldedProp; + +#ifdef XP_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 YYMAXTOKEN 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 YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#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 == MAXLEVEL) + return PR_FALSE; + + ObjStack[++ObjStackTop] = curObj; + + if (curObj) { + newObj = addProp(curObj,prop); + curObj = newObj; + } + else + curObj = newVObject(prop); + + return PR_TRUE; + } + + +/******************************************************************************/ +/* This pops the recently built vCard off the stack and returns it. */ +static VObject* popVObject() + { + VObject *oldObj; + if (ObjStackTop < 0) { + yyerror("pop on empty Object Stack\n"); + return 0; + } + oldObj = curObj; + curObj = ObjStack[ObjStackTop--]; + + return oldObj; + } + + +static void enterValues(const char *value) + { + if (fieldedProp && *fieldedProp) { + if (value) { + addPropValue(curProp,*fieldedProp,value); + } + /* else this field is empty, advance to next field */ + fieldedProp++; + } + else { + if (value) { + setVObjectUStringZValue_(curProp,fakeUnicode(value,0)); + } + } + deleteStr(value); + } + +static void enterProps(const char *s) + { + curProp = addGroup(curObj,s); + deleteStr(s); + } + +static void enterAttr(const char *s1, const char *s2) + { + const char *p1, *p2; + 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); + deleteStr(s1); deleteStr(s2); + } + + +#define MAX_LEX_LOOKAHEAD_0 32 +#define MAX_LEX_LOOKAHEAD 64 +#define MAX_LEX_MODE_STACK_SIZE 10 +#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) + +struct LexBuf { + /* input */ + XP_File inputFile; + char *inputString; + unsigned long curPos; + unsigned long inputLen; + /* lookahead buffer */ + /* -- lookahead buffer is short instead of char so that EOF + / can be represented correctly. + */ + unsigned long len; + short buf[MAX_LEX_LOOKAHEAD]; + unsigned long getPtr; + /* context stack */ + unsigned long lexModeStackTop; + enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; + /* token buffer */ + unsigned long maxToken; + char *strs; + unsigned long strsLen; + } lexBuf; + +static void lexPushMode(enum LexMode mode) + { + if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) + yyerror("lexical context stack overflow"); + else { + lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; + } + } + +static void lexPopMode(int top) + { + /* special case of pop for ease of error recovery -- this + version will never underflow */ + if (top) + lexBuf.lexModeStackTop = 0; + else + if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; + } + +static int lexWithinMode(enum LexMode mode) { + unsigned long i; + for (i=0;i 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + /* don't skip EOF. */ + lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; + lexBuf.len--; + } + } + +static int lexLookahead() { + int c = (lexBuf.len)? + lexBuf.buf[lexBuf.getPtr]: + lexGeta(); + /* do the \r\n -> \n or \r -> \n translation here */ + if (c == '\r') { + int a = (lexBuf.len>1)? + lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: + lexGeta_(1); + if (a == '\n') { + lexSkipLookahead(); + } + lexBuf.buf[lexBuf.getPtr] = c = '\n'; + } + else if (c == '\n') { + int a = (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) % MAX_LEX_LOOKAHEAD; + lexBuf.len--; + } + return c; + } + +static void lexSkipLookaheadWord() { + if (lexBuf.strsLen <= lexBuf.len) { + lexBuf.len -= lexBuf.strsLen; + lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; + } + } + +static void lexClearToken() + { + lexBuf.strsLen = 0; + } + +static void lexAppendc(int c) + { + 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 ;:=",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 MAX_LEX_LOOKAHEAD. + */ + if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; + lexBuf.getPtr = putptr; + while (*s) { + lexBuf.buf[putptr] = *s++; + putptr = (putptr + 1) % MAX_LEX_LOOKAHEAD; + } + lexBuf.len += len; + } +#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 += MAX_LEX_LOOKAHEAD; + lexBuf.getPtr = putptr; + lexBuf.buf[putptr] = c; + lexBuf.len += 1; + } + +static char* lexLookaheadWord() { + /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 + / and thing bigger than that will stop the lookahead and return 0; + / leading white spaces are not recoverable. + */ + int c; + int len = 0; + int curgetptr = 0; + lexSkipWhite(); + lexClearToken(); + curgetptr = (int) lexBuf.getPtr; /* remember! */ + while (len < (MAX_LEX_LOOKAHEAD_0)) { + c = lexGetc(); + len++; + if (c == EOF || PL_strchr("\t\n ;:=", c)) { + lexAppendc(0); + /* restore lookahead buf. */ + lexBuf.len += len; + lexBuf.getPtr = curgetptr; + return lexStr(); + } + else + lexAppendc(c); + } + lexBuf.len += len; /* char that has been moved to lookahead buffer */ + lexBuf.getPtr = curgetptr; + return 0; + } + +#ifdef _SUPPORT_LINE_FOLDING +static void handleMoreRFC822LineBreak(int c) { + /* suport RFC 822 line break in cases like + * ADR: foo; + * morefoo; + * more foo; + */ + if (c == ';') { + int a; + lexSkipLookahead(); + /* skip white spaces */ + a = lexLookahead(); + while (a == ' ' || a == '\t') { + lexSkipLookahead(); + a = lexLookahead(); + } + if (a == '\n') { + lexSkipLookahead(); + a = lexLookahead(); + if (a == ' ' || a == '\t') { + /* continuation, throw away all the \n and spaces read so + * far + */ + lexSkipWhite(); + lexPushLookaheadc(';'); + } + else { + lexPushLookaheadc('\n'); + lexPushLookaheadc(';'); + } + } + else { + lexPushLookaheadc(';'); + } + } + } + +static char* lexGet1Value() { +/* int 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 + + +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(); + } + +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; + deleteStr(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, XP_File inputfile) + { + /* initialize lex mode stack */ + lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; + + /* iniatialize lex buffer. */ + lexBuf.inputString = (char*) inputstring; + lexBuf.inputLen = inputlen; + lexBuf.curPos = 0; + lexBuf.inputFile = inputfile; + + lexBuf.len = 0; + lexBuf.getPtr = 0; + + lexBuf.maxToken = MAXTOKEN; + lexBuf.strs = (char*)PR_Malloc(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_Malloc(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) { + XP_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(); + deleteStr(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",c)) { + ++mime_lineNum; + /* consume all line separator(s) adjacent to each other */ + c = lexLookahead(); + while (PL_strchr("\n",c)) { + lexSkipLookahead(); + c = lexLookahead(); + ++mime_lineNum; + } + DBG_(("db: LINESEP\n")); + return LINESEP; + } + else { + char *p = 0; + lexPushLookaheadc(c); + if (lexWithinMode(L_BASE64)) { + /* get each char and convert to bin on the fly... */ + p = lexGetDataFromBase64(); + yylval.str = p; + return STRING; + } + else if (lexWithinMode(L_QUOTED_PRINTABLE)) { + p = lexGetQuotedPrintable(); + } + else { +#ifdef _SUPPORT_LINE_FOLDING + p = lexGet1Value(); +#else + p = lexGetStrUntil(";\n"); +#endif + } + if (p) { + DBG_(("db: STRING: '%s'\n", p)); + yylval.str = p; + return STRING; + } + else return 0; + } + } + else { + /* normal mode */ + while (1) { + int c = lexGetc(); + switch(c) { + case ':': { + /* consume all line separator(s) adjacent to each other */ + /* ignoring linesep immediately after colon. */ + c = lexLookahead(); + while (PL_strchr("\n",c)) { + lexSkipLookahead(); + c = lexLookahead(); + ++mime_lineNum; + } + DBG_(("db: COLON\n")); + return COLON; + } + case ';': + DBG_(("db: SEMICOLON\n")); + return SEMICOLON; + case '=': + DBG_(("db: EQ\n")); + return EQ; + /* ignore 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(XP_File file) + { + VObject *result; + long startPos; + + initLex(0,(unsigned long)-1,file); + startPos = XP_FileTell(file); + if (!(result = Parse_MIMEHelper())) { + XP_FileSeek(file,startPos,SEEK_SET); + } + return result; + } + +VObject* Parse_MIME_FromFileName(char *fname) + { +#if !defined(MOZADDRSTANDALONE) + XP_File fp = XP_FileOpen(fname, xpVCardFile, XP_FILE_READ); + if (fp) { + VObject* o = Parse_MIME_FromFile(fp); + XP_FileClose(fp); + return o; + } + else { + char msg[80]; + sprintf(msg, "can't open file '%s' for reading\n", fname); + mime_error_(msg); + return 0; + } +#else + PR_ASSERT (PR_FALSE); + return 0; +#endif + } + +/******************************************************************************/ +#if 0 +static void YYDebug(const char *s) +{ +/* PR_LogPrint("%s\n", s); */ +} +#endif + +static MimeErrorHandler mimeErrorHandler; + +void registerMimeErrorHandler(MimeErrorHandler me) + { + mimeErrorHandler = me; + } + +void mime_error(char *s) + { + char msg[256]; + if (mimeErrorHandler) { + sprintf(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 <= YYMAXTOKEN) 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; +yynewerror: +#endif + 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 <= YYMAXTOKEN) 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 <= YYMAXTOKEN) 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); +} + + +/* end of source file vcc.c */ + diff --git a/mozilla/mailnews/mime/cthandlers/vcard/oldvobj.c b/mozilla/mailnews/mime/cthandlers/vcard/oldvobj.c new file mode 100644 index 00000000000..48b93d2e403 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/oldvobj.c @@ -0,0 +1,1590 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +/* + * src: vobject.c + * doc: vobject and APIs to construct vobject, APIs pretty print + * vobject, and convert a vobject into its textual representation. + */ + +#include "xp.h" + +#include "vobject.h" +#include "xp_mem.h" +#include "plstr.h" +#include "prmem.h" + +/* debugging utilities */ +#if DEBUG_mwatkins +#define DBG_(x) PR_LogPrint x +#else +#define DBG_(x) +#endif + +const char** fieldedProp; + +static VObject* newVObject_(const char *id); +static int vObjectValueType(VObject *o); +static void initVObjectIterator(VObjectIterator *i, VObject *o); + +/*---------------------------------------------------------------------- + The following functions involve with memory allocation: + newVObject + deleteVObject + dupStr + deleteStr + newStrItem + deleteStrItem + ----------------------------------------------------------------------*/ + +static PRBool needsQuotedPrintable (const char *s) +{ + const unsigned char *p = (const unsigned char *)s; + + if (PL_strstr (s, LINEBREAK)) + return PR_TRUE; + + while (*p) { + if (*p & 0x80) + return PR_TRUE; + else + return PR_FALSE; + p++; + } + + return PR_FALSE; +} + +VObject* newVObject_(const char *id) +{ + VObject *p = (VObject*)PR_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); + PR_FREEIF (p); +} + +char* dupStr(const char *s, unsigned int size) +{ + char *t; + if (size == 0) { + size = PL_strlen(s); + } + t = (char*)PR_Malloc(size+1); + if (t) { + XP_MEMCPY(t,s,size); + t[size] = 0; + return t; + } + else { + return (char*)0; + } +} + +void deleteStr(const char *p) +{ + if (p) PR_Free ((void*)p); +} + +static StrItem* newStrItem(const char *s, StrItem *next) +{ + StrItem *p = (StrItem*)PR_Malloc(sizeof(StrItem)); + p->next = next; + p->s = s; + p->refCnt = 1; + return p; +} + +static void deleteStrItem(StrItem *p) +{ + if (p) PR_Free ((void*)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; +} + +int vObjectValueType(VObject *o) +{ + return VALUE_TYPE(o); +} + + +/*---------------------------------------------------------------------- + The following functions can be used to build VObject. + ----------------------------------------------------------------------*/ + +VObject* addVObjectProp(VObject *o, VObject *p) +{ + /* circular link list pointed to tail */ + /* + o {next,id,prop,val} + V + pn {next,id,prop,val} + V + ... + p1 {next,id,prop,val} + V + pn + --> + o {next,id,prop,val} + V + pn {next,id,prop,val} + V + p {next,id,prop,val} + ... + p1 {next,id,prop,val} + V + pn + */ + + VObject *tail = o->prop; + if (tail) { + p->next = tail->next; + o->prop = tail->next = p; + } + else { + o->prop = p->next = p; + } + return p; +} + +VObject* addProp(VObject *o, const char *id) +{ + return addVObjectProp(o,newVObject(id)); +} + +VObject* addProp_(VObject *o, const char *id) +{ + return addVObjectProp(o,newVObject_(id)); +} + +void addList(VObject **o, VObject *p) +{ + p->next = 0; + if (*o == 0) { + *o = p; + } + else { + VObject *t = *o; + while (t->next) { + t = t->next; + } + t->next = p; + } +} + +VObject* nextVObjectInList(VObject *o) +{ + return o->next; +} + +VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size) +{ + VObject *sizeProp; + setVObjectAnyValue(prop, val); + sizeProp = addProp(prop,VCDataSizeProp); + setVObjectLongValue(sizeProp, size); + return prop; +} + +VObject* setValueWithSize(VObject *prop, void *val, unsigned int size) +{ + void *p = dupStr((const char *)val,size); + return setValueWithSize_(prop,p,p?size:0); +} + +void initPropIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->prop; + i->next = 0; +} + +void initVObjectIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->next; + i->next = 0; +} + +int moreIteration(VObjectIterator *i) +{ + return (i->start && (i->next==0 || i->next!=i->start)); +} + +VObject* nextVObject(VObjectIterator *i) +{ + if (i->start && i->next != i->start) { + if (i->next == 0) { + i->next = i->start->next; + return i->next; + } + else { + i->next = i->next->next; + return i->next; + } + } + else return (VObject*)0; +} + +VObject* isAPropertyOf(VObject *o, const char *id) +{ + VObjectIterator i; + initPropIterator(&i,o); + while (moreIteration(&i)) { + VObject *each = nextVObject(&i); + if (!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); + deleteStr(gs); + return p; + } + else + return addProp_(o,lookupProp(g)); +} + +VObject* addPropValue(VObject *o, const char *p, const char *v) +{ + VObject *prop; + prop = addProp(o,p); + 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 + ----------------------------------------------------------------------*/ + +/* extern void printVObject_(XP_File fp, VObject *o, int level); */ + +static void indent(XP_File fp, int level) +{ + int i; + for (i=0;iprop) { + /* 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 (p == strTbl[h]) { + strTbl[h] = t->next; + } + else { + p->next = t->next; + } + deleteStr(t->s); + deleteStrItem(t); + return; + } + } + p = t; + t = t->next; + } while (t); + } +} + +void cleanStrTbl() +{ + int i; + for (i=0; is); + p = t; + t = t->next; + deleteStrItem(p); + } while (t) {} + strTbl[i] = 0; + } +} + + +struct PreDefProp { + const char *name; + const char *alias; + const char** fields; + unsigned int flags; + }; + +/* flags in PreDefProp */ +#define PD_BEGIN 0x1 +#define PD_INTERNAL 0x2 + +static const char *adrFields[] = { + VCPostalBoxProp, + VCExtAddressProp, + VCStreetAddressProp, + VCCityProp, + VCRegionProp, + VCPostalCodeProp, + VCCountryNameProp, + 0 +}; + +static const char *nameFields[] = { + VCFamilyNameProp, + VCGivenNameProp, + VCAdditionalNamesProp, + VCNamePrefixesProp, + VCNameSuffixesProp, + NULL + }; + +static const char *orgFields[] = { + VCOrgNameProp, + VCOrgUnitProp, + VCOrgUnit2Prop, + VCOrgUnit3Prop, + VCOrgUnit4Prop, + NULL + }; + +static const char *AAlarmFields[] = { + VCRunTimeProp, + VCSnoozeTimeProp, + VCRepeatCountProp, + VCAudioContentProp, + 0 + }; + +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 = 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 { + XP_File fp; + char *s; + int len; + int limit; + int alloc:1; + int fail:1; + } OFile; */ + +#if 0 +static void appendsOFile(OFile *fp, const char *s) +{ + int slen; + if (fp->fail) return; + slen = PL_strlen(s); + if (fp->fp) { + XP_FileWrite(s,slen,fp->fp); + } + else { +stuff: + if (fp->len + slen < fp->limit) { + XP_MEMCPY(fp->s+fp->len,s,slen); + fp->len += slen; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; + 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) +{ + if (fp->fail) return; + if (fp->fp) { + XP_FileWrite(&c,1,fp->fp); + } + else { +stuff: + if (fp->len+1 < fp->limit) { + fp->s[fp->len] = c; + fp->len++; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + fp->s = (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; + } +} +#else +static void appendcOFile_(OFile *fp, char c) +{ + if (fp->fail) return; + if (fp->fp) { + XP_FileWrite(&c,1,fp->fp); + } + else { +stuff: + if (fp->len+1 < fp->limit) { + fp->s[fp->len] = c; + fp->len++; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + fp->s = 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 MAXQUADS 16 + + quad[4] = 0; + + while (cur < len) { + /* collect the triplet of bytes into 'trip' */ + trip = 0; + for (i = 0; i < 3; i++) { + b = (cur < len) ? *(s + cur) : 0; + cur++; + trip = trip << 8 | b; + } + /* fill in 'quad' with the appropriate four characters */ + for (i = 3; i >= 0; i--) { + b = (unsigned char)(trip & 0x3F); + trip = trip >> 6; + if ((3 - i) < (cur - len)) + quad[i] = '='; /* pad char */ + else if (b < 26) quad[i] = (char)b + 'A'; + else if (b < 52) quad[i] = (char)(b - 26) + 'a'; + else if (b < 62) quad[i] = (char)(b - 52) + '0'; + else if (b == 62) quad[i] = '+'; + else quad[i] = '/'; + } + /* now output 'quad' with appropriate whitespace and line ending */ + appendsOFile(fp, (numQuads == 0 ? " " : "")); + appendsOFile(fp, quad); + appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); + numQuads = (numQuads + 1) % MAXQUADS; + } + appendcOFile(fp,'\n'); + + return 1; +} + +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 == CR || *p == 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 == CR && *(p+1) == 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; + } + + PR_ASSERT (current_column <= 76); /* 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++; + } + } +} + + +/* extern void writeVObject_(OFile *fp, VObject *o); */ + +static void writeValue(OFile *fp, VObject *o, unsigned long size) +{ + if (o == 0) return; + switch (VALUE_TYPE(o)) { + case VCVT_USTRINGZ: { + char *s = fakeCString(USTRINGZ_VALUE_OF(o)); + writeQPString(fp, s); + deleteStr(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 *t = isAPropertyOf(o,*fields); + i++; + if (t) 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(XP_File fp, VObject *o) +{ + OFile ofp; + initOFile(&ofp,fp); + writeVObject_(&ofp,o); +} + +void writeVObjectToFile(char *fname, VObject *o) +{ +#if !defined(MOZADDRSTANDALONE) + XP_File fp = XP_FileOpen(fname,xpVCardFile,XP_FILE_WRITE); + if (fp) { + writeVObject(fp,o); + XP_FileClose(fp); + } +#else + PR_ASSERT (PR_FALSE); +#endif +} + +void writeVObjectsToFile(char *fname, VObject *list) +{ +#if !defined(MOZADDRSTANDALONE) + XP_File fp = XP_FileOpen(fname,xpVCardFile,XP_FILE_WRITE); + if (fp) { + while (list) { + writeVObject(fp,list); + list = nextVObjectInList(list); + } + XP_FileClose(fp); + } +#else + PR_ASSERT (PR_FALSE); +#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; +} + +char* writeMemVObjects(char *s, int *len, VObject *list) +{ + OFile ofp; + initMemOFile(&ofp,s,len?*len:0); + while (list) { + writeVObject_(&ofp,list); + list = nextVObjectInList(list); + } + if (len) *len = ofp.len; + appendcOFile(&ofp,0); + return ofp.s; +} + +/*---------------------------------------------------------------------- + APIs to do fake Unicode stuff. + ----------------------------------------------------------------------*/ +vwchar_t* fakeUnicode(const char *ps, int *bytes) +{ + vwchar_t *r, *pw; + int len = PL_strlen(ps)+1; + + pw = r = (vwchar_t*)PR_Malloc(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_Malloc(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; +} + + +/* end of source file vobject.c */ diff --git a/mozilla/mailnews/mime/cthandlers/vcard/oldxp.c b/mozilla/mailnews/mime/cthandlers/vcard/oldxp.c new file mode 100644 index 00000000000..a2ba7568111 --- /dev/null +++ b/mozilla/mailnews/mime/cthandlers/vcard/oldxp.c @@ -0,0 +1,254 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +/* + * i18n.c - I18N depencencies + */ + +#include "xp.h" +#include "prmem.h" +#include "plstr.h" + +PUBLIC void * +FE_SetTimeout(TimeoutCallbackFunction func, void * closure, uint32 msecs) +{ + return NULL; +} + +/* RICHIE - THIS HACK MUST GO!!! - INCLUDING FILE TO TRY TO KEEP DIRECTORY CLEAN */ +#ifdef XP_UNIX +#define PUBLIC +#else +#include "..\..\..\lib\xp\xp_time.c" +#endif + + +char *XP_AppendStr(char *in, const char *append) +{ + int alen, inlen; + + alen = PL_strlen(append); + if (in) { + inlen = PL_strlen(in); + in = (char*) PR_Realloc(in,inlen+alen+1); + if (in) { + memcpy(in+inlen, append, alen+1); + } + } else { + in = (char*) PR_Malloc(alen+1); + if (in) { + memcpy(in, append, alen+1); + } + } + return in; +} + +#define MOZ_FUNCTION_STUB + +char * +WH_TempName(XP_FileType type, const char * prefix) +{ + MOZ_FUNCTION_STUB; + return NULL; +} + +/* +// The caller is responsible for PR_Free()ing the return string +*/ +PUBLIC char * +WH_FileName (const char *NetName, XP_FileType type) +{ + MOZ_FUNCTION_STUB; + + if (type == xpHTTPCookie) { +#ifdef XP_PC + return PL_strdup("cookies.txt"); +#else + return PL_strdup("cookies"); +#endif + } else if (type == xpCacheFAT) { +;// sprintf(newName, "%s\\fat.db", (const char *)theApp.m_pCacheDir); + + } else if ((type == xpURL) || (type == xpFileToPost)) { + /* + * This is the body of XP_NetToDosFileName(...) which is implemented + * for Windows only in fegui.cpp + */ + PRBool bChopSlash = PR_FALSE; + char *p, *newName; + + if(!NetName) + return NULL; + + // If the name is only '/' or begins '//' keep the + // whole name else strip the leading '/' + + if(NetName[0] == '/') + bChopSlash = PR_TRUE; + + // save just / as a path + if(NetName[0] == '/' && NetName[1] == '\0') + bChopSlash = PR_FALSE; + + // spanky Win9X path name + if(NetName[0] == '/' && NetName[1] == '/') + bChopSlash = PR_FALSE; + + if(bChopSlash) + newName = PL_strdup(&(NetName[1])); + else + newName = PL_strdup(NetName); + + if(!newName) + return NULL; + + if( newName[1] == '|' ) + newName[1] = ':'; + + for(p = newName; *p; p++){ + if( *p == '/' ) + *p = '\\'; + } + return(newName); + } + + return NULL; +} + +PUBLIC XP_File +XP_FileOpen(const char * name, XP_FileType type, const XP_FilePerm perm) +{ + MOZ_FUNCTION_STUB; + switch (type) { + case xpURL: + case xpFileToPost: + case xpHTTPCookie: + { + XP_File fp; + char* newName = WH_FileName(name, type); + + if (!newName) return NULL; + + fp = fopen(newName, (char *) perm); + PR_Free(newName); + return fp; + + } + default: + break; + } + + return NULL; +} + +PUBLIC XP_Dir +XP_OpenDir(const char * name, XP_FileType type) +{ + MOZ_FUNCTION_STUB; + return NULL; +} + +PUBLIC void +XP_CloseDir(XP_Dir dir) +{ + MOZ_FUNCTION_STUB; +} + +PUBLIC XP_DirEntryStruct * +XP_ReadDir(XP_Dir dir) +{ + MOZ_FUNCTION_STUB; + return NULL; +} + +PUBLIC int +XP_FileRemove(const char * name, XP_FileType type) +{ + if (PR_Delete(name) == PR_SUCCESS) + return 0; + return -1; +} + +/* If you want to trace netlib, set this to 1, or use CTRL-ALT-T + * stroke (preferred method) to toggle it on and off */ +int MKLib_trace_flag=0; + + +/* Used by NET_NTrace() */ +PRIVATE void net_Trace(char *msg) { +#if defined(WIN32) && defined(DEBUG) + OutputDebugString(msg); + OutputDebugString("\n"); +#else + PR_LogPrint(msg); +#endif +} + +/* #define'd in mktrace.h to TRACEMSG */ +void _MK_TraceMsg(char *fmt, ...) { + va_list ap; + char buf[512]; + + va_start(ap, fmt); + PR_vsnprintf(buf, sizeof(buf), fmt, ap); + + net_Trace(buf); +} + +PUBLIC int +XP_Stat(const char * name, XP_StatStruct * info, XP_FileType type) +{ + int result = -1; + MOZ_FUNCTION_STUB; + + switch (type) { + case xpURL: + case xpFileToPost: { + char *newName = WH_FileName(name, type); + + if (!newName) return -1; + result = _stat( newName, info ); + PR_Free(newName); + break; + } + default: + break; + } + return result; +} + +char *XP_STRNCPY_SAFE (char *dest, const char *src, size_t destLength) +{ + char *result = strncpy (dest, src, --destLength); + dest[destLength] = '\0'; + return result; +} + +int +RNG_GenerateGlobalRandomBytes(void *dest, size_t len) +{ + size_t i; + char *ptr = (char *) dest; + + for (i=0; i