|
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: Preparation XOP message for HTTP transmission in case |
|
15 * of request and extracting BLOBs from XOP message responsed |
|
16 * through HTTP channel in case of response |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 #include "senmultipartutils.h" |
|
28 |
|
29 |
|
30 |
|
31 // ======== MEMBER FUNCTIONS ======== |
|
32 |
|
33 // --------------------------------------------------------------------------- |
|
34 // Serializes SoapEnvelope message in XOP message |
|
35 // --------------------------------------------------------------------------- |
|
36 // |
|
37 EXPORT_C void SenMultiPartUtils::SerializeMessageL(CSenFragmentBase& aMessage, |
|
38 RBuf8& aMultiPartMessage, |
|
39 TXmlEngSerializerType aType) |
|
40 { |
|
41 __ASSERT_ALWAYS(&aMessage, |
|
42 User::Panic(KMultiPartNoRequestMessagePanicText, EMultiPartNoRequestMessage)); |
|
43 RSenDocument doc = aMessage.AsDocumentL(); |
|
44 CXmlEngSerializer* serializer = CXmlEngSerializer::NewL(aType); |
|
45 __ASSERT_ALWAYS(serializer, User::Panic(KMultiPartPanicText, KErrNotFound)); |
|
46 CleanupStack::PushL(serializer); |
|
47 TXmlEngSerializationOptions options(TXmlEngSerializationOptions::KOptionIndent & TXmlEngSerializationOptions::KOptionOmitXMLDeclaration); |
|
48 serializer->SetOutput(aMultiPartMessage); |
|
49 serializer->SetSerializationOptions(options); |
|
50 serializer->SerializeL(doc); |
|
51 CleanupStack::PopAndDestroy(serializer); |
|
52 } |
|
53 |
|
54 // --------------------------------------------------------------------------- |
|
55 // Generates random content-ID for header of XOP message and for headers of BLOBs |
|
56 // as randomNumber@homeTime |
|
57 // @param aRootCid is ReAlloc'd, which means that any existing data is freed |
|
58 // prior the generated root cid is assinged to that buffer. |
|
59 // --------------------------------------------------------------------------- |
|
60 // |
|
61 EXPORT_C void SenMultiPartUtils::GenerateRandomRootCidL(RBuf8& aRootCid) |
|
62 { |
|
63 _LIT8(KAt, "@"); |
|
64 TTime now; |
|
65 now.HomeTime(); |
|
66 TInt64 homeTime = now.Int64(); |
|
67 TInt64 randomNumber = Math::Random(); |
|
68 aRootCid.ReAllocL(32+KAt().Length()); |
|
69 aRootCid.AppendNum(randomNumber); |
|
70 aRootCid.Append(KAt); |
|
71 aRootCid.AppendNum(homeTime); |
|
72 } |
|
73 |
|
74 // --------------------------------------------------------------------------- |
|
75 // Generates random boundary for mime header as randomNumber |
|
76 // @param aBoundary is ReAlloc'd, which means that any existing data is freed |
|
77 // prior the generated root cid is assinged to that buffer. |
|
78 // --------------------------------------------------------------------------- |
|
79 // |
|
80 EXPORT_C void SenMultiPartUtils::GenerateRandomBoundaryL(RBuf8& aBoundary) |
|
81 { |
|
82 TInt64 randomNumber = Math::Random(); |
|
83 aBoundary.ReAllocL(16); |
|
84 aBoundary.AppendNum(randomNumber); |
|
85 } |
|
86 |
|
87 // --------------------------------------------------------------------------- |
|
88 // Generates MimeBoundary to separate mime parts of the message |
|
89 // as --randomNumber |
|
90 // --------------------------------------------------------------------------- |
|
91 // |
|
92 EXPORT_C void SenMultiPartUtils::BoundaryLineStartL(const RBuf8& aBoundary, RBuf8& aBoundaryStart) |
|
93 { |
|
94 aBoundaryStart.ReAllocL(KNewLine().Length()+KDush().Length()+aBoundary.Length()); |
|
95 aBoundaryStart.Append(KDush); |
|
96 aBoundaryStart.Append(aBoundary); |
|
97 aBoundaryStart.Append(KNewLine); |
|
98 } |
|
99 |
|
100 // --------------------------------------------------------------------------- |
|
101 // Generates MimeBoundaryEnd to end the multipart message (MultiPart message) |
|
102 // as --randomNumber-- |
|
103 // --------------------------------------------------------------------------- |
|
104 // |
|
105 EXPORT_C void SenMultiPartUtils::BoundaryLineEndL(const RBuf8& aBoundary, RBuf8& aBoundaryEnd) |
|
106 { |
|
107 aBoundaryEnd.ReAllocL(3*KNewLine().Length()+2*KDush().Length()+aBoundary.Length()); |
|
108 aBoundaryEnd.Append(KNewLine); |
|
109 aBoundaryEnd.Append(KNewLine); |
|
110 aBoundaryEnd.Append(KDush); |
|
111 aBoundaryEnd.Append(aBoundary); |
|
112 aBoundaryEnd.Append(KDush); |
|
113 aBoundaryEnd.Append(KNewLine); |
|
114 } |
|
115 |
|
116 // --------------------------------------------------------------------------- |
|
117 // Creates header for root of XOP message or other multiPart message |
|
118 // The header sould be the next: |
|
119 // |
|
120 // Content-Type: application/xop+xml; |
|
121 // charset=UTF-8; |
|
122 // type="text/xml" (for SOAP 1.1) or "application/soap+xml" (for SOAP 1.2) |
|
123 // Content-Transfer-Encoding: 8bit |
|
124 // Content-ID: <randomNumber@homeTime> |
|
125 // |
|
126 // where "Content-ID" is the same as "start" in Header of Outer Package |
|
127 // --------------------------------------------------------------------------- |
|
128 // |
|
129 EXPORT_C void SenMultiPartUtils::HeaderRootL(MSenMessage* aMessage, |
|
130 const RBuf8& aRootCid, RBuf8& aHeaderRoot) |
|
131 { |
|
132 |
|
133 if( aMessage->IsSafeToCast(MSenMessage::ESoapEnvelope2 )) |
|
134 { |
|
135 CSenSoapEnvelope2* pSoapEnvelope2 = (CSenSoapEnvelope2*)aMessage; |
|
136 switch (pSoapEnvelope2->SoapVersion()) |
|
137 { |
|
138 case ESOAP11: |
|
139 { |
|
140 aHeaderRoot.ReAllocL(KMultiPartHeaderRootStart11().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length()); |
|
141 aHeaderRoot.Append(KMultiPartHeaderRootStart11); |
|
142 break; |
|
143 } |
|
144 case ESOAP12: |
|
145 { |
|
146 aHeaderRoot.ReAllocL(KMultiPartHeaderRootStart12().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length()); |
|
147 aHeaderRoot.Append(KMultiPartHeaderRootStart12); |
|
148 break; |
|
149 } |
|
150 default: |
|
151 { |
|
152 User::Panic(KMultiPartSoapVersionInvalidPanicText, EMultiPartSoapVersionInvalid); |
|
153 } |
|
154 } |
|
155 } |
|
156 else if( aMessage->IsSafeToCast(MSenMessage::EAtomMessage )) |
|
157 { |
|
158 aHeaderRoot.ReAllocL(KMultiPartAtomHeaderRootStart().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length()); |
|
159 aHeaderRoot.Append(KMultiPartAtomHeaderRootStart); |
|
160 } |
|
161 aHeaderRoot.Append(aRootCid); |
|
162 aHeaderRoot.Append(KMultiPartHeaderRootEnd); |
|
163 } |
|
164 |
|
165 // --------------------------------------------------------------------------- |
|
166 // Creates the header for binary data[aIndex] of XOP message |
|
167 // The header sould be the next: |
|
168 // |
|
169 // --MIME_boundary |
|
170 // Content-Type: image/png (for images) or some other type for other BLOBs |
|
171 // Content-Transfer-Encoding: binary |
|
172 // Content-ID: <randomNumber@homeTime> |
|
173 // |
|
174 // --------------------------------------------------------------------------- |
|
175 // |
|
176 EXPORT_C void SenMultiPartUtils::HeaderBinaryDataL(TUint aIndex, |
|
177 RArray<TXmlEngDataContainer>& aBinaryDataList, |
|
178 RBuf8& aHeaderBinaryData) |
|
179 { |
|
180 __ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); |
|
181 __ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument)); |
|
182 |
|
183 TPtrC8 cid = aBinaryDataList[aIndex].Cid(); |
|
184 |
|
185 RXmlEngNodeList<TXmlEngAttr> attributes; // to take value of "ContentType" attribute |
|
186 aBinaryDataList[aIndex].ParentNode().AsElement().GetAttributes(attributes); |
|
187 CleanupClosePushL(attributes); |
|
188 |
|
189 RBuf8 contentType; |
|
190 CleanupClosePushL(contentType); |
|
191 while (attributes.HasNext()) |
|
192 { |
|
193 TXmlEngAttr attr = attributes.Next(); |
|
194 if (attr.Name() == KMultiPartContentTypeName) |
|
195 { |
|
196 contentType.ReAllocL(attr.Value().Length()); |
|
197 contentType.Copy(attr.Value()); |
|
198 break; |
|
199 } |
|
200 } |
|
201 if (contentType == KNullDesC8) |
|
202 { |
|
203 contentType.ReAllocL(KMultiPartDefaultBinaryContentTypeValue().Length()); |
|
204 contentType.Copy(KMultiPartDefaultBinaryContentTypeValue); |
|
205 } |
|
206 |
|
207 |
|
208 aHeaderBinaryData.ReAllocL(KMultiPartHeaderBinaryDataContentType().Length()+ |
|
209 KMultiPartHeaderBinaryDataContentID().Length()+ |
|
210 KMultiPartHeaderBinaryDataEnd().Length()+ |
|
211 contentType.Length()+ |
|
212 cid.Length()); |
|
213 aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataContentType); |
|
214 aHeaderBinaryData.Append(contentType); |
|
215 aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataContentID); |
|
216 aHeaderBinaryData.Append(cid); |
|
217 aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataEnd); |
|
218 |
|
219 CleanupStack::PopAndDestroy(&contentType); |
|
220 CleanupStack::PopAndDestroy(&attributes); |
|
221 } |
|
222 |
|
223 // --------------------------------------------------------------------------- |
|
224 // Extracts a part of BLOB (10KB) from a file |
|
225 // --------------------------------------------------------------------------- |
|
226 // |
|
227 EXPORT_C void SenMultiPartUtils::FileDataPartL(TUint aPart, TUint aIndex, |
|
228 RArray<TXmlEngDataContainer>& aBinaryDataList, |
|
229 RBuf8& aBinaryData) |
|
230 { |
|
231 __ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); |
|
232 __ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument)); |
|
233 |
|
234 aBinaryData.ReAllocL(KTenKBytes); |
|
235 |
|
236 RFile& file = aBinaryDataList[aIndex].AsFileContainer().File(); |
|
237 file.Flush(); |
|
238 file.Read(aPart*KTenKBytes, aBinaryData, KTenKBytes); |
|
239 } |
|
240 |
|
241 // --------------------------------------------------------------------------- |
|
242 // Extracts the rest of BLOB (less than 10KB) from a file |
|
243 // --------------------------------------------------------------------------- |
|
244 // |
|
245 EXPORT_C void SenMultiPartUtils::FileDataRestL(TUint aParts, TUint aRest, TUint aIndex, |
|
246 RArray<TXmlEngDataContainer>& aBinaryDataList, |
|
247 RBuf8& aBinaryData) |
|
248 { |
|
249 __ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); |
|
250 __ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument)); |
|
251 |
|
252 aBinaryData.ReAllocL(aRest); |
|
253 RFile& file = aBinaryDataList[aIndex].AsFileContainer().File(); |
|
254 file.Flush(); |
|
255 file.Read(aParts*KTenKBytes, aBinaryData, aRest); |
|
256 } |
|
257 |
|
258 // --------------------------------------------------------------------------- |
|
259 // Extracts CIDs of BLOBs from response MultiPart message |
|
260 // --------------------------------------------------------------------------- |
|
261 // |
|
262 EXPORT_C void SenMultiPartUtils::CidL(const RBuf8& aBlobHeader, RArray<RBuf8>& aCids) |
|
263 { |
|
264 _LIT8(KContentIDName, "Content-ID: <"); |
|
265 _LIT8(KGreaterThan,">"); |
|
266 TInt offset = aBlobHeader.Find(KContentIDName); |
|
267 if (offset == KErrNotFound) |
|
268 { |
|
269 User::Panic(KMultiPartNoCidPanicText, EMultiPartNoCid); |
|
270 } |
|
271 TPtrC8 blobHeaderPtr; // to extract BLOB header from Response message |
|
272 blobHeaderPtr.Set(aBlobHeader.Right(aBlobHeader.Length()-offset-KContentIDName().Length())); |
|
273 |
|
274 offset = blobHeaderPtr.Find(KGreaterThan);//CodeScannerWarning |
|
275 if (offset == KErrNotFound) |
|
276 { |
|
277 User::Panic(KMultiPartCidInvalidPanicText, EMultiPartCidInvalid); |
|
278 } |
|
279 RBuf8 cid; // CID of the BLOB |
|
280 cid.ReAllocL(offset); |
|
281 cid.Copy(blobHeaderPtr.Left(offset)); |
|
282 aCids.AppendL(cid); // collects CIDs of all BLOBs |
|
283 } |
|
284 |
|
285 // --------------------------------------------------------------------------- |
|
286 // Generates the file name for BLOB of response MultiPart message |
|
287 // and collects it in array of file names for the all BLOBs |
|
288 // --------------------------------------------------------------------------- |
|
289 // |
|
290 void SenMultiPartUtils::FileNameL(TUint aIndex, RArray<RBuf8>& aFileNames) |
|
291 { |
|
292 RBuf8 fileName; |
|
293 fileName.ReAllocL(KFileName().Length()+7); |
|
294 fileName.Append(KFileName); |
|
295 fileName.AppendNum(aIndex); |
|
296 aFileNames.Append(fileName); |
|
297 } |
|
298 |
|
299 // --------------------------------------------------------------------------- |
|
300 // Extracts BLOB from response MultiPart message and writes it in a file |
|
301 // --------------------------------------------------------------------------- |
|
302 // |
|
303 EXPORT_C TInt SenMultiPartUtils::SetFileL(TUint aIndex, TBool aFirst, TDesC8& aBlob, |
|
304 RArray<RBuf8>& aFileNames) |
|
305 { |
|
306 RFs rfs; |
|
307 RFile file; |
|
308 |
|
309 User::LeaveIfError(rfs.Connect()); |
|
310 CleanupClosePushL(rfs); |
|
311 TInt retVal = rfs.ShareProtected(); |
|
312 CleanupClosePushL(file); |
|
313 |
|
314 TInt sizeFile = 0; |
|
315 RBuf fileName; //fileName is necessary to convert from 8bites(aFileNames[aIndex]) to 16 |
|
316 CleanupClosePushL(fileName); |
|
317 if (aFirst) // check if is it the first part of a BLOB to write in a file |
|
318 { |
|
319 FileNameL(aIndex, aFileNames); // generates the new file |
|
320 fileName.ReAllocL(aFileNames[aIndex].Length()); |
|
321 fileName.Copy(aFileNames[aIndex]); |
|
322 User::LeaveIfError(file.Replace(rfs, fileName, EFileWrite)); // replases the old one to the new one |
|
323 } |
|
324 else // if it's not the first part of BLOB then only open the existing file and write a BLOB part in it |
|
325 { |
|
326 fileName.ReAllocL(aFileNames[aIndex].Length()); |
|
327 fileName.Copy(aFileNames[aIndex]); |
|
328 User::LeaveIfError(file.Open(rfs, fileName, EFileWrite)); |
|
329 } |
|
330 |
|
331 file.Size(sizeFile); |
|
332 User::LeaveIfError(file.Write(sizeFile, aBlob, aBlob.Length())); |
|
333 |
|
334 file.Flush(); |
|
335 file.Close(); |
|
336 |
|
337 User::LeaveIfError(file.Open(rfs, fileName, EFileRead)); |
|
338 |
|
339 //fileName.Close(); |
|
340 CleanupStack::PopAndDestroy(&fileName); |
|
341 CleanupStack::PopAndDestroy(&file); |
|
342 CleanupStack::PopAndDestroy(&rfs); |
|
343 return (sizeFile+aBlob.Length()); |
|
344 } |
|
345 |
|
346 // End of file |
|
347 |