-rw-r--r-- | library/backend/vcc.y | 22 | ||||
-rw-r--r-- | library/backend/vcc_yacc.cpp | 127 | ||||
-rw-r--r-- | library/backend/vobject.cpp | 163 | ||||
-rw-r--r-- | library/backend/vobject_p.h | 29 |
4 files changed, 189 insertions, 152 deletions
diff --git a/library/backend/vcc.y b/library/backend/vcc.y index 6781312..94a8fea 100644 --- a/library/backend/vcc.y +++ b/library/backend/vcc.y @@ -119,13 +119,13 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. #include <stdlib.h>
#include <ctype.h>
//#ifdef PALMTOPCENTER
//#include <qpe/vobject_p.h>
//#else
-#include <qtopia/private/vobject_p.h> +#include "vobject_p.h"
//#endif
/**** Types, Constants ****/
#define YYDEBUG 0 /* 1 to compile in some debugging code */
#define MAXTOKEN 256 /* maximum token (line) length */
@@ -720,22 +720,28 @@ static void handleMoreRFC822LineBreak(int c) { static char* lexGet1Value() {
int c;
lexSkipWhite();
c = lexLookahead();
lexClearToken();
- while (c != EOF && c != ';') {
+ while (c != EOF && (c != ';' || !fieldedProp)) {
if (c == '\\' ) {
int a;
lexSkipLookahead();
a = lexLookahead();
- if ( a != ';' ) {
- lexAppendc('\\');
- } else {
+ if ( a == ';' ) {
lexAppendc( ';' );
lexSkipLookahead();
+ } else if ( a == '\n' ) {
+ lexAppendc( '\n' );
+ lexSkipLookahead();
+ } else if ( a == '\\' ) {
+ lexAppendc( '\\' );
+ lexSkipLookahead();
+ } else {
+ lexAppendc('\\');
}
} else if (c == '\n') {
int a;
lexSkipLookahead();
a = lexLookahead();
if (a == ' ' || a == '\t') {
@@ -958,12 +964,13 @@ static char* lexGetQuotedPrintable() } else if (next >= 'A' && next <= 'F') {
cur = next - 'A' + 10;
} else {
// we have been sent buggy stuff. doesn't matter
// what we do so long as we keep going.
// should probably spit an error here
+ lexSkipLookahead();
c = lexLookahead();
continue;
}
lexSkipLookahead(); // skip A-Z0-9
next = lexLookahead();
@@ -975,12 +982,13 @@ static char* lexGetQuotedPrintable() } else if (next >= 'A' && next <= 'F') {
cur += next - 'A' + 10;
} else {
// we have been sent buggy stuff. doesn't matter
// what we do so long as we keep going.
// should probably spit an error here
+ lexSkipLookahead();
c = lexLookahead();
continue;
}
// got a valid escaped =. append it.
lexSkipLookahead(); // skip second 0-9A-F
@@ -997,13 +1005,13 @@ static char* lexGetQuotedPrintable() static int yylex() {
int lexmode = LEXMODE();
if (lexmode == L_VALUES) {
int c = lexGetc();
- if (c == ';') {
+ if (c == ';' && fieldedProp) {
DBG_(("db: SEMICOLON\n"));
lexPushLookaheadc(c);
handleMoreRFC822LineBreak(c);
lexSkipLookahead();
return SEMICOLON;
}
@@ -1051,18 +1059,20 @@ static int yylex() { while (1) {
int c = lexGetc();
switch(c) {
case ':': {
/* consume all line separator(s) adjacent to each other */
/* ignoring linesep immediately after colon. */
+ /* I don't see this in the spec, and it breaks null values -- WA
c = lexLookahead();
while (strchr("\n",c)) {
lexSkipLookahead();
c = lexLookahead();
++mime_lineNum;
}
+ */
DBG_(("db: COLON\n"));
return COLON;
}
case ';':
DBG_(("db: SEMICOLON\n"));
return SEMICOLON;
diff --git a/library/backend/vcc_yacc.cpp b/library/backend/vcc_yacc.cpp index b2b0c14..5649522 100644 --- a/library/backend/vcc_yacc.cpp +++ b/library/backend/vcc_yacc.cpp @@ -155,13 +155,13 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. #include <stdlib.h>
#include <ctype.h>
/*#ifdef PALMTOPCENTER
*/ /*#include <qpe/vobject_p.h>
*/ /*#else
*/ -#include <qtopia/private/vobject_p.h> +#include "vobject_p.h"
/*#endif
*/ /**** Types, Constants ****/
#define YYDEBUG 0 /* 1 to compile in some debugging code */
#define MAXTOKEN 256 /* maximum token (line) length */
@@ -740,22 +740,28 @@ static void handleMoreRFC822LineBreak(int c) { static char* lexGet1Value() {
int c;
lexSkipWhite();
c = lexLookahead();
lexClearToken();
- while (c != EOF && c != ';') {
+ while (c != EOF && (c != ';' || !fieldedProp)) {
if (c == '\\' ) {
int a;
lexSkipLookahead();
a = lexLookahead();
- if ( a != ';' ) {
- lexAppendc('\\');
- } else {
+ if ( a == ';' ) {
lexAppendc( ';' );
lexSkipLookahead();
+ } else if ( a == '\n' ) {
+ lexAppendc( '\n' );
+ lexSkipLookahead();
+ } else if ( a == '\\' ) {
+ lexAppendc( '\\' );
+ lexSkipLookahead();
+ } else {
+ lexAppendc('\\');
}
} else if (c == '\n') {
int a;
lexSkipLookahead();
a = lexLookahead();
if (a == ' ' || a == '\t') {
@@ -948,73 +954,84 @@ static int match_begin_end_name(int end) { }
return 0;
}
static char* lexGetQuotedPrintable()
{
- int cur;
-
+ int c;
+ lexSkipWhite();
+ c = lexLookahead();
lexClearToken();
- do {
- cur = lexGetc();
- switch (cur) {
- case '=': {
- int c = 0;
- int next[2];
- int i;
- for (i = 0; i < 2; i++) {
- next[i] = lexGetc();
- if (next[i] >= '0' && next[i] <= '9')
- c = c * 16 + next[i] - '0';
- else if (next[i] >= 'A' && next[i] <= 'F')
- c = c * 16 + next[i] - 'A' + 10;
- else
+
+ while (c != EOF && c != ';') {
+ if (c == '\n') {
+ // break, leave '\n' on remaining chars.
break;
+ } else if (c == '=') {
+ int cur = 0;
+ int next;
+
+ lexSkipLookahead(); // skip '='
+ next = lexLookahead();
+
+ if (next == '\n') {
+ // skip and only skip the \n
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum; // aid in error reporting
+ continue;
+ } else if (next >= '0' && next <= '9') {
+ cur = next - '0';
+ } else if (next >= 'A' && next <= 'F') {
+ cur = next - 'A' + 10;
+ } else {
+ // we have been sent buggy stuff. doesn't matter
+ // what we do so long as we keep going.
+ // should probably spit an error here
+ lexSkipLookahead();
+ c = lexLookahead();
+ continue;
}
- if (i == 0) {
- /* single '=' follow by LINESEP is continuation sign? */
- if (next[0] == '\n') {
- ++mime_lineNum;
- }
- else {
- lexPushLookaheadc('=');
- goto EndString;
- }
+
+ lexSkipLookahead(); // skip A-Z0-9
+ next = lexLookahead();
+
+ cur = cur * 16;
+ // this time really just expecting 0-9A-F
+ if (next >= '0' && next <= '9') {
+ cur += next - '0';
+ } else if (next >= 'A' && next <= 'F') {
+ cur += next - 'A' + 10;
+ } else {
+ // we have been sent buggy stuff. doesn't matter
+ // what we do so long as we keep going.
+ // should probably spit an error here
+ lexSkipLookahead();
+ c = lexLookahead();
+ continue;
}
- else if (i == 1) {
- lexPushLookaheadc(next[1]);
- lexPushLookaheadc(next[0]);
- lexAppendc('=');
+
+ // got a valid escaped =. append it.
+ lexSkipLookahead(); // skip second 0-9A-F
+ lexAppendc(cur);
} else {
- lexAppendc(c);
+ lexSkipLookahead(); // skip whatever we just read.
+ lexAppendc(c); // and append it.
}
- break;
- } /* '=' */
- case '\n': {
- lexPushLookaheadc('\n');
- goto EndString;
+ c = lexLookahead();
}
- case (int)EOF:
- break;
- default:
- lexAppendc(cur);
- break;
- } /* switch */
- } while (cur != (int)EOF);
-
-EndString:
lexAppendc(0);
- return lexStr();
- } /* LexQuotedPrintable */
+ return c==EOF?0:lexStr();
+}
static int yylex() {
int lexmode = LEXMODE();
if (lexmode == L_VALUES) {
int c = lexGetc();
- if (c == ';') {
+ if (c == ';' && fieldedProp) {
DBG_(("db: SEMICOLON\n"));
lexPushLookaheadc(c);
handleMoreRFC822LineBreak(c);
lexSkipLookahead();
return SEMICOLON;
}
@@ -1062,18 +1079,20 @@ static int yylex() { while (1) {
int c = lexGetc();
switch(c) {
case ':': {
/* consume all line separator(s) adjacent to each other */
/* ignoring linesep immediately after colon. */
+ /* I don't see this in the spec, and it breaks null values -- WA
c = lexLookahead();
while (strchr("\n",c)) {
lexSkipLookahead();
c = lexLookahead();
++mime_lineNum;
}
+ */
DBG_(("db: COLON\n"));
return COLON;
}
case ';':
DBG_(("db: SEMICOLON\n"));
return SEMICOLON;
@@ -1214,13 +1233,13 @@ void mime_error_(char *s) {
if (mimeErrorHandler) {
mimeErrorHandler(s);
}
}
-#line 1221 "y.tab.c" +#line 1240 "y.tab.c" #define YYABORT goto yyabort #define YYREJECT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int #if defined(__STDC__) @@ -1514,13 +1533,13 @@ case 45: #line 376 "backend/vcc.y" {
lexPopMode(0);
popVObject();
} break; -#line 1521 "y.tab.c" +#line 1540 "y.tab.c" } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) diff --git a/library/backend/vobject.cpp b/library/backend/vobject.cpp index 2c5b577..b6d17dc 100644 --- a/library/backend/vobject.cpp +++ b/library/backend/vobject.cpp @@ -43,14 +43,15 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. */ #ifndef MWERKS #include <malloc.h> #endif -#include <qtopia/private/vobject_p.h> -#include <qtopia/private/qfiledirect_p.h> +#include <qtopia/config.h> +#include "vobject_p.h" +#include "qfiledirect_p.h" #include <string.h> #include <stdio.h> #include <fcntl.h> //#include <io.h> @@ -59,12 +60,16 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. #define STRINGZ_VALUE_OF(o) o->val.strs #define INTEGER_VALUE_OF(o) o->val.i #define LONG_VALUE_OF(o) o->val.l #define ANY_VALUE_OF(o) o->val.any #define VOBJECT_VALUE_OF(o) o->val.vobj +static char vobj_cs[10]; +static enum { EightBit, QuotedPrintable, Base64 } vobj_enc=EightBit; +static const char *vobj_enc_s=0; + typedef union ValueItem { const char *strs; unsigned int i; unsigned long l; void *any; VObject *vobj; @@ -83,13 +88,13 @@ typedef struct StrItem StrItem; struct StrItem { StrItem *next; const char *s; unsigned int refCnt; }; -const char** fieldedProp; +DLLEXPORT(const char**) fieldedProp; /*---------------------------------------------------------------------- The following functions involve with memory allocation: newVObject @@ -950,12 +955,23 @@ static void appendsOFile(OFile *fp, const char *s) appendcOFile(fp,s[i]); } } #endif +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 initOFile(OFile *fp, FILE *ofp) { fp->fp = ofp; fp->s = 0; fp->len = 0; fp->limit = 0; @@ -1002,47 +1018,26 @@ static int writeBase64(OFile *fp, unsigned char *s, long len) } appendcOFile(fp,'\n'); return 1; } -static const char *replaceChar(unsigned char c) +static const char *qpReplaceChar(unsigned char c) { if (c == '\n') { return "=0A=\n"; } else if ( - (c >= 'A' && c <= 'Z') - || - (c >= 'a' && c <= 'z') + // RFC 1521 + (c >= 32 && c <= 60) // Note: " " not allowed at EOL || - (c >= '0' && c <= '9') - || - (c >= '\'' && c <= ')') - || - (c >= '+' && c <= '-') - || - (c == '/') - || - (c == '?') - || - (c == ' ')) + (c >= 62 && c <= 126) + ) { return 0; } -#warning "Bug-Workaround must be fixed !" - // IF THIS FUNCTION RETURNES TRUE, THE DATA IS EXPORTED - // AS QUOTED PRINTABLE. - // BUT THE PARSER IS UNABLE TO IMPORT THIS, THEREFORE - // I DECIDED TO DISABLE IT UNTIL TROLLTECH FIXES THIS BUG - // SEE ALSO includesUnprintable(VObject *o) - // (se) - - return 0; - -#if 0 static char trans[4]; trans[0] = '='; trans[3] = '\0'; int rem = c % 16; int div = c / 16; @@ -1054,16 +1049,15 @@ static const char *replaceChar(unsigned char c) if (rem < 10) trans[2] = '0' + rem; else trans[2] = 'A' + (rem - 10); return trans; -#endif } -static void writeQPString(OFile *fp, const char *s) +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) @@ -1076,61 +1070,70 @@ static void writeQPString(OFile *fp, const char *s) 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 = replaceChar(*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; + } } static bool includesUnprintable(VObject *o) { - -#if 0 - - // IF THIS FUNCTION RETURNES TRUE, THE DATA IS EXPORTED - // AS QUOTED PRINTABLE. - // BUT THE PARSER IS UNABLE TO IMPORT THIS, THEREFORE - // I DECIDED TO DISABLE IT UNTIL TROLLTECH FIXES THIS BUG - // SEE ALSO *replaceChar(unsigned char c) - // (se) - if (o) { if (VALUE_TYPE(o) == VCVT_STRINGZ) { const char *p = STRINGZ_VALUE_OF(o); if (p) { while (*p) { - if (replaceChar(*p)) + if (*p==' ' && (!p[1] || p[1]=='\n') // RFC 1521: spaces at ends need quoting + || qpReplaceChar(*p) ) return TRUE; p++; } } } } - -#endif -#warning "Bug-Workaround must be fixed !" - return FALSE; } static void writeVObject_(OFile *fp, VObject *o); -static void writeValue(OFile *fp, VObject *o, unsigned long size) +static void writeValue(OFile *fp, VObject *o, unsigned long size, bool nosemi) { if (o == 0) return; switch (VALUE_TYPE(o)) { case VCVT_STRINGZ: { - writeQPString(fp, STRINGZ_VALUE_OF(o)); + writeEncString(fp, STRINGZ_VALUE_OF(o), nosemi); break; } case VCVT_UINT: { char buf[16]; sprintf(buf,"%u", INTEGER_VALUE_OF(o)); appendsOFile(fp,buf); @@ -1157,24 +1160,22 @@ static void writeValue(OFile *fp, VObject *o, unsigned long size) 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; - if ( includesUnprintable(o) ) { - appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp); - appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8"); - } + if ( includesUnprintable(o) ) + appendsOFileEncCs(fp); appendcOFile(fp,';'); appendsOFile(fp,NAME_OF(o)); - } - else + } else { appendcOFile(fp,';'); + } if (VALUE_TYPE(o)) { appendcOFile(fp,'='); - writeValue(fp,o,0); + writeValue(fp,o,0,TRUE); } } static void writeGroup(OFile *fp, VObject *o) { char buf1[256]; @@ -1232,43 +1233,39 @@ static void writeProp(OFile *fp, VObject *o) VObject *t = isAPropertyOf(o,*fields); if (includesUnprintable(t)) printable = FALSE; fields++; } fields = fields_; - if (!printable) { - appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp); - appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8"); - } + 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); + writeValue(fp,isAPropertyOf(o,*fields),0,TRUE); fields++; if (i<(n-1)) appendcOFile(fp,';'); } } } if (VALUE_TYPE(o)) { - if ( includesUnprintable(o) ) { - appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp); - appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8"); - } + if ( includesUnprintable(o) ) + appendsOFileEncCs(fp); unsigned long size = 0; VObject *p = isAPropertyOf(o,VCDataSizeProp); if (p) size = LONG_VALUE_OF(p); appendcOFile(fp,':'); - writeValue(fp,o,size); + writeValue(fp,o,size,FALSE); } appendcOFile(fp,'\n'); } static void writeVObject_(OFile *fp, VObject *o) @@ -1292,14 +1289,41 @@ static void writeVObject_(OFile *fp, VObject *o) appendsOFile(fp,begin); appendsOFile(fp,"\n\n"); } } } +static void initVObjectEncoding() +{ + Config pimConfig( "Beam" ); + pimConfig.setGroup("Send"); + Config devcfg(pimConfig.readEntry("DeviceConfig"),Config::File); + QString enc = "QP"; + QString cs = "UTF-8"; + if ( devcfg.isValid() ) { + devcfg.setGroup("Send"); + enc = devcfg.readEntry("Encoding","QP"); + cs = devcfg.readEntry("CharSet","UTF-8"); + } + strncpy(vobj_cs,cs.latin1(),10); + if ( enc == "QP" ) { + vobj_enc = QuotedPrintable; + vobj_enc_s = VCQuotedPrintableProp; + } else if ( enc == "B64" ) { + vobj_enc = Base64; + vobj_enc_s = VCBase64Prop; + } else { + vobj_enc = EightBit; + vobj_enc_s = 0; + } +} + void writeVObject(FILE *fp, VObject *o) { + initVObjectEncoding(); + OFile ofp; // ##### //_setmode(_fileno(fp), _O_BINARY); initOFile(&ofp,fp); writeVObject_(&ofp,o); } @@ -1326,21 +1350,16 @@ DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list) while (list) { writeVObject(f.directHandle(),list); list = nextVObjectInList(list); } } -#ifndef __SHARP_COMP_ - -// This function is not available in the Sharp ROM for SL 5500 ! -// Therefore I have to move it into the header file.. (se) - DLLEXPORT(const char *) vObjectTypeInfo(VObject *o) { const char *type = vObjectName( o ); if ( strcmp( type, "TYPE" ) == 0 ) type = vObjectStringZValue( o ); return type; } -#endif + // end of source file vobject.c diff --git a/library/backend/vobject_p.h b/library/backend/vobject_p.h index bab22bb..f969898 100644 --- a/library/backend/vobject_p.h +++ b/library/backend/vobject_p.h @@ -96,15 +96,19 @@ For example: */ #define vCardMimeType "text/x-vCard" #define vCalendarMimeType "text/x-vCalendar" #undef DLLEXPORT + //#include <qtopia/qpeglobal.h> #include <qglobal.h> -#if defined(Q_WS_WIN) + +#if defined(QTOPIA_MAKEDLL) #define DLLEXPORT(t) __declspec(dllexport) t +#elif defined(QTOPIA_DLL) +#define DLLEXPORT(t) __declspec(dllimport) t #else #define DLLEXPORT(t) t #endif #ifndef FALSE #define FALSE 0 @@ -348,13 +352,13 @@ extern DLLEXPORT(int) vObjectValueType(VObject *o); /* if the VObject has value set by setVObjectLongValue. */ #define VCVT_RAW 4 /* if the VObject has value set by setVObjectAnyValue. */ #define VCVT_VOBJECT 5 /* if the VObject has value set by setVObjectVObjectValue. */ -extern const char** fieldedProp; +extern DLLEXPORT(const char**) fieldedProp; /*************************************************** * The methods below are implemented in vcc.c (generated from vcc.y ) ***************************************************/ /* NOTE regarding printVObject and writeVObject @@ -365,13 +369,13 @@ interface (at least that is my experience). Instead you can use their companion functions which take file names or pointers to memory. However, if you are linking this code into your build directly then you may find them a more convenient API and you can go ahead and use them. If you try to use them with the DLL LIB you will get a link error. */ -extern void writeVObject(FILE *fp, VObject *o); +extern DLLEXPORT(void) writeVObject(FILE *fp, VObject *o); typedef void (*MimeErrorHandler)(char *); extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler); @@ -390,32 +394,17 @@ you may find them a more convenient API that the other flavors that take a file name. If you use them with the DLL LIB you will get a link error. */ #if INCLUDEMFC -extern VObject* Parse_MIME_FromFile(CFile *file); +extern DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file); #else -extern VObject* Parse_MIME_FromFile(FILE *file); +extern DLLEXPORT(VObject*) Parse_MIME_FromFile(FILE *file); #endif -#define __SHARP_COMP_ - -#ifndef __SHARP_COMP_ extern DLLEXPORT(const char *) vObjectTypeInfo(VObject *o); -#else -// This function is not available in the Sharp ROM for SL 5500 ! -// Therefore I have to move it into the header file.. (se) - -inline const char* vObjectTypeInfo(VObject *o) -{ - const char *type = vObjectName( o ); - if ( strcmp( type, "TYPE" ) == 0 ) - type = vObjectStringZValue( o ); - return type; -} -#endif #endif /* __VOBJECT_H__ */ |