static void writeValue(OFile *fp, VObject *o, unsigned long size, bool nosemi) { if (o == 0) return; switch (VALUE_TYPE(o)) { case VCVT_STRINGZ: { writeEncString(fp, STRINGZ_VALUE_OF(o), nosemi); 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 writeQPString(OFile *fp, const char *s) { char buf[4]; int count=0; const char *p = s; while (*p) { /* break up lines biggger than 75 chars */ if(count >=74){ count=0; appendsOFile(fp,"=\n"); } /* escape any non ASCII characters and '=' as per rfc1521 */ if (*p<= 0x1f || *p >=0x7f || *p == '=' ) { snprintf(buf,sizeof(buf),"=%02X",(unsigned char)*p); appendsOFile(fp,buf); count+=3; } else { appendcOFile(fp,*p); count++; } p++; } }
static void appendsOFileEncCs(OFile *fp) { if ( vobj_enc_s ) { appendsOFile(fp, ";" VCEncodingProp "="); appendsOFile(fp, vobj_enc_s); } appendsOFile(fp, ";" VCCharSetProp "="); appendsOFile(fp, vobj_cs); }
static void writeEncString(OFile *fp, const char *s, bool nosemi) { /* only A-Z, 0-9 and "'" (ASCII code 39) "(" (ASCII code 40) ")" (ASCII code 41) "+" (ASCII code 43) "," (ASCII code 44) "-" (ASCII code 45) "/" (ASCII code 47) "?" (ASCII code 63) should remain un-encoded. '=' needs to be encoded as it is the escape character. ';' needs to be as it is a field separator. */ const char *p = s; switch ( vobj_enc ) { case EightBit: while (*p) { if ( *p == '\n' || nosemi && ( *p == '\\' || *p == ';' ) ) appendcOFile(fp, '\\'); appendcOFile(fp, *p); p++; } break; case QuotedPrintable: while (*p) { const char *rep = qpReplaceChar(*p); if (rep) appendsOFile(fp, rep); else if ( *p == ';' && nosemi ) appendsOFile(fp, "=3B"); else if ( *p == ' ' ) { if ( !p[1] || p[1] == '\n' ) // RFC 1521 appendsOFile(fp, "=20"); else appendcOFile(fp, *p); } else appendcOFile(fp, *p); p++; } break; case Base64: writeBase64(fp, (unsigned char*)p, strlen(p)); break; } }
/* this function really sucks. Too basic. */ static void writeQPString(OFile *fp, const char *s, int qp) { const char *p = s; while (*p) { if (*p == '\n') { if (p[1]) appendsOFile(fp,"=0A="); } if (*p == '=' && qp) appendsOFile(fp,"=3D"); else appendcOFile(fp,*p); p++; } }
static void writeProp(OFile *fp, VObject *o) { int isQuoted=0; if (NAME_OF(o)) { const struct PreDefProp *pi; VObjectIterator t; const char **fields_ = 0; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { writeVObject_(fp,o); return; } if (isAPropertyOf(o,VCGroupingProp)) writeGroup(fp,o); else appendsOFile(fp,NAME_OF(o)); if (pi) fields_ = pi->fields; initPropIterator(&t,o); while (moreIteration(&t)) { const char *s; VObject *eachProp = nextVObject(&t); s = NAME_OF(eachProp); if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) writeAttrValue(fp,eachProp); if (strcasecmp(VCQPProp,s)==0 || strcasecmp(VCQuotedPrintableProp,s)==0) isQuoted=1; } if (fields_) { int i = 0, n = 0; const char** fields = fields_; /* output prop as fields */ appendcOFile(fp,':'); while (*fields) { VObject *tl = isAPropertyOf(o,*fields); i++; if (tl) n = i; fields++; } fields = fields_; for (i=0;i<n;i++) { writeValue(fp,isAPropertyOf(o,*fields),0,isQuoted); fields++; if (i<(n-1)) appendcOFile(fp,';'); } } } if (VALUE_TYPE(o)) { unsigned long size = 0; VObject *p = isAPropertyOf(o,VCDataSizeProp); if (p) size = LONG_VALUE_OF(p); appendcOFile(fp,':'); writeValue(fp,o,size,isQuoted); } appendcOFile(fp,'\n'); }
static void writeValue(OFile *fp, VObject *o, unsigned long size) { if (o == 0) return; switch (VALUE_TYPE(o)) { case VCVT_USTRINGZ: { char *s = fakeCString(USTRINGZ_VALUE_OF(o)); if (isAPropertyOf(o, VCQuotedPrintableProp)) writeQPString(fp, s, 1); else writeQPString(fp, s, 0); deleteStr(s); break; } case VCVT_STRINGZ: { if (isAPropertyOf(o, VCQuotedPrintableProp)) writeQPString(fp, STRINGZ_VALUE_OF(o), 1); else writeQPString(fp, STRINGZ_VALUE_OF(o), 0); break; } case VCVT_UINT: { char buf[16]; snprintf(buf,sizeof(buf),"%u", INTEGER_VALUE_OF(o)); appendsOFile(fp,buf); break; } case VCVT_ULONG: { char buf[16]; snprintf(buf,sizeof(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 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 writeGroup(OFile *fp, VObject *o) { char buf1[256]; char buf2[256]; strncpy(buf1,NAME_OF(o), 255); while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { strncpy(buf2,STRINGZ_VALUE_OF(o),255); strcat(buf2,"."); strncat(buf2,buf1,254-strlen(STRINGZ_VALUE_OF(o))); strcpy(buf1,buf2); } appendsOFile(fp,buf1); }
static void writeVObject_(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { VObjectIterator t; const char *begin = NAME_OF(o); appendsOFile(fp,"BEGIN:"); appendsOFile(fp,begin); appendcOFile(fp,'\n'); initPropIterator(&t,o); while (moreIteration(&t)) { VObject *eachProp = nextVObject(&t); writeProp(fp, eachProp); } appendsOFile(fp,"END:"); appendsOFile(fp,begin); appendsOFile(fp,"\n\n"); } } }
static void writeGroup(OFile *fp, VObject *o) { char buf1[256]; char buf2[256]; strcpy(buf1,NAME_OF(o)); while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2)); buf2[sizeof(buf2)-1] = '\0'; strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1); strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1); strcpy(buf1,buf2); } appendsOFile(fp,buf1); }
static void writeAttrValue(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; appendcOFile(fp,';'); appendsOFile(fp,NAME_OF(o)); } else appendcOFile(fp,';'); if (VALUE_TYPE(o)) { appendcOFile(fp,'='); writeValue(fp,o,0); } }
static void writeProp(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; VObjectIterator t; const char **fields_ = 0; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { writeVObject_(fp,o); return; } if (isAPropertyOf(o,VCGroupingProp)) writeGroup(fp,o); else appendsOFile(fp,NAME_OF(o)); if (pi) fields_ = pi->fields; initPropIterator(&t,o); while (moreIteration(&t)) { const char *s; VObject *eachProp = nextVObject(&t); s = NAME_OF(eachProp); if (qstricmp(VCGroupingProp,s) && !inList(fields_,s)) writeAttrValue(fp,eachProp); } if (fields_) { int i = 0, n = 0; const char** fields = fields_; /* output prop as fields */ bool printable = TRUE; while (*fields && printable) { VObject *t = isAPropertyOf(o,*fields); if (includesUnprintable(t,TRUE)) printable = FALSE; fields++; } fields = fields_; if (!printable) appendsOFileEncCs(fp); appendcOFile(fp,':'); while (*fields) { VObject *t = isAPropertyOf(o,*fields); i++; if (t) n = i; fields++; } fields = fields_; for (i=0;i<n;i++) { writeValue(fp,isAPropertyOf(o,*fields),0,TRUE); fields++; if (i<(n-1)) appendcOFile(fp,';'); } } } if (VALUE_TYPE(o)) { if ( includesUnprintable(o,FALSE) ) appendsOFileEncCs(fp); unsigned long size = 0; VObject *p = isAPropertyOf(o,VCDataSizeProp); if (p) size = LONG_VALUE_OF(p); appendcOFile(fp,':'); writeValue(fp,o,size,FALSE); } appendcOFile(fp,'\n'); }
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 == '\r' || *p == '\n') { /* 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 == '\r' && *(p+1) == '\n') p++; white = PR_FALSE; current_column = 0; } else { if ((*p >= 33 && *p <= 60) || /* safe printing chars */ (*p >= 62 && *p <= 126) || (mb_p && (*p == 61 || *p == 127 || *p == 0x1B))) { appendcOFile(fp,*p); current_column++; white = PR_FALSE; contWhite = PR_FALSE; } else if (*p == ' ' || *p == '\t') /* whitespace */ { if (contWhite) { appendcOFile(fp,'='); appendcOFile(fp,hexdigits[*p >> 4]); appendcOFile(fp,hexdigits[*p & 0xF]); current_column += 3; contWhite = PR_FALSE; } else { appendcOFile(fp,*p); current_column++; } white = PR_TRUE; } else /* print as =FF */ { appendcOFile(fp,'='); appendcOFile(fp,hexdigits[*p >> 4]); appendcOFile(fp,hexdigits[*p & 0xF]); current_column += 3; white = PR_FALSE; contWhite = PR_FALSE; } NS_ASSERTION(current_column <= 76, "1.10 <*****@*****.**> 06 Jan 2000 08:01"); /* Hard limit required by spec */ if (current_column >= 73 || ((*(p+1) == ' ') && (current_column + 3 >= 73))) /* soft line break: "=\r\n" */ { appendcOFile(fp,'='); appendcOFile(fp,'\n'); appendcOFile(fp,'\t'); current_column = 0; if (white) contWhite = PR_TRUE; else contWhite = PR_FALSE; white = PR_FALSE; } } p++; } /* while */
static void writeString(OFile *fp, const char *s) { appendsOFile(fp,s); }