Merge lp:~davidagraf/zorba/email-module-fixes into lp:zorba/email-module

Proposed by David Graf
Status: Merged
Approved by: David Graf
Approved revision: 47
Merged at revision: 47
Proposed branch: lp:~davidagraf/zorba/email-module-fixes
Merge into: lp:zorba/email-module
Diff against target: 496 lines (+151/-87)
2 files modified
src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp (+148/-85)
src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h (+3/-2)
To merge this branch: bzr merge lp:~davidagraf/zorba/email-module-fixes
Reviewer Review Type Date Requested Status
David Graf (community) Approve
Dennis Knochenwefel Approve
Alexander Kreutz (community) Approve
Review via email: mp+112051@code.launchpad.net

Commit message

Several email module fixes:
- case insensitive email attribute comparison
- catch more attachment filenames
- don't create empty recipients and email tags
- fixed typos
- made constant for namespace prefix
- introduced default mime charset
- remove newlines from base64 that comes from uw-imap
- if email content is quoted-printable encoded and the content type binary, it needs to be encoded into base64
- fixed content type check
- decode all email headers
- non-ascii (non encoded) chars are not allowed in email headers -> we ignore them
- added missing namespaces

Description of the change

Several email module fixes:
- case insensitive email attribute comparison
- catch more attachment filenames
- don't create empty recipients and email tags
- fixed typos
- made constant for namespace prefix
- introduced default mime charset
- remove newlines from base64 that comes from uw-imap
- if email content is quoted-printable encoded and the content type binary, it needs to be encoded into base64
- fixed content type check
- decode all email headers
- non-ascii (non encoded) chars are not allowed in email headers -> we ignore them
- added missing namespaces

To post a comment you must log in.
Revision history for this message
Alexander Kreutz (kreutz) :
review: Approve
Revision history for this message
David Graf (davidagraf) :
review: Approve
Revision history for this message
David Graf (davidagraf) wrote :

Unfortunately, I cannot run fix on ubuntu 12.04 because of:

./bin/zorba -q ~/sausalito/build/test.xq -f
operating system error [zerr:ZOSE0005]: "/home/dagraf/zorba/build/LIB_PATH/com/zorba-xquery/www/modules/email/libsmtp_1.0.so": error loading dynamic library: /home/dagraf/zorba/build/LIB_PATH/com/zorba-xquery/www/modules/email/libsmtp_1.0.so: undefined symbol: crypt; raised at /home/dagraf/zorba/sandbox/src/context/dynamic_loader.cpp:168

But it has nothing to do with the change.

Revision history for this message
David Graf (davidagraf) :
review: Needs Fixing
Revision history for this message
Dennis Knochenwefel (dennis-knochenwefel) :
review: Approve
Revision history for this message
David Graf (davidagraf) wrote :

The failing query execution on ubuntu has nothing to do with this change. When execution in a different environment, it works. Therefore, I approve it.

review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job email-module-fixes-2012-07-02T09-40-42.139Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp'
2--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp 2012-06-01 13:35:25 +0000
3+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp 2012-06-26 10:10:34 +0000
4@@ -21,10 +21,11 @@
5 #include <map>
6 #include <sstream>
7
8-#include <zorba/zorba.h>
9+#include <zorba/base64.h>
10+#include <zorba/diagnostic_list.h>
11 #include <zorba/iterator.h>
12 #include <zorba/user_exception.h>
13-#include <zorba/diagnostic_list.h>
14+#include <zorba/zorba.h>
15
16 #include <unicode/ucnv.h>
17 #include <unicode/ustring.h>
18@@ -36,6 +37,7 @@
19 namespace zorba { namespace emailmodule {
20
21 const char* ImapFunction::SCHEMA_NAMESPACE = "http://www.zorba-xquery.com/modules/email";
22+const char* ImapFunction::SCHEMA_PREFIX = "email";
23
24 ImapFunction::ImapFunction(const ImapModule* aModule)
25 : theModule(aModule)
26@@ -297,11 +299,11 @@
27 const bool aQualified) const
28 {
29 NsBindings ns_binding;
30- ns_binding.push_back(std::pair<String, String>("email", SCHEMA_NAMESPACE));
31+ ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
32
33 // if aParent is null, then we want to have the flags node qualified (so that it can be shema validated)
34 Item lFlagsName;
35- lFlagsName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "flags");
36+ lFlagsName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "flags");
37 Item lFlagsType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "flagsType");
38 aFlags = theModule->getItemFactory()->createElementNode(aParent, lFlagsName, lFlagsType, false, false, ns_binding);
39
40@@ -327,7 +329,7 @@
41 break;
42 }
43
44- Item lOneFlagName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", lFlagName);
45+ Item lOneFlagName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, lFlagName);
46 Item lOneFlagType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "emptyType");
47 Item lOneFlag = theModule->getItemFactory()->createElementNode(aFlags, lOneFlagName, lOneFlagType, false, true, ns_binding);
48 }
49@@ -366,7 +368,7 @@
50 Item lNullItem;
51
52 NsBindings null_binding;
53- Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "content");
54+ Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "content");
55 Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "contentType" );
56 Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, null_binding);
57
58@@ -390,37 +392,51 @@
59 const char* aMailbox,
60 const char* aHost) const
61 {
62- Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "emailAddress");
63- Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", aName);
64-
65- NsBindings ns_binding;
66- ns_binding.push_back(std::pair<String, String>("email", SCHEMA_NAMESPACE));
67-
68- Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding);
69- if (aPersonal) {
70- createInnerNodeWithText(lItem, SCHEMA_NAMESPACE, "email", "name", "http://www.w3.org/2001/XMLSchema", "string", aPersonal);
71- }
72 if ((aMailbox) && (aHost)) {
73- createInnerNodeWithText(lItem, SCHEMA_NAMESPACE, "email", "email", SCHEMA_NAMESPACE, "emailAddressType", std::string(aMailbox) + "@" + std::string(aHost));
74+ // mailbox and host needs to be available, otherwise broken
75+ Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "emailAddress");
76+ Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, aName);
77+
78+ NsBindings ns_binding;
79+ ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
80+
81+ Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding);
82+ if (aPersonal) {
83+ std::string lDecodedPersonal;
84+ decodeHeader(std::string(aPersonal), lDecodedPersonal);
85+ createInnerNodeWithText(
86+ lItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "name",
87+ "http://www.w3.org/2001/XMLSchema", "string", lDecodedPersonal);
88+ }
89+
90+ std::string lDecodedMailbox, lDecodedHost;
91+ decodeHeader(std::string(aMailbox), lDecodedMailbox);
92+ decodeHeader(std::string(aHost), lDecodedHost);
93+ createInnerNodeWithText(
94+ lItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "email", SCHEMA_NAMESPACE,
95+ "emailAddressType", lDecodedMailbox + "@" + lDecodedHost);
96 }
97 }
98
99 void
100-ImapFunction::createRecipentNode(
101+ImapFunction::createRecipientNode(
102 Item& aParent,
103 const std::string& aName,
104 const char* aPersonal,
105 const char* aMailbox,
106 const char* aHost) const
107 {
108- Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "recipientType");
109- Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "recipient");
110-
111- NsBindings ns_binding;
112- ns_binding.push_back(std::pair<String, String>("email", SCHEMA_NAMESPACE));
113-
114- Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding);
115- createEmailAddressNode(lItem, aName, aPersonal, aMailbox, aHost);
116+ if (aMailbox && aHost) {
117+ // mailbox and host needs to be available, otherwise bcc
118+ Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "recipientType");
119+ Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "recipient");
120+
121+ NsBindings ns_binding;
122+ ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
123+
124+ Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding);
125+ createEmailAddressNode(lItem, aName, aPersonal, aMailbox, aHost);
126+ }
127 }
128
129 void
130@@ -499,7 +515,7 @@
131 }
132
133 NsBindings ns_binding;
134- ns_binding.push_back(std::pair<String, String>("email", SCHEMA_NAMESPACE));
135+ ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
136
137 Item lEnvelopeItem;
138 std::string lErrorMessage = ImapClient::Instance().getError();
139@@ -512,33 +528,37 @@
140 // Important: if we only want the envelope, then the envelope MUST be qualified (being the root of the DOM)
141 Item lEnvelopeName;
142 if (aOnlyEnvelope) {
143- lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "envelope");
144+ lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelope");
145 } else {
146- lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "envelope");
147+ lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelope");
148 }
149- Item lEnvelopeType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "envelopeType");
150+ Item lEnvelopeType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelopeType");
151
152 Item lNullItem;
153 // if we only want the envelope, then create it with a null parent, else create the message and use it as parent
154 if (aOnlyEnvelope) {
155 lEnvelopeItem = theModule->getItemFactory()->createElementNode(lNullItem, lEnvelopeName, lEnvelopeType, false, false, ns_binding);
156 } else {
157- Item lMessageName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "message");
158- Item lMessageType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "messageType");
159+ Item lMessageName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "message");
160+ Item lMessageType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "messageType");
161 aParent = theModule->getItemFactory()->createElementNode(lNullItem, lMessageName, lMessageType, false, false, ns_binding);
162 lEnvelopeItem = theModule->getItemFactory()->createElementNode(aParent, lEnvelopeName, lEnvelopeType, false, false, ns_binding);
163 }
164
165 // create the remail node if needed
166 if (lEnvelope->remail) {
167- createInnerNodeWithText(lEnvelopeItem, SCHEMA_NAMESPACE, "email", "remail", "http://www.w3.org/2001/XMLSchema", "string", lEnvelope->remail);
168+ std::string lDecodedRemail;
169+ decodeHeader(std::string(lEnvelope->remail), lDecodedRemail);
170+ createInnerNodeWithText(
171+ lEnvelopeItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "remail",
172+ "http://www.w3.org/2001/XMLSchema", "string", lDecodedRemail);
173 }
174 // create the date node if needed
175 if (lEnvelope->date) {
176 createInnerNodeWithText(
177 lEnvelopeItem,
178 SCHEMA_NAMESPACE,
179- "email",
180+ SCHEMA_PREFIX,
181 "date",
182 "http://www.w3.org/2001/XMLSchema",
183 "string",
184@@ -561,36 +581,36 @@
185 std::string lSubject = lEnvelope->subject;
186 std::string lDecodedSubject;
187 decodeHeader(lSubject, lDecodedSubject);
188- createInnerNodeWithText(lEnvelopeItem, "", "", "subject", "http://www.w3.org/2001/XMLSchema", "string", lDecodedSubject);
189+ createInnerNodeWithText(lEnvelopeItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "subject", "http://www.w3.org/2001/XMLSchema", "string", lDecodedSubject);
190 }
191
192- ADDRESS* lRecipents;
193+ ADDRESS* lRecipients;
194 if (lEnvelope->to) {
195- createRecipentNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
196- lRecipents = lEnvelope->to;
197- while ((lRecipents = lRecipents->next)) {
198- createRecipentNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
199+ createRecipientNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
200+ lRecipients = lEnvelope->to;
201+ while ((lRecipients = lRecipients->next)) {
202+ createRecipientNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
203 }
204 }
205
206 if (lEnvelope->cc) {
207- createRecipentNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
208- lRecipents = lEnvelope->cc;
209- while ((lRecipents = lRecipents->next)) {
210- createRecipentNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
211+ createRecipientNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
212+ lRecipients = lEnvelope->cc;
213+ while ((lRecipients = lRecipients->next)) {
214+ createRecipientNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
215 }
216 }
217
218- if ((lRecipents = lEnvelope->bcc)) {
219- createRecipentNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
220- while ((lRecipents = lRecipents->next)) {
221- createRecipentNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
222+ if ((lRecipients = lEnvelope->bcc)) {
223+ createRecipientNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
224+ while ((lRecipients = lRecipients->next)) {
225+ createRecipientNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
226 }
227 }
228
229 // create messageId node
230 if (lEnvelope->message_id) {
231- createInnerNodeWithText(lEnvelopeItem, SCHEMA_NAMESPACE, "email", "messageId", "http://www.w3.org/2001/XMLSchema", "string", lEnvelope->message_id);
232+ createInnerNodeWithText(lEnvelopeItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "messageId", "http://www.w3.org/2001/XMLSchema", "string", lEnvelope->message_id);
233 }
234 Item lFlagsItem;
235 // create flags node
236@@ -605,20 +625,20 @@
237 // if we want the whole message, then build it together
238
239 // <email:mimeVersion>1.0</email:mimeVersion>
240- createInnerNodeWithText(aParent, SCHEMA_NAMESPACE, "email", "mimeVersion", "http://www.w3.org/2001/XMLSchema", "string", "1.0");
241+ createInnerNodeWithText(aParent, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "mimeVersion", "http://www.w3.org/2001/XMLSchema", "string", "1.0");
242
243 // make a tolower version of the subtype
244 std::string lSubType(lBody->subtype);
245 std::transform(lSubType.begin(), lSubType.end(), lSubType.begin(), tolower);
246
247 // creating the <body> node
248- Item lBodyName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "body");
249- Item lBodyType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "bodyTypeChoice");
250+ Item lBodyName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "body");
251+ Item lBodyType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "bodyTypeChoice");
252 Item lBodyItem = theModule->getItemFactory()->createElementNode(aParent, lBodyName, lBodyType, false, false, ns_binding);
253 // in case of non-multipart, just add the body to the message
254
255- Item lMultipartParentName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "multipart");
256- Item lMultipartParentType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "email", "multipartType");
257+ Item lMultipartParentName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "multipart");
258+ Item lMultipartParentType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "multipartType");
259 Item lMultipartParent;
260 // using a vector instead of a stack, because including stack will clash with the c-client include ...
261 std::vector<BODY*> lBodies;
262@@ -656,10 +676,15 @@
263
264 PARAMETER* lCurrentParameter = lCurrentBody->disposition.parameter;
265 while (lCurrentParameter != NIL) {
266-
267- if (!std::string("filename").compare(lCurrentParameter->attribute)) {
268- lContentDispositionFilename = cpystr(lCurrentParameter->value);
269- } else if (!std::string("modification-date").compare(lCurrentParameter->attribute)) {
270+ std::string lAttribute = lCurrentParameter->attribute;
271+ std::transform(lAttribute.begin(), lAttribute.end(), lAttribute.begin(), ::tolower);
272+ if (!std::string("filename").compare(lAttribute)) {
273+ lContentDispositionFilename = cpystr(lCurrentParameter->value);
274+ } else if (!std::string("filename*0").compare(lAttribute)) {
275+ // TODO this is a hack that works for most cases.
276+ // See: http://tools.ietf.org/html/rfc2184 [Page 3]
277+ lContentDispositionFilename = cpystr(lCurrentParameter->value);
278+ } else if (!std::string("modification-date").compare(lAttribute)) {
279 lContentDispositionModificationDate = cpystr(lCurrentParameter->value);
280 }
281
282@@ -684,10 +709,14 @@
283 std::string lBodyContent = ImapClient::Instance().fetchBodyFull(aHostName, aUserName, aPassword, aMailbox, aMessageNumber, lNoMultipart ? "1" : lCurrentSection, aUid);
284
285 // reading charset from email
286- const char* lCharset = 0;
287+ // default mime charset, see
288+ // http://tools.ietf.org/html/draft-ietf-appsawg-mime-default-charset-04
289+ std::string lCharset = "ISO-8859-1";
290 PARAMETER* lParam = lCurrentBody->parameter;
291 while (lParam) {
292- if (strcmp(lParam->attribute, "charset") == 0) {
293+ std::string lAttribute = lParam->attribute;
294+ std::transform(lAttribute.begin(), lAttribute.end(), lAttribute.begin(), ::tolower);
295+ if (lAttribute.compare("charset") == 0) {
296 lCharset = lParam->value;
297 }
298 lParam = lParam->next;
299@@ -697,7 +726,7 @@
300 unsigned short lEncoding = lCurrentBody->encoding;
301 // decode the body according the transfer encoding if it is quoted-printable
302 decodeTextualTransferEncoding(lBodyContent, lContentType, lEncoding, lTransferEncodingDecoded);
303-
304+
305 // decode the body according to the charset
306 std::string lCharsetDecoded;
307 toUtf8(lTransferEncodingDecoded, lCharset, lCharsetDecoded);
308@@ -736,10 +765,10 @@
309 void
310 ImapFunction::toUtf8(
311 const std::string& aValue,
312- const char* aFromCharset,
313+ const std::string& aFromCharset,
314 std::string& aResult) const
315 {
316- if (!aFromCharset || std::string(aFromCharset) == "") {
317+ if (aFromCharset == "") {
318 aResult = aValue;
319 return;
320 }
321@@ -752,7 +781,7 @@
322 UConverter *lConverter;
323
324 // set up the converter
325- lConverter = ucnv_open(aFromCharset, &lStatus);
326+ lConverter = ucnv_open(aFromCharset.c_str(), &lStatus);
327 checkStatus(lStatus);
328
329 // convert to Unicode
330@@ -793,23 +822,42 @@
331 }
332 }
333
334+struct PrintableAsciiChar
335+{
336+ bool operator()(char c) const {
337+ unsigned int u = static_cast<unsigned int>(c);
338+ return !(u == '\t' || u == '\n' || u == '\t' || (u >= 32 && u <= 127));
339+ }
340+};
341
342 void
343 ImapFunction::decodeHeader(
344 const std::string& aValue,
345 std::string& aResult) const
346 {
347+ std::string lValue = aValue;
348+ // We assume that email headers must not contain non-printable characters
349+ // because special chars need to be encoded.
350+ // Therefore, we filter everything non-printable out to avoid problems.
351+ lValue.erase(
352+ std::remove_if(
353+ lValue.begin(),
354+ lValue.end(),
355+ PrintableAsciiChar()),
356+ lValue.end()
357+ );
358+
359 std::stringstream lDecoded;
360 std::size_t lMarker = 0;
361
362 // size used many times
363- std::size_t lLength = aValue.length();
364+ std::size_t lLength = lValue.length();
365 // to collect question mark positions
366 std::vector<std::size_t> lQMs;
367
368 // populate the above vectors
369 for (std::size_t i = 0; i < lLength; i++) {
370- if (aValue.at(i) == '?') {
371+ if (lValue.at(i) == '?') {
372 lQMs.push_back(i);
373 }
374 }
375@@ -819,7 +867,7 @@
376
377 // not enough questions marks to make up an encoding, give up
378 if (lQLength < 4) {
379- aResult = aValue;
380+ aResult = lValue;
381 return;
382 }
383
384@@ -830,17 +878,17 @@
385 // 2nd and 3rd question marks have only one character in between
386 lQMs[j + 1] + 2 == lQMs[j + 2] &&
387 // 1st question mark is prefixed by an equal sign
388- (lQMs[j] > 0 && aValue.at(lQMs[j] - 1) == '=') &&
389+ (lQMs[j] > 0 && lValue.at(lQMs[j] - 1) == '=') &&
390 // 4th question mark is suffixes by an equal sign
391- (lQMs[j + 3] < (lLength-1) && aValue.at(lQMs[j + 3] + 1) == '='))
392+ (lQMs[j + 3] < (lLength-1) && lValue.at(lQMs[j + 3] + 1) == '='))
393 {
394 // ok were good, so first save the text from the last marker
395 // upto the starting equal sign
396- lDecoded << aValue.substr(lMarker, lQMs[j] - lMarker - 1);
397+ lDecoded << lValue.substr(lMarker, lQMs[j] - lMarker - 1);
398
399 // then take the entire region, including =? and ?= and try to decode it
400 std::string lWords;
401- decodeEncodedWords(aValue.substr(lQMs[j] - 1, lQMs[j + 3] - lQMs[j] + 3), lWords);
402+ decodeEncodedWords(lValue.substr(lQMs[j] - 1, lQMs[j + 3] - lQMs[j] + 3), lWords);
403 lDecoded << lWords;
404
405 // save the new marker at the end of this encoded word group
406@@ -854,11 +902,16 @@
407 ++j;
408 }
409 }
410- lDecoded << aValue.substr(lMarker);
411+ lDecoded << lValue.substr(lMarker);
412
413 aResult = lDecoded.str();
414 }
415
416+bool isTextOrXMLContentType(const std::string& aContentType) {
417+ return aContentType.find("text/") != std::string::npos
418+ || aContentType == "application/xml"
419+ || aContentType.find("+xml") != std::string::npos;
420+}
421
422 void
423 ImapFunction::decodeTextualTransferEncoding(
424@@ -873,19 +926,29 @@
425 aResult = std::string((char *)lNewData, lNewLength);
426 fs_give(&lNewData);
427 aEncoding = ENC8BIT;
428- }
429- else if (aEncoding == ENCBASE64 &&
430- (
431- aContentType.find("text") != std::string::npos
432- || aContentType.find("xml") != std::string::npos
433- )) {
434- unsigned long lNewLength;
435- void* lNewData = rfc822_base64((unsigned char*)aValue.c_str(), aValue.length(), &lNewLength);
436- aResult = std::string((char *)lNewData, lNewLength);
437- fs_give(&lNewData);
438- aEncoding = ENC8BIT;
439- }
440- else {
441+ if (!isTextOrXMLContentType(aContentType)) {
442+ // binary content needs to be base64 encoded for zorba
443+ zorba::String lInput(aResult.c_str());
444+ zorba::String lOutput = zorba::encoding::Base64::encode(lInput);
445+ aResult = lOutput.c_str();
446+ }
447+ }
448+ else if (aEncoding == ENCBASE64) {
449+ aResult = aValue;
450+ // remove newlines from base64
451+ aResult.erase(std::remove(aResult.begin(), aResult.end(), '\r'), aResult.end());
452+ aResult.erase(std::remove(aResult.begin(), aResult.end(), '\n'), aResult.end());
453+ if (isTextOrXMLContentType(aContentType))
454+ {
455+ unsigned long lNewLength;
456+ void* lNewData = rfc822_base64((unsigned char*)aResult.c_str(), aResult.length(), &lNewLength);
457+ aResult = std::string((char *)lNewData, lNewLength);
458+ fs_give(&lNewData);
459+ aEncoding = ENC8BIT;
460+ }
461+ }
462+ else
463+ {
464 aResult = aValue;
465 }
466 }
467
468=== modified file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h'
469--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h 2012-01-11 16:52:34 +0000
470+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h 2012-06-26 10:10:34 +0000
471@@ -35,6 +35,7 @@
472 protected:
473 const ImapModule* theModule;
474 static const char* SCHEMA_NAMESPACE;
475+ static const char* SCHEMA_PREFIX;
476
477 void
478 raiseImapError(
479@@ -130,7 +131,7 @@
480 const char* aHost) const;
481
482 void
483- createRecipentNode(
484+ createRecipientNode(
485 Item& aParent,
486 const std::string& aName,
487 const char* aPersonal,
488@@ -167,7 +168,7 @@
489 void
490 toUtf8(
491 const std::string& value,
492- const char* fromCharset,
493+ const std::string& fromCharset,
494 std::string& result) const;
495
496 void

Subscribers

People subscribed via source and target branches

to all changes: