summaryrefslogtreecommitdiff
authoreilers <eilers>2003-03-27 16:17:48 (UTC)
committer eilers <eilers>2003-03-27 16:17:48 (UTC)
commit390a5a0c332c8c6fb380c1ed4cd6adae3e544a08 (patch) (side-by-side diff)
tree7ad6266be3d78d25ae061a0be067f82f8d666246
parentff43585778968407bb08473e45ddd1d942f8d8c8 (diff)
downloadopie-390a5a0c332c8c6fb380c1ed4cd6adae3e544a08.zip
opie-390a5a0c332c8c6fb380c1ed4cd6adae3e544a08.tar.gz
opie-390a5a0c332c8c6fb380c1ed4cd6adae3e544a08.tar.bz2
using releases from qtopia-free-1.6.0-snapshot-20030324 which fixes the
following bugs #776 and #490: Now, we could successfully parse vcards from palm 4 + 5 and quoted-printable encoded lines .. !
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/backend/vcc.y22
-rw-r--r--library/backend/vcc_yacc.cpp127
-rw-r--r--library/backend/vobject.cpp163
-rw-r--r--library/backend/vobject_p.h29
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
@@ -101,49 +101,49 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
#ifndef _NO_LINE_FOLDING
#define _SUPPORT_LINE_FOLDING 1
#endif
/* undef below if compile with MFC */
/* #define INCLUDEMFC 1 */
#if defined(WIN32) || defined(_WIN32)
#ifdef INCLUDEMFC
#include <afx.h>
#endif
#endif
#include <string.h>
#ifndef __MWERKS__
#include <stdlib.h>
#endif
#include <stdio.h>
#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 */
#define YYSTACKSIZE 100 // ~unref ?
#define MAXLEVEL 10 /* max # of nested objects parseable */
/* (includes outermost) */
/**** Global Variables ****/
int mime_lineNum, mime_numErrors; /* yyerror() can use these */
static VObject* vObjList;
static VObject *curProp;
static VObject *curObj;
static VObject* ObjStack[MAXLEVEL];
static int ObjStackTop;
/* A helpful utility for the rest of the app. */
#if __CPLUSPLUS__
extern "C" {
#endif
@@ -702,58 +702,64 @@ static void handleMoreRFC822LineBreak(int c) {
a = lexLookahead();
if (a == ' ' || a == '\t') {
/* continuation, throw away all the \n and spaces read so
* far
*/
lexSkipWhite();
lexPushLookaheadc(';');
}
else {
lexPushLookaheadc('\n');
lexPushLookaheadc(';');
}
}
else {
lexPushLookaheadc(';');
}
}
}
static char* lexGet1Value() {
int c;
lexSkipWhite();
c = lexLookahead();
lexClearToken();
- while (c != EOF && c != ';') {
+ 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') {
lexAppendc(' ');
lexSkipLookahead();
}
else {
lexPushLookaheadc('\n');
break;
}
}
else {
lexAppendc(c);
lexSkipLookahead();
}
c = lexLookahead();
}
lexAppendc(0);
handleMoreRFC822LineBreak(c);
return c==EOF?0:lexStr();
}
@@ -940,88 +946,90 @@ static char* lexGetQuotedPrintable()
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;
}
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;
}
// got a valid escaped =. append it.
lexSkipLookahead(); // skip second 0-9A-F
lexAppendc(cur);
} else {
lexSkipLookahead(); // skip whatever we just read.
lexAppendc(c); // and append it.
}
c = lexLookahead();
}
lexAppendc(0);
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;
}
else if (strchr("\n",c)) {
++mime_lineNum;
/* consume all line separator(s) adjacent to each other */
c = lexLookahead();
while (strchr("\n",c)) {
lexSkipLookahead();
c = lexLookahead();
++mime_lineNum;
}
DBG_(("db: LINESEP\n"));
return LINESEP;
}
else {
char *p = 0;
lexPushLookaheadc(c);
if (lexWithinMode(L_BASE64)) {
/* get each char and convert to bin on the fly... */
p = lexGetDataFromBase64();
@@ -1033,54 +1041,56 @@ static int yylex() {
}
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. */
+ /* 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;
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 (isalnum(c)) {
char *t = lexGetWord();
yylval.str = t;
if (!qstricmp(t, "begin")) {
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
@@ -137,49 +137,49 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
#ifndef _NO_LINE_FOLDING
#define _SUPPORT_LINE_FOLDING 1
#endif
/* undef below if compile with MFC */
/* #define INCLUDEMFC 1 */
#if defined(WIN32) || defined(_WIN32)
#ifdef INCLUDEMFC
#include <afx.h>
#endif
#endif
#include <string.h>
#ifndef __MWERKS__
#include <stdlib.h>
#endif
#include <stdio.h>
#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 */
#define YYSTACKSIZE 100 /* ~unref ? */
#define MAXLEVEL 10 /* max # of nested objects parseable */
/* (includes outermost) */
/**** Global Variables ****/
int mime_lineNum, mime_numErrors; /* yyerror() can use these */
static VObject* vObjList;
static VObject *curProp;
static VObject *curObj;
static VObject* ObjStack[MAXLEVEL];
static int ObjStackTop;
/* A helpful utility for the rest of the app. */
#if __CPLUSPLUS__
extern "C" {
#endif
@@ -722,58 +722,64 @@ static void handleMoreRFC822LineBreak(int c) {
a = lexLookahead();
if (a == ' ' || a == '\t') {
/* continuation, throw away all the \n and spaces read so
* far
*/
lexSkipWhite();
lexPushLookaheadc(';');
}
else {
lexPushLookaheadc('\n');
lexPushLookaheadc(';');
}
}
else {
lexPushLookaheadc(';');
}
}
}
static char* lexGet1Value() {
int c;
lexSkipWhite();
c = lexLookahead();
lexClearToken();
- while (c != EOF && c != ';') {
+ 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') {
lexAppendc(' ');
lexSkipLookahead();
}
else {
lexPushLookaheadc('\n');
break;
}
}
else {
lexAppendc(c);
lexSkipLookahead();
}
c = lexLookahead();
}
lexAppendc(0);
handleMoreRFC822LineBreak(c);
return c==EOF?0:lexStr();
}
@@ -930,109 +936,120 @@ static char * lexGetDataFromBase64()
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()
{
- 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;
}
else if (strchr("\n",c)) {
++mime_lineNum;
/* consume all line separator(s) adjacent to each other */
c = lexLookahead();
while (strchr("\n",c)) {
lexSkipLookahead();
c = lexLookahead();
++mime_lineNum;
}
DBG_(("db: LINESEP\n"));
return LINESEP;
}
else {
char *p = 0;
lexPushLookaheadc(c);
if (lexWithinMode(L_BASE64)) {
/* get each char and convert to bin on the fly... */
p = lexGetDataFromBase64();
@@ -1044,54 +1061,56 @@ static int yylex() {
}
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. */
+ /* 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;
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 (isalnum(c)) {
char *t = lexGetWord();
yylval.str = t;
if (!qstricmp(t, "begin")) {
@@ -1196,49 +1215,49 @@ DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
static MimeErrorHandler mimeErrorHandler;
DLLEXPORT(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"
+#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__)
yyparse(void)
#else
yyparse()
#endif
{
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
@@ -1496,49 +1515,49 @@ case 42:
if (!pushVObject(VCTodoProp)) YYERROR;
}
break;
case 43:
#line 366 "backend/vcc.y"
{
lexPopMode(0);
popVObject();
}
break;
case 44:
#line 371 "backend/vcc.y"
{
lexPushMode(L_VTODO);
if (!pushVObject(VCTodoProp)) YYERROR;
}
break;
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)
{
#if YYDEBUG
if (yydebug)
printf("%sdebug: after reduction, shifting from state 0 to\
state %d\n", YYPREFIX, 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";
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
@@ -25,89 +25,94 @@ 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.
*/
#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>
#define NAME_OF(o) o->id
#define VALUE_TYPE(o) o->valType
#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;
} ValueItem;
struct VObject {
VObject *next;
const char *id;
VObject *prop;
unsigned short valType;
ValueItem val;
};
typedef struct StrItem StrItem;
struct StrItem {
StrItem *next;
const char *s;
unsigned int refCnt;
};
-const char** fieldedProp;
+DLLEXPORT(const char**) fieldedProp;
/*----------------------------------------------------------------------
The following functions involve with memory allocation:
newVObject
deleteVObject
dupStr
deleteStr
newStrItem
deleteStrItem
----------------------------------------------------------------------*/
DLLEXPORT(VObject*) newVObject_(const char *id)
{
VObject *p = (VObject*)malloc(sizeof(VObject));
p->next = 0;
p->id = id;
p->prop = 0;
VALUE_TYPE(p) = 0;
ANY_VALUE_OF(p) = 0;
return p;
}
@@ -932,48 +937,59 @@ stuff:
}
static void appendcOFile(OFile *fp, char c)
{
if (c == '\n') {
/* write out as <CR><LF> */
appendcOFile_(fp,0xd);
appendcOFile_(fp,0xa);
}
else
appendcOFile_(fp,c);
}
static void appendsOFile(OFile *fp, const char *s)
{
int i, slen;
slen = strlen(s);
for (i=0; i<slen; i++) {
appendcOFile(fp,s[i]);
}
}
#endif
+static void 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;
fp->alloc = 0;
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;
@@ -984,215 +1000,200 @@ static int writeBase64(OFile *fp, unsigned char *s, long len)
}
// 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 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;
if (div < 10)
trans[1] = '0' + div;
else
trans[1] = 'A' + (div - 10);
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)
"+" (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 = 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);
break;
}
case VCVT_ULONG: {
char buf[16];
sprintf(buf,"%lu", LONG_VALUE_OF(o));
appendsOFile(fp,buf);
break;
}
case VCVT_RAW: {
appendcOFile(fp,'\n');
writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
break;
}
case VCVT_VOBJECT:
appendcOFile(fp,'\n');
writeVObject_(fp,VOBJECT_VALUE_OF(o));
break;
}
}
static void writeAttrValue(OFile *fp, VObject *o)
{
if (NAME_OF(o)) {
struct PreDefProp *pi;
pi = lookupPropInfo(NAME_OF(o));
if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
- 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];
char buf2[256];
strcpy(buf1,NAME_OF(o));
while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
strcpy(buf2,STRINGZ_VALUE_OF(o));
strcat(buf2,".");
strcat(buf2,buf1);
strcpy(buf1,buf2);
}
appendsOFile(fp,buf1);
}
static int inList(const char **list, const char *s)
{
if (list == 0) return 0;
while (*list) {
if (qstricmp(*list,s) == 0) return 1;
list++;
}
@@ -1214,133 +1215,151 @@ static void writeProp(OFile *fp, VObject *o)
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))
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)
{
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 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);
}
DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
{
QFileDirect f( fname);
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vobject write %s", fname);
return;
}
writeVObject( f.directHandle(),o );
}
DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
{
QFileDirect f( fname);
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vobject write %s", fname);
return;
}
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
@@ -78,51 +78,55 @@ which accompanied this distribution.
#ifndef __VOBJECT_H__
#define __VOBJECT_H__ 1
#include <qstring.h>
#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
are globally unique IDs which can be used to generate clipboard format
ID's as per the requirements of a specific platform. For example, in
Windows they are used as the parameter in a call to RegisterClipboardFormat.
For example:
CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
*/
#define vCardMimeType "text/x-vCard"
#define vCalendarMimeType "text/x-vCalendar"
#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
#endif
#ifndef TRUE
#define TRUE 1
#endif
#include <stdlib.h>
#include <stdio.h>
#define VC7bitProp "7BIT"
#define VC8bitProp "8BIT"
#define VCAAlarmProp "AALARM"
#define VCAdditionalNamesProp "ADDN"
#define VCAdrProp "ADR"
#define VCAgentProp "AGENT"
#define VCAIFFProp "AIFF"
#define VCAOLProp "AOL"
#define VCAppleLinkProp "APPLELINK"
@@ -330,92 +334,77 @@ extern DLLEXPORT(void) cleanVObject(VObject *o);
extern DLLEXPORT(void) cleanVObjects(VObject *list);
extern DLLEXPORT(const char*) lookupProp(const char* str);
extern DLLEXPORT(const char*) lookupProp_(const char* str);
extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o);
extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list);
extern DLLEXPORT(int) vObjectValueType(VObject *o);
/* return type of vObjectValueType: */
#define VCVT_NOVALUE 0
/* if the VObject has no value associated with it. */
#define VCVT_STRINGZ 1
/* if the VObject has value set by setVObjectStringZValue. */
#define VCVT_UINT 2
/* if the VObject has value set by setVObjectIntegerValue. */
#define VCVT_ULONG 3
/* 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
The functions below are not exported from the DLL because they
take a FILE* as a parameter, which cannot be passed across a DLL
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);
extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len);
extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname);
/* NOTE regarding Parse_MIME_FromFile
The function above, Parse_MIME_FromFile, comes in two flavors,
neither of which is exported from the DLL. Each version takes
a CFile or FILE* as a parameter, neither of which can be
passed across a DLL interface (at least that is my experience).
If you are linking this code into your build directly then
you may find them a more convenient API that the other flavors
that take a file name. If you use them with the DLL LIB you
will get a link error.
*/
#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__ */