|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Simple Engine |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 |
|
23 #include <e32def.h> // First to avoid NULL redefine warning (no #ifndef NULL). |
|
24 #include <e32std.h> |
|
25 #include <string.h> |
|
26 |
|
27 #include <imcvcodc.h> |
|
28 |
|
29 // #include <e32std.h> |
|
30 #include <s32strm.h> |
|
31 #include <SenBaseElement.h> |
|
32 #include <SenBaseAttribute.h> |
|
33 #include <SenXmlUtils.h> |
|
34 #include <SenXmlReader.h> |
|
35 #include <SenDomFragment.h> |
|
36 |
|
37 #include <multipartparser.h> |
|
38 #include <bodypart.h> |
|
39 |
|
40 // own simple |
|
41 #include "simplecommon.h" |
|
42 #include "simpleelement.h" |
|
43 #include "simplenamespace.h" |
|
44 #include "simpleattribute.h" |
|
45 #include "simpledocument.h" |
|
46 #include "simplebasedocument.h" |
|
47 #include "simpleutils.h" |
|
48 #include "simplecontent.h" |
|
49 |
|
50 |
|
51 _LIT8 ( KSimpleEntity, "entity"); |
|
52 |
|
53 // Multipart CONSTANTS |
|
54 |
|
55 const char Multipart_CRLF_Text[] = {"\r\n"}; |
|
56 const char Multipart_DoubleCRLF_Text[] = {"\r\n\r\n"}; |
|
57 |
|
58 // MACROS |
|
59 #define MULTIPART_CONTENT_LOCATION_LENGTH 17 |
|
60 #define MULTIPART_CONTENT_TYPE_LENGTH 13 |
|
61 #define MULTIPART_CONTENT_TRANSFER_ENCODING_LENGTH 26 |
|
62 // violates RFC2045; but upon vodafone request |
|
63 #define MULTIPART_CONTENT_ENCODING_LENGTH 17 |
|
64 #define MULTIPART_CONTENT_LENGTH_LENGTH 15 |
|
65 #define MULTIPART_LAST_MODIFIED_LENGTH 14 |
|
66 #define MULTIPART_CONTENT_ID_LENGTH 11 |
|
67 |
|
68 #define MULTIPART_CONTENT_LOCATION 2 |
|
69 #define MULTIPART_CONTENT_TRANSFER_ENCODING 3 |
|
70 #define MULTIPART_CONTENT_TYPE 4 |
|
71 #define MULTIPART_CONTENT_ID 5 |
|
72 |
|
73 #define MULTIPART_INTERNET_DATE_STRING_LENGTH 29 |
|
74 |
|
75 #define SLASH_CHAR '/' |
|
76 #define DOT_CHAR '.' |
|
77 #define AT_CHAR '@' |
|
78 #define COLON_CHAR ':' |
|
79 // <scheme>:// |
|
80 // #define SCHEME_SEPARATOR_LENGTH 3 |
|
81 // ================= MEMBER FUNCTIONS ======================= |
|
82 // |
|
83 |
|
84 // ---------------------------------------------------------- |
|
85 // CSimpleDocument::CSimpleDocument |
|
86 // ---------------------------------------------------------- |
|
87 // |
|
88 CSimpleDocument::CSimpleDocument( ) |
|
89 : CSimpleBaseDocument() |
|
90 { |
|
91 } |
|
92 |
|
93 // ---------------------------------------------------------- |
|
94 // CSimpleDocument::~CSimpleDocument |
|
95 // ---------------------------------------------------------- |
|
96 // |
|
97 CSimpleDocument::~CSimpleDocument() |
|
98 { |
|
99 iContents.ResetAndDestroy(); |
|
100 iContents.Close(); |
|
101 } |
|
102 |
|
103 // ---------------------------------------------------------- |
|
104 // CSimpleDocument::ConstructL |
|
105 // ---------------------------------------------------------- |
|
106 // |
|
107 void CSimpleDocument::ConstructL( |
|
108 const TDesC8& aNsUri, |
|
109 const TDesC8& aLocalName ) |
|
110 { |
|
111 BaseConstructL(aNsUri, aLocalName); |
|
112 } |
|
113 |
|
114 // ---------------------------------------------------------- |
|
115 // CSimpleDocument::ConstructMultiPartL |
|
116 // ---------------------------------------------------------- |
|
117 // |
|
118 void CSimpleDocument::ConstructMultiPartL( |
|
119 const TDesC8& aData, const TDesC8& aBoundary, const TDesC8& aStart ) |
|
120 { |
|
121 _LIT(KUrl, "http://dummy.com/d1/d.html"); |
|
122 |
|
123 // body part array |
|
124 RPointerArray<CBodyPart> bodyPartArray; |
|
125 TCleanupItem clItem( ResetAndDestroy, &bodyPartArray ); |
|
126 CleanupStack::PushL( clItem ); |
|
127 |
|
128 // remove "..." characters from boundary if needed |
|
129 TPtrC8 pUnQuoted = aBoundary; |
|
130 TInt quoted = aBoundary.Locate('"'); |
|
131 if (!quoted) |
|
132 { |
|
133 pUnQuoted.Set( aBoundary.Mid( 1, aBoundary.Length() - 2 )); |
|
134 } |
|
135 // parse |
|
136 MultipartParser::ParseL( aData, KSimpleMultipartType, pUnQuoted, KUrl, bodyPartArray ); |
|
137 DoConstructL( bodyPartArray, aStart ); |
|
138 |
|
139 CleanupStack::PopAndDestroy( ); // bodyPartArray |
|
140 } |
|
141 |
|
142 // ---------------------------------------------------------- |
|
143 // CSimpleDocument::ConstructL |
|
144 // ---------------------------------------------------------- |
|
145 // |
|
146 void CSimpleDocument::ConstructL( |
|
147 const TDesC8& aXml ) |
|
148 { |
|
149 BaseConstructL( aXml ); |
|
150 } |
|
151 |
|
152 // ---------------------------------------------------------- |
|
153 // CSimpleDocument::NewL |
|
154 // ---------------------------------------------------------- |
|
155 // |
|
156 CSimpleDocument* CSimpleDocument::NewL( ) |
|
157 { |
|
158 CSimpleDocument* self = new (ELeave) CSimpleDocument( ); |
|
159 CleanupStack::PushL( self ); |
|
160 self->ConstructL( KSimpleNsDefault, KDocumentLocalName ); |
|
161 CleanupStack::Pop( self ); |
|
162 return self; |
|
163 } |
|
164 |
|
165 // ---------------------------------------------------------- |
|
166 // CSimpleDocument::NewL |
|
167 // ---------------------------------------------------------- |
|
168 // |
|
169 CSimpleDocument* CSimpleDocument::NewL( const TDesC8& aXml ) |
|
170 { |
|
171 CSimpleDocument* self = new (ELeave) CSimpleDocument( ); |
|
172 CleanupStack::PushL( self ); |
|
173 self->ConstructL( aXml ); |
|
174 CleanupStack::Pop( self ); |
|
175 return self; |
|
176 } |
|
177 |
|
178 // ---------------------------------------------------------- |
|
179 // CSimpleDocument::NewInMultiPartL |
|
180 // ---------------------------------------------------------- |
|
181 // |
|
182 CSimpleDocument* CSimpleDocument::NewInMultiPartL( |
|
183 const TDesC8& aData, const TDesC8& aBoundary, const TDesC8& aStart ) |
|
184 { |
|
185 CSimpleDocument* self = new (ELeave) CSimpleDocument( ); |
|
186 CleanupStack::PushL( self ); |
|
187 self->ConstructMultiPartL( aData, aBoundary, aStart ); |
|
188 CleanupStack::Pop( self ); |
|
189 return self; |
|
190 } |
|
191 |
|
192 // ---------------------------------------------------------- |
|
193 // CSimpleDocument::GetDirectContentsL |
|
194 // ---------------------------------------------------------- |
|
195 // |
|
196 void CSimpleDocument::GetDirectContentsL( |
|
197 RPointerArray<MSimpleContent>& aContents ) |
|
198 { |
|
199 aContents.Reset(); |
|
200 TInt myCount = iContents.Count(); |
|
201 for ( TInt i = 0; i<myCount; i++ ) |
|
202 { |
|
203 User::LeaveIfError( aContents.Append( iContents[i] )); |
|
204 } |
|
205 } |
|
206 |
|
207 // ---------------------------------------------------------- |
|
208 // CSimpleDocument::AddDirectContentL |
|
209 // ---------------------------------------------------------- |
|
210 // |
|
211 void CSimpleDocument::AddDirectContentL( |
|
212 MSimpleContent& aContent, |
|
213 TBool aCopyContent ) |
|
214 { |
|
215 CSimpleContent* content = CSimpleContent::NewLC( |
|
216 aContent.ContentID(), aContent.ContentType()); |
|
217 User::LeaveIfError( iContents.Append( content )); |
|
218 CleanupStack::Pop( content ); |
|
219 |
|
220 if ( aCopyContent ) |
|
221 { |
|
222 content->CopyBodyL( aContent.Body() ); |
|
223 } |
|
224 else |
|
225 { |
|
226 content->SetBody( aContent.GiveBodyOwnerShip() ); |
|
227 } |
|
228 } |
|
229 |
|
230 // ---------------------------------------------------------- |
|
231 // CSimpleDocument::ValidateXmlL |
|
232 // ---------------------------------------------------------- |
|
233 // |
|
234 void CSimpleDocument::ValidateXmlL( const TDesC8& aName ) |
|
235 { |
|
236 if ( aName.CompareF( KDocumentLocalName ) ) |
|
237 { |
|
238 User::Leave( KErrCorrupt ); |
|
239 } |
|
240 } |
|
241 |
|
242 // ---------------------------------------------------------- |
|
243 // CSimpleDocument::EntityURI |
|
244 // ---------------------------------------------------------- |
|
245 // |
|
246 const TDesC8* CSimpleDocument::EntityURI() |
|
247 { |
|
248 return Root()->AttrValue( KSimpleEntity ); |
|
249 } |
|
250 |
|
251 // ---------------------------------------------------------- |
|
252 // CSimpleDocument::SetEntityURIL |
|
253 // ---------------------------------------------------------- |
|
254 // |
|
255 void CSimpleDocument::SetEntityURIL( const TDesC8& aValue ) |
|
256 { |
|
257 Root()->AddAttr8L( KSimpleEntity, aValue ); |
|
258 } |
|
259 |
|
260 // ---------------------------------------------------------- |
|
261 // CSimpleDocument::DefaultNamespace |
|
262 // ---------------------------------------------------------- |
|
263 // |
|
264 |
|
265 TPtrC8 CSimpleDocument::DefaultNamespace() |
|
266 { |
|
267 return CSimpleBaseDocument::DefaultNamespace(); |
|
268 } |
|
269 |
|
270 |
|
271 // ---------------------------------------------------------- |
|
272 // CSimpleDocument::AddNamespaceL |
|
273 // ---------------------------------------------------------- |
|
274 // |
|
275 void CSimpleDocument::AddNamespaceL( |
|
276 const TDesC8& aPrefix, |
|
277 const TDesC8& aUri ) |
|
278 { |
|
279 CSimpleBaseDocument::AddNamespaceL( aPrefix, aUri ); |
|
280 } |
|
281 |
|
282 // ---------------------------------------------------------- |
|
283 // CSimpleDocument::NamespacesL |
|
284 // ---------------------------------------------------------- |
|
285 // |
|
286 RPointerArray<MSimpleNamespace>& CSimpleDocument::NamespacesL() |
|
287 { |
|
288 return CSimpleBaseDocument::NamespacesL(); |
|
289 } |
|
290 |
|
291 // ---------------------------------------------------------- |
|
292 // CSimpleDocument::ExternalizeL |
|
293 // ---------------------------------------------------------- |
|
294 // |
|
295 void CSimpleDocument::ExternalizeL( RWriteStream& aStream ) |
|
296 { |
|
297 |
|
298 // notice: check the max message size |
|
299 |
|
300 if ( !iContents.Count() ) |
|
301 { |
|
302 // single pidf+xml |
|
303 CSimpleBaseDocument::ExternalizeL( aStream ); |
|
304 } |
|
305 else |
|
306 { |
|
307 RPointerArray<CBodyPart> bodyPartsArray; |
|
308 RPointerArray<HBufC8> bufferArray; |
|
309 |
|
310 TRAPD( err, DoExternalizeMultiPartL( bodyPartsArray, bufferArray, aStream ) ); |
|
311 |
|
312 bufferArray.ResetAndDestroy(); |
|
313 bodyPartsArray.ResetAndDestroy(); |
|
314 bufferArray.Close(); |
|
315 bodyPartsArray.Close(); |
|
316 |
|
317 User::LeaveIfError( err ); |
|
318 } |
|
319 } |
|
320 |
|
321 // ---------------------------------------------------------- |
|
322 // CSimpleDocument::Close |
|
323 // ---------------------------------------------------------- |
|
324 // |
|
325 void CSimpleDocument::Close() |
|
326 { |
|
327 CSimpleBaseDocument::Close(); |
|
328 } |
|
329 |
|
330 // ---------------------------------------------------------- |
|
331 // CSimpleDocument::LocalName |
|
332 // ---------------------------------------------------------- |
|
333 // |
|
334 const TDesC8& CSimpleDocument::LocalName() |
|
335 { |
|
336 return CSimpleBaseDocument::LocalName(); |
|
337 } |
|
338 |
|
339 // ---------------------------------------------------------- |
|
340 // CSimpleDocument::DefNamespaceL |
|
341 // ---------------------------------------------------------- |
|
342 // |
|
343 MSimpleNamespace* CSimpleDocument::DefNamespaceL() |
|
344 { |
|
345 return CSimpleBaseDocument::DefNamespaceL(); |
|
346 } |
|
347 |
|
348 // ---------------------------------------------------------- |
|
349 // CSimpleDocument::HasContent |
|
350 // ---------------------------------------------------------- |
|
351 // |
|
352 TBool CSimpleDocument::HasContent() |
|
353 { |
|
354 return CSimpleBaseDocument::HasContent(); |
|
355 } |
|
356 |
|
357 // ---------------------------------------------------------- |
|
358 // CSimpleDocument::ContentUnicodeL |
|
359 // ---------------------------------------------------------- |
|
360 // |
|
361 HBufC* CSimpleDocument::ContentUnicodeL() |
|
362 { |
|
363 return CSimpleBaseDocument::ContentUnicodeL(); |
|
364 } |
|
365 |
|
366 // ---------------------------------------------------------- |
|
367 // CSimpleDocument::SetContentUnicodeL |
|
368 // ---------------------------------------------------------- |
|
369 // |
|
370 void CSimpleDocument::SetContentUnicodeL( const TDesC& aContent ) |
|
371 { |
|
372 CSimpleBaseDocument::SetContentUnicodeL( aContent ); |
|
373 } |
|
374 |
|
375 // ---------------------------------------------------------- |
|
376 // CSimpleDocument::SimpleElementsL |
|
377 // ---------------------------------------------------------- |
|
378 // |
|
379 TInt CSimpleDocument::SimpleElementsL( RPointerArray<MSimpleElement>& aElementArray ) |
|
380 { |
|
381 return CSimpleBaseDocument::SimpleElementsL( aElementArray ); |
|
382 } |
|
383 |
|
384 // ---------------------------------------------------------- |
|
385 // CSimpleDocument::AttrValueLC |
|
386 // ---------------------------------------------------------- |
|
387 // |
|
388 HBufC* CSimpleDocument::AttrValueLC( const TDesC8& aName ) |
|
389 { |
|
390 return CSimpleBaseDocument::AttrValueLC( aName ); |
|
391 } |
|
392 |
|
393 // ---------------------------------------------------------- |
|
394 // CSimpleDocument::AttrValue |
|
395 // ---------------------------------------------------------- |
|
396 // |
|
397 const TDesC8* CSimpleDocument::AttrValue( const TDesC8& aName ) |
|
398 { |
|
399 return CSimpleBaseDocument::AttrValue( aName ); |
|
400 } |
|
401 |
|
402 // ---------------------------------------------------------- |
|
403 // CSimpleDocument::AddAttrL |
|
404 // ---------------------------------------------------------- |
|
405 // |
|
406 void CSimpleDocument::AddAttrL( const TDesC8& aName, const TDesC& aValue ) |
|
407 { |
|
408 CSimpleBaseDocument::AddAttrL( aName, aValue ); |
|
409 } |
|
410 |
|
411 // ---------------------------------------------------------- |
|
412 // CSimpleDocument::SimpleAttributesL |
|
413 // ---------------------------------------------------------- |
|
414 // |
|
415 TInt CSimpleDocument::SimpleAttributesL( RPointerArray<MSimpleAttribute>& aArray ) |
|
416 { |
|
417 return CSimpleBaseDocument::SimpleAttributesL( aArray ); |
|
418 } |
|
419 |
|
420 // ---------------------------------------------------------- |
|
421 // CSimpleDocument::SimpleParentL |
|
422 // ---------------------------------------------------------- |
|
423 // |
|
424 MSimpleElement* CSimpleDocument::SimpleParentL() |
|
425 { |
|
426 return NULL; |
|
427 } |
|
428 |
|
429 // ---------------------------------------------------------- |
|
430 // CSimpleDocument::DetachSimpleL |
|
431 // ---------------------------------------------------------- |
|
432 // |
|
433 void CSimpleDocument::DetachSimpleL() |
|
434 { |
|
435 User::Leave( KErrNotFound ); |
|
436 } |
|
437 |
|
438 |
|
439 // ---------------------------------------------------------- |
|
440 // CSimpleDocument::AddSimpleElementL |
|
441 // ---------------------------------------------------------- |
|
442 // |
|
443 MSimpleElement* CSimpleDocument::AddSimpleElementL( |
|
444 const TDesC8& aNsUri, |
|
445 const TDesC8& aLocalName ) |
|
446 { |
|
447 return CSimpleBaseDocument::AddSimpleElementL( aNsUri, aLocalName ); |
|
448 } |
|
449 |
|
450 // ---------------------------------------------------------- |
|
451 // CSimpleDocument::AddSimpleElementL |
|
452 // ---------------------------------------------------------- |
|
453 // |
|
454 MSimpleElement* CSimpleDocument::AddSimpleElementL( |
|
455 const TDesC8& aLocalName ) |
|
456 { |
|
457 return CSimpleBaseDocument::AddSimpleElementL( aLocalName ); |
|
458 } |
|
459 |
|
460 |
|
461 // ---------------------------------------------------------- |
|
462 // CSimpleDocument::RemoveSimpleElement |
|
463 // ---------------------------------------------------------- |
|
464 // |
|
465 void CSimpleDocument::RemoveSimpleElement( |
|
466 const TDesC8& aNsUri, |
|
467 const TDesC8& aLocalName ) |
|
468 { |
|
469 CSimpleBaseDocument::RemoveSimpleElement( aNsUri, aLocalName ); |
|
470 } |
|
471 |
|
472 // ---------------------------------------------------------- |
|
473 // CSimpleDocument::ResetAndDestroy |
|
474 // ---------------------------------------------------------- |
|
475 // |
|
476 void CSimpleDocument::ResetAndDestroy( TAny* aPtrArray ) |
|
477 { |
|
478 RPointerArray<CBodyPart>* array = |
|
479 static_cast<RPointerArray<CBodyPart>*>( aPtrArray ); |
|
480 array->ResetAndDestroy(); |
|
481 array->Close(); |
|
482 } |
|
483 |
|
484 // ---------------------------------------------------------- |
|
485 // CSimpleDocument::DoConstructL |
|
486 // ---------------------------------------------------------- |
|
487 // |
|
488 void CSimpleDocument::DoConstructL( |
|
489 RPointerArray<CBodyPart>& aParts, const TDesC8& aStart ) |
|
490 { |
|
491 // Handle body parts one by one |
|
492 TInt size = aParts.Count(); |
|
493 TInt i; |
|
494 CBodyPart* cp = NULL; |
|
495 TPtrC8 boundary; |
|
496 TPtrC8 start; |
|
497 |
|
498 TBool pidfOk ( EFalse ); |
|
499 |
|
500 |
|
501 for (i = 0; i < size; i++) |
|
502 { |
|
503 cp = aParts[i]; |
|
504 |
|
505 if ( (( aStart.Length() > 0 && !aStart.Compare( cp->ContentID()) ) || |
|
506 !pidfOk ) && |
|
507 !cp->ContentType().Left(sizeof(KSimpleDocumentType)).CompareF( KSimpleDocumentType )) |
|
508 { |
|
509 // Multipart root is in the pidf+xml format |
|
510 BaseConstructL( cp->Body() ); |
|
511 pidfOk = ETrue; |
|
512 } |
|
513 else |
|
514 { |
|
515 // Direct contents, as a separate MIME multipart parts |
|
516 CSimpleContent* cd = CSimpleContent::NewL( |
|
517 cp->ContentID(), cp->ContentType() ); |
|
518 cd->CopyBodyL( cp->Body() ); |
|
519 CleanupStack::PushL( cd ); |
|
520 User::LeaveIfError( iContents.Append( cd ) ); |
|
521 CleanupStack::Pop( cd ); |
|
522 } |
|
523 } |
|
524 } |
|
525 |
|
526 // ------------------------------------------------------------------------- |
|
527 // CSimpleDocument::DoComposeMultiPartL |
|
528 // ------------------------------------------------------------------------- |
|
529 HBufC8* CSimpleDocument::DoComposeMultiPartL( RPointerArray<CBodyPart>& aBodyArray, |
|
530 const TDesC8& aBoundary ) |
|
531 { |
|
532 // --(aBoundary) |
|
533 using namespace NSimpleDocument; |
|
534 HBufC8* boundary = HBufC8::NewLC( aBoundary.Length() + 4 ); |
|
535 boundary->Des().Format( KBoundary, &aBoundary ); |
|
536 |
|
537 // CALCULATE the size of this document. |
|
538 TInt bodySize = 0; |
|
539 // a. for each CBodyPart |
|
540 // boundaries + CRLF between headers and body (constant addition) |
|
541 bodySize += (boundary->Length() + strlen(Multipart_CRLF_Text)) * aBodyArray.Count() ; |
|
542 TInt bodyCounter = aBodyArray.Count(); |
|
543 for (TInt i = 0; i < bodyCounter; i++) |
|
544 { |
|
545 if (!(aBodyArray[i]->Headers().Length() + |
|
546 aBodyArray[i]->Body().Length())) |
|
547 { |
|
548 // one less boundary |
|
549 bodySize -= boundary->Length() + strlen(Multipart_CRLF_Text); |
|
550 // skip empty bodypart |
|
551 continue; |
|
552 } |
|
553 bodySize += aBodyArray[i]->Headers().Length(); |
|
554 // ensure there are only 2 CRLFs between header and body |
|
555 if (aBodyArray[i]->Headers().Length() > 0) |
|
556 { |
|
557 TPtrC8 bodyHeaders(aBodyArray[i]->Headers().Ptr(), aBodyArray[i]->Headers().Length()); |
|
558 TUint newEnd = bodyHeaders.Length() - 1; |
|
559 while( bodyHeaders[ newEnd ] == '\r' || bodyHeaders[ newEnd ] == '\n' ) |
|
560 { |
|
561 --newEnd; |
|
562 --bodySize; |
|
563 } |
|
564 // two CRLFs |
|
565 bodySize += strlen(Multipart_CRLF_Text); |
|
566 } |
|
567 bodySize += aBodyArray[i]->Body().Length(); |
|
568 // CRLF (end of body, add one only if there is body AND does not end with CRLF) |
|
569 TPtrC8 bodyBody(aBodyArray[i]->Body().Ptr(), aBodyArray[i]->Body().Length()); |
|
570 if (bodyBody.Length() > 0 |
|
571 && bodyBody.Right(2) != TPtrC8((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text))) |
|
572 { |
|
573 bodySize += strlen(Multipart_CRLF_Text); |
|
574 } |
|
575 } |
|
576 // end boundary (boundary - '\r\n' + "--") |
|
577 bodySize += boundary->Length(); |
|
578 TInt docSize = bodySize; |
|
579 |
|
580 // CALCULATE the size of Headers |
|
581 using namespace NSimpleDocument::NSimpleMulti; |
|
582 |
|
583 // extra CRLF for separating header and body |
|
584 docSize += strlen(Multipart_CRLF_Text); |
|
585 // CALCULATION COMPLETE |
|
586 // at this point, bodySize contains the size of bodyparts, i.e. Content-Length: |
|
587 // and docSize contains the size of the entire document (use it to create HBufC8* |
|
588 // of appropriate size) |
|
589 |
|
590 // CONSTRUCT MULTIPART DOCUMENT |
|
591 HBufC8* document = HBufC8::NewLC(docSize); |
|
592 |
|
593 TPtr8 docAppend(document->Des()); |
|
594 |
|
595 // BODYPARTS |
|
596 for (TInt i = 0; i < aBodyArray.Count(); i++) |
|
597 { |
|
598 if (!(aBodyArray[i]->Headers().Length() + |
|
599 aBodyArray[i]->Body().Length())) |
|
600 { |
|
601 // skip empty bodypart |
|
602 continue; |
|
603 } |
|
604 docAppend.Append( *boundary ); |
|
605 TInt headerLength = aBodyArray[i]->Headers().Length() - 1; |
|
606 while ( headerLength > 0 && |
|
607 (aBodyArray[i]->Headers()[headerLength] == '\r' |
|
608 || aBodyArray[i]->Headers()[headerLength] == '\n' )) |
|
609 { |
|
610 --headerLength; |
|
611 } |
|
612 docAppend.Append( aBodyArray[i]->Headers().Ptr(), headerLength + 1 ); |
|
613 |
|
614 if ( headerLength > 0 ) |
|
615 { |
|
616 docAppend.Append((TUint8*)Multipart_DoubleCRLF_Text, strlen(Multipart_DoubleCRLF_Text)); |
|
617 } |
|
618 else |
|
619 { |
|
620 docAppend.Append((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text)); |
|
621 } |
|
622 // body |
|
623 TPtrC8 opa = aBodyArray[i]->Body(); |
|
624 docAppend.Append(aBodyArray[i]->Body()); |
|
625 // CRLF only if body exists and doesn't end with CRLF |
|
626 TPtrC8 bodyBody(aBodyArray[i]->Body().Ptr(), aBodyArray[i]->Body().Length()); |
|
627 if (bodyBody.Length() > 0 |
|
628 && bodyBody.Right(2) != TPtrC8((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text))) |
|
629 { |
|
630 docAppend.Append((TUint8*)Multipart_CRLF_Text, strlen(Multipart_CRLF_Text)); |
|
631 } |
|
632 } |
|
633 // end boundary |
|
634 docAppend.AppendFormat(KEndBoundary, &aBoundary); |
|
635 CleanupStack::Pop( document ); |
|
636 CleanupStack::PopAndDestroy( boundary ); |
|
637 return document; |
|
638 } |
|
639 |
|
640 // ------------------------------------------------------------------------- |
|
641 // CSimpleDocument::DoExternalizeMultiPartL |
|
642 // ------------------------------------------------------------------------- |
|
643 void CSimpleDocument::DoExternalizeMultiPartL( |
|
644 RPointerArray<CBodyPart>& aBodies, |
|
645 RPointerArray<HBufC8>& aBuffers, |
|
646 RWriteStream& aStream ) |
|
647 { |
|
648 const TReal KB64Expand = 1.5; // reserve room for Base64 encoding |
|
649 const TInt KBufferSize = 500; |
|
650 |
|
651 // Convert all the multipart into CBodyPart. |
|
652 |
|
653 // Let's convert first ROOT element into CBodyPart |
|
654 CBodyPart* root = CBodyPart::NewL(); |
|
655 // Add into cleanup array |
|
656 aBodies.Append( root ); |
|
657 CSenElement* e = Root()->BaseElement(); |
|
658 |
|
659 // externalize the document into stream |
|
660 CBufFlat* myBuffer = CBufFlat::NewL( KBufferSize ); |
|
661 CleanupStack::PushL( myBuffer ); |
|
662 myBuffer->Reset(); |
|
663 |
|
664 RBufWriteStream stream( *myBuffer ); |
|
665 stream.Open( *myBuffer ); |
|
666 CSimpleBaseDocument::ExternalizeL( stream ); |
|
667 stream.Close(); |
|
668 |
|
669 // Add content, no need to transfer encode |
|
670 TPtrC8 body ( myBuffer->Ptr(0) ); |
|
671 root->SetBody( body ); |
|
672 |
|
673 // Handle the headers of the ROOT part |
|
674 using namespace NSimpleDocument::NSimpleRoot; |
|
675 |
|
676 // calculate the size of headers |
|
677 TInt headerSize = KContentTypeSize + KCIDSize; |
|
678 HBufC8* headers = HBufC8::NewL( headerSize ); |
|
679 aBuffers.Append( headers ); |
|
680 TPtr8 pH(headers->Des()); |
|
681 // append to MIME headers for the root part |
|
682 pH.Append( NSimpleDocument::NSimpleRoot::KContentType ); |
|
683 pH.Append( NSimpleDocument::NSimpleRoot::KCID ); |
|
684 root->SetHeaders( pH ); |
|
685 |
|
686 // handle the direct contents one by one |
|
687 TInt contCount = iContents.Count(); |
|
688 for ( TInt i=0; i<contCount; i++ ) |
|
689 { |
|
690 // Let's convert next element into CBodyPart |
|
691 CBodyPart* cp = CBodyPart::NewL(); |
|
692 aBodies.Append( cp ); |
|
693 |
|
694 // Set Headers |
|
695 headerSize = NSimpleDocument::NSimpleContent::KContentTypeSize + |
|
696 NSimpleDocument::NSimpleContent::KCIDSize + |
|
697 NSimpleDocument::NSimpleContent::KContentEncodingSize; |
|
698 headerSize += (iContents[i])->ContentID().Length(); |
|
699 headerSize += (iContents[i])->ContentType().Length(); |
|
700 |
|
701 headers = HBufC8::NewL( headerSize ); |
|
702 // Append to cleanup array |
|
703 aBuffers.Append( headers ); |
|
704 pH.Set( headers->Des() ); |
|
705 |
|
706 // _LIT8( KMyContentType, "Content-Type: %S\r\n"); |
|
707 TPtrC8 myValue = (iContents[i])->ContentType(); |
|
708 pH.Format( NSimpleDocument::NSimpleContent::KContentType, &myValue ); |
|
709 myValue.Set((iContents[i])->ContentID() ); |
|
710 pH.AppendFormat( NSimpleDocument::NSimpleContent::KCID, &myValue ); |
|
711 pH.Append( NSimpleDocument::NSimpleContent::KContentEncoding ); |
|
712 // append to MIME headers |
|
713 cp->SetHeaders( pH ); |
|
714 |
|
715 // Body |
|
716 |
|
717 // BASE64 encode |
|
718 HBufC8* body64 = HBufC8::NewL( (iContents[i])->Body().Length() * KB64Expand ); |
|
719 aBuffers.Append( body64 ); |
|
720 TImCodecB64 codec64; |
|
721 codec64.Initialise(); |
|
722 TPtr8 desti8 = body64->Des(); |
|
723 |
|
724 // notice: leave if error? |
|
725 TInt err = codec64.Encode( (iContents[i])->Body(), desti8 ); |
|
726 |
|
727 cp->SetBody( body64->Des() ); |
|
728 } |
|
729 |
|
730 // Compose the multipart MIME flat data |
|
731 HBufC8* entireMsg = NULL; |
|
732 entireMsg = DoComposeMultiPartL( aBodies, NSimpleDocument::KSimpleBoundary ); |
|
733 CleanupStack::PushL( entireMsg ); |
|
734 // Finally stream entireMsg, |
|
735 // Notice: later DoComposeMultiPartL could stream directly? |
|
736 aStream.WriteL( entireMsg->Des() ); |
|
737 CleanupStack::PopAndDestroy( entireMsg ); |
|
738 CleanupStack::PopAndDestroy( myBuffer ); |
|
739 |
|
740 } |
|
741 |
|
742 |
|
743 |
|
744 |
|
745 |