|
1 /* |
|
2 * Copyright (c) 2002-2004 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: Loads html content |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "MailLog.h" |
|
22 #include "MailUtils.h" |
|
23 #include "MailLoadStateHtml.h" |
|
24 #include "MailLoadStateInline.h" |
|
25 #include "MailLoadStateMachine.h" |
|
26 #include "MsgMailViewerHtmlConv.h" |
|
27 #include <MailPlainView.rsg> |
|
28 #include <MMailAppUiInterface.h> |
|
29 #include <CMailMessage.h> |
|
30 #include <StringLoader.h> |
|
31 #include <charconv.h> |
|
32 |
|
33 _LIT8( KStartTag, "<html>" ); |
|
34 _LIT8( KHtmlHeader1, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset="); |
|
35 _LIT8( KHtmlHeader2, "\">\n"); |
|
36 _LIT8( KCharsetTag, "CHARSET" ); |
|
37 _LIT16( KCDrive, "C:" ); |
|
38 const TInt KPathNameLength( 100 ); |
|
39 |
|
40 // ============================ MEMBER FUNCTIONS =============================== |
|
41 |
|
42 // load html file |
|
43 // ----------------------------------------------------------------------------- |
|
44 // CLoadHtmlFile::MessageLoadingL |
|
45 // ----------------------------------------------------------------------------- |
|
46 // |
|
47 void CLoadHtmlFile::MessageLoadingL(TInt aStatus, CMailMessage& aMessage) |
|
48 { |
|
49 if( aStatus == CMailMessage::EBodyTextReady ) |
|
50 { |
|
51 TRAPD( err, HandleBodyTextReadyL( aMessage ) ); |
|
52 |
|
53 if( err ) |
|
54 { |
|
55 // Complete request and leave if error occured |
|
56 CompleteRequest( err ); |
|
57 User::LeaveIfError( err ); |
|
58 } |
|
59 } |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // CLoadHtmlFile::CLoadHtmlFile |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 CLoadHtmlFile::CLoadHtmlFile( |
|
67 MMailAppUiInterface* aAppUI, MStateMachine& aStateMachine ) : |
|
68 CActive( CActive::EPriorityStandard ) |
|
69 { |
|
70 CActiveScheduler::Add( this ); |
|
71 iAppUI = aAppUI; |
|
72 iStateMachine = &aStateMachine; |
|
73 } |
|
74 |
|
75 // ----------------------------------------------------------------------------- |
|
76 // CLoadHtmlFile::~CLoadHtmlFile |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 CLoadHtmlFile::~CLoadHtmlFile() |
|
80 { |
|
81 Cancel(); |
|
82 delete iConverter; |
|
83 } |
|
84 |
|
85 // ----------------------------------------------------------------------------- |
|
86 // CLoadHtmlFile::NextStateL |
|
87 // ----------------------------------------------------------------------------- |
|
88 // |
|
89 MLoadState* CLoadHtmlFile::NextStateL() |
|
90 { |
|
91 return new( ELeave ) CLoadInlineImages( |
|
92 iAppUI, *iStateMachine ); |
|
93 } |
|
94 |
|
95 // ----------------------------------------------------------------------------- |
|
96 // CLoadHtmlFile::MakeRequestL |
|
97 // ----------------------------------------------------------------------------- |
|
98 // |
|
99 void CLoadHtmlFile::MakeRequestL( |
|
100 TRequestStatus& aStatus, |
|
101 CMailMessage& aMessage ) |
|
102 { |
|
103 iLoadStatus = &aStatus; |
|
104 iMessage = &aMessage; |
|
105 aMessage.LoadHtmlContentL( *this ); |
|
106 aStatus = KRequestPending; |
|
107 } |
|
108 |
|
109 // ----------------------------------------------------------------------------- |
|
110 // CLoadHtmlFile::HandleBodyTextReadyL |
|
111 // ----------------------------------------------------------------------------- |
|
112 // |
|
113 void CLoadHtmlFile::HandleBodyTextReadyL( CMailMessage& aMessage ) |
|
114 { |
|
115 RFile handle = aMessage.HtmlContent(); |
|
116 CleanupClosePushL( handle ); |
|
117 |
|
118 if ( handle.SubSessionHandle() == 0 ) |
|
119 { |
|
120 // if html content can not be found try to show plain text |
|
121 // content |
|
122 CRichText* bodyText = aMessage.MessageBody(); |
|
123 // Partial loaded or corrupted message? |
|
124 if ( aMessage.MessageEntry().PartialDownloaded() ) |
|
125 { |
|
126 HBufC* text = StringLoader::LoadLC( |
|
127 R_QTN_MAIL_REST_OF_MAIL_NOT_FETCHED, CCoeEnv::Static()); |
|
128 |
|
129 bodyText->InsertL(0, *text); |
|
130 CleanupStack::PopAndDestroy(); // text |
|
131 } |
|
132 else // Corrupted? |
|
133 { |
|
134 MailUtils::InformationNoteL( |
|
135 R_MAIL_VIEWER_HTML_ERROR_DLG_TEXT ); |
|
136 } |
|
137 iAppUI->SetBodyTextL(*aMessage.MessageBody()); |
|
138 CompleteRequest( KErrNone ); |
|
139 } |
|
140 else |
|
141 { |
|
142 // Add html content as attachment before conversion. |
|
143 if ( !aMessage.MessageEntry().PartialDownloaded() ) |
|
144 { |
|
145 AddHtmlFileAttachmentAndCharsetL( aMessage, handle ); |
|
146 } |
|
147 ParseHtmlFileL( aMessage, handle ); |
|
148 } |
|
149 CleanupStack::PopAndDestroy(); // handle |
|
150 } |
|
151 |
|
152 // ----------------------------------------------------------------------------- |
|
153 // CLoadHtmlFile::ShowHtmlErrorNoteIfNeededL |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 void CLoadHtmlFile::ShowHtmlErrorNoteIfNeededL( TInt aResult ) |
|
157 { |
|
158 if ( aResult == KErrNotFound ) |
|
159 { |
|
160 MailUtils::InformationNoteL( R_MAIL_VIEWER_HTML_ERROR_DLG_TEXT ); |
|
161 } |
|
162 else if ( aResult == KErrCorrupt ) |
|
163 { |
|
164 MailUtils::InformationNoteL( R_MAIL_VIEWER_HTML_CORRUPTED_NOTE_TEXT ); |
|
165 } |
|
166 else if ( aResult == KErrEof ) |
|
167 { |
|
168 // Successfully parsed. Do nothing. |
|
169 } |
|
170 else |
|
171 { |
|
172 User::LeaveIfError( aResult ); |
|
173 } |
|
174 } |
|
175 |
|
176 // ----------------------------------------------------------------------------- |
|
177 // CLoadHtmlFile::AddHtmlFileAttachmentL |
|
178 // ----------------------------------------------------------------------------- |
|
179 // |
|
180 void CLoadHtmlFile::AddHtmlFileAttachmentL( |
|
181 CMailMessage& aMessage, RFile aFile ) |
|
182 { |
|
183 CMsvAttachment* htmlFileInfo = CMsvAttachment::NewL( |
|
184 CMsvAttachment::EMsvFile ); |
|
185 CleanupStack::PushL( htmlFileInfo ); |
|
186 |
|
187 TInt htmlSize(0); |
|
188 aFile.Size( htmlSize ); |
|
189 htmlFileInfo->SetSize( htmlSize ); |
|
190 TFileName filename; |
|
191 User::LeaveIfError( aFile.Name( filename ) ); |
|
192 htmlFileInfo->SetAttachmentNameL( filename ); |
|
193 htmlFileInfo->SetComplete( ETrue ); |
|
194 htmlFileInfo->SetId( aMessage.MhtmlPartId() ); |
|
195 |
|
196 iAppUI->AddAttachmentL( *htmlFileInfo, EFalse ); |
|
197 CleanupStack::PopAndDestroy( htmlFileInfo ); |
|
198 } |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // CLoadHtmlFile::ParseHtmlFileL |
|
202 // ----------------------------------------------------------------------------- |
|
203 // |
|
204 void CLoadHtmlFile::ParseHtmlFileL(CMailMessage& aMessage, RFile aFile ) |
|
205 { |
|
206 LOG( "CLoadHtmlFile::ParseHtmlFileL" ); |
|
207 LOGHANDLESIZE( aFile ); |
|
208 |
|
209 // Get the charset of the html part from the message. If the message |
|
210 // thinks it knows the html charset then force the conversion of the html |
|
211 // part using the specified character set decoding. |
|
212 // |
|
213 // Otherwise, if the html message part character set is unknown, then |
|
214 // we'll let the conversion object try to identify the character set during |
|
215 // the parsing process. |
|
216 const TUint htmlCharSetId = aMessage.HtmlCharsetIdL(); |
|
217 const TBool forceCharSet = ( htmlCharSetId != 0 ); |
|
218 |
|
219 delete iConverter; |
|
220 iConverter = NULL; |
|
221 iConverter = CMsgMailViewerHtmlConv::NewL( |
|
222 aFile, |
|
223 htmlCharSetId, |
|
224 forceCharSet ); |
|
225 |
|
226 iConverter->Convert( &iStatus ); |
|
227 SetActive(); |
|
228 } |
|
229 |
|
230 // ----------------------------------------------------------------------------- |
|
231 // CLoadHtmlFile::RunL |
|
232 // ----------------------------------------------------------------------------- |
|
233 // |
|
234 void CLoadHtmlFile::RunL() |
|
235 { |
|
236 LOG( "CLoadHtmlFile::RunL" ); |
|
237 ShowHtmlErrorNoteIfNeededL( iStatus.Int() ); |
|
238 |
|
239 CRichText* bodyText = iMessage->MessageBody(); |
|
240 bodyText->Reset(); |
|
241 bodyText->InsertL(0, *(iConverter->GetText())); |
|
242 |
|
243 // If the conversion process successfully identified the characterset |
|
244 // of the html part, then update the message with this new charset |
|
245 // decoding value. |
|
246 if ( iConverter->AutoParsedCharSetNameAndIdentifier() ) |
|
247 { |
|
248 const TUint autoParsedCharSetId = iConverter->AutoParsedCharSetIdentifier(); |
|
249 iMessage->OverrideHtmlMessageCharset( autoParsedCharSetId ); |
|
250 } |
|
251 |
|
252 iStateMachine->SetIdArray( iConverter->FileIdArray() ); |
|
253 |
|
254 if ( iMessage->MessageEntry().PartialDownloaded() ) |
|
255 { |
|
256 HBufC* text = StringLoader::LoadLC( |
|
257 R_QTN_MAIL_REST_OF_MAIL_NOT_FETCHED, CCoeEnv::Static()); |
|
258 |
|
259 bodyText->InsertL(bodyText->DocumentLength(), CEditableText::ELineBreak); |
|
260 |
|
261 bodyText->InsertL(bodyText->DocumentLength(), *text); |
|
262 |
|
263 CleanupStack::PopAndDestroy(); // text |
|
264 } |
|
265 |
|
266 iAppUI->SetBodyTextL( *(iMessage->MessageBody()) ); |
|
267 |
|
268 // All done |
|
269 CompleteRequest( KErrNone ); |
|
270 } |
|
271 |
|
272 // ----------------------------------------------------------------------------- |
|
273 // CLoadHtmlFile::RunError |
|
274 // ----------------------------------------------------------------------------- |
|
275 // |
|
276 TInt CLoadHtmlFile::RunError( TInt aError ) |
|
277 { |
|
278 LOG( "CLoadHtmlFile::DoCancel" ); |
|
279 CompleteRequest( aError ); |
|
280 return KErrNone; |
|
281 } |
|
282 |
|
283 // ----------------------------------------------------------------------------- |
|
284 // CLoadHtmlFile::DoCancel |
|
285 // ----------------------------------------------------------------------------- |
|
286 // |
|
287 void CLoadHtmlFile::DoCancel() |
|
288 { |
|
289 LOG( "CLoadHtmlFile::DoCancel" ); |
|
290 |
|
291 if( iConverter ) |
|
292 { |
|
293 iConverter->Cancel(); |
|
294 } |
|
295 } |
|
296 |
|
297 // ----------------------------------------------------------------------------- |
|
298 // CLoadHtmlFile::CompleteRequest |
|
299 // ----------------------------------------------------------------------------- |
|
300 // |
|
301 void CLoadHtmlFile::CompleteRequest( TInt aError ) |
|
302 { |
|
303 LOG( "CLoadHtmlFile::CompleteRequest" ); |
|
304 User::RequestComplete( iLoadStatus, aError ); |
|
305 iAppUI->ViewMessageComplete(); |
|
306 } |
|
307 |
|
308 // ----------------------------------------------------------------------------- |
|
309 // CLoadHtmlFile::AddCharsetToHtmlAttachment |
|
310 // ----------------------------------------------------------------------------- |
|
311 // |
|
312 void CLoadHtmlFile::AddHtmlFileAttachmentAndCharsetL( CMailMessage& aMessage, RFile& aHandle ) |
|
313 { |
|
314 // We have to check if the html body contains information about |
|
315 // charset used. If it does, we use original file. Otherwise |
|
316 // we create a new html file which has charset |
|
317 // information added |
|
318 |
|
319 // Get charset Id and handle for the html body content |
|
320 TUint htmlCharsetId = aMessage.HtmlCharsetIdL(); |
|
321 |
|
322 // Convert charset Id into string |
|
323 RFs& fs = CCoeEnv::Static()->FsSession(); |
|
324 CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC(); |
|
325 HBufC8* charsetBuf = charConv-> |
|
326 ConvertCharacterSetIdentifierToStandardNameL( |
|
327 htmlCharsetId, fs); |
|
328 CleanupStack::PopAndDestroy( charConv ); // charConv |
|
329 CleanupStack::PushL( charsetBuf ); |
|
330 TPtr8 charsetPtr = charsetBuf->Des(); |
|
331 |
|
332 // Calculate buffer size for charsetRowBuf and also for |
|
333 // htmlContentBuf to avoid reallocation of memory |
|
334 TInt bufferSize( 0 ); |
|
335 bufferSize += KHtmlHeader1().Length(); |
|
336 bufferSize += charsetBuf->Length(); |
|
337 bufferSize += KHtmlHeader2().Length(); |
|
338 |
|
339 // Read html content from the html file |
|
340 TInt fileSize(0); |
|
341 aHandle.Size( fileSize ); |
|
342 HBufC8* htmlContentBuf = HBufC8::NewLC( fileSize+bufferSize ); |
|
343 TPtr8 htmlContentPtr = htmlContentBuf->Des(); |
|
344 aHandle.Read( htmlContentPtr ); |
|
345 TInt i( 0 ); |
|
346 aHandle.Seek( ESeekStart, i ); // rewind the file |
|
347 |
|
348 // Try to find strings CHARSET and <html> |
|
349 // If the string is not found append information containing charset |
|
350 TInt charsetFoundAt( htmlContentBuf->Find( KCharsetTag ) ); |
|
351 TInt htmlTagFoundAt( htmlContentBuf->Find( KStartTag ) ); |
|
352 |
|
353 // If CHARSET is defined in the email but it is not found from the |
|
354 // html body part, we have to add it ourselves. |
|
355 // Else use the original html file |
|
356 if( charsetFoundAt <= 0 |
|
357 && htmlTagFoundAt >= 0 ) |
|
358 { |
|
359 // Create a new hmtl line containing character set information |
|
360 // and append it. |
|
361 // Create new buffer for storing charset html info row and |
|
362 // insert it to the buffer containing html body |
|
363 HBufC8* charsetRowBuf = HBufC8::NewLC( bufferSize ); |
|
364 TPtr8 charsetRowPtr = charsetRowBuf->Des(); |
|
365 charsetRowPtr.Append( KHtmlHeader1 ); |
|
366 charsetRowPtr.Append( charsetPtr ); |
|
367 charsetRowPtr.Append( KHtmlHeader2 ); |
|
368 htmlContentPtr.Insert( htmlTagFoundAt, charsetRowPtr ); |
|
369 CleanupStack::PopAndDestroy( charsetRowBuf ); |
|
370 |
|
371 // create mailviewer folder in c:\private |
|
372 HBufC* pathNameBuf = HBufC::NewLC( KPathNameLength ); |
|
373 TPtr pathNamePtr = pathNameBuf->Des(); |
|
374 fs.PrivatePath( pathNamePtr ); |
|
375 pathNamePtr.Insert( 0, KCDrive ); |
|
376 |
|
377 TInt makeDir = fs.MkDir( pathNamePtr ); |
|
378 // Itīs ok if directory already exists. If other errors, |
|
379 // use original html file |
|
380 if( makeDir != KErrAlreadyExists && makeDir < 0 ) |
|
381 { |
|
382 AddHtmlFileAttachmentL( aMessage, aHandle ); |
|
383 } |
|
384 else // continue creating new html attachment |
|
385 { |
|
386 // create new html attachment |
|
387 RFile newHtmlFile; |
|
388 HBufC* newHtmlFileNameBuf = HBufC::NewLC( KPathNameLength ); |
|
389 TPtr newHtmlFileNamePtr = newHtmlFileNameBuf->Des(); |
|
390 aHandle.Name( newHtmlFileNamePtr ); |
|
391 pathNamePtr.Append( newHtmlFileNamePtr ); |
|
392 CleanupStack::PopAndDestroy( newHtmlFileNameBuf ); |
|
393 |
|
394 TInt openResult = newHtmlFile.Replace( fs, pathNamePtr, EFileWrite ); |
|
395 CleanupClosePushL( newHtmlFile ); |
|
396 if( openResult >= KErrNone ) |
|
397 { |
|
398 TInt writeResult = newHtmlFile.Write( 0, htmlContentPtr ); |
|
399 if( writeResult >= KErrNone ) |
|
400 { |
|
401 AddHtmlFileAttachmentL( aMessage, newHtmlFile ); |
|
402 } |
|
403 else // else use original html file |
|
404 { |
|
405 AddHtmlFileAttachmentL( aMessage, aHandle ); |
|
406 } |
|
407 } |
|
408 CleanupStack::PopAndDestroy( &newHtmlFile ); |
|
409 } |
|
410 CleanupStack::PopAndDestroy( pathNameBuf ); |
|
411 } |
|
412 else // charset found, use original html file |
|
413 { |
|
414 AddHtmlFileAttachmentL( aMessage, aHandle ); |
|
415 } |
|
416 CleanupStack::PopAndDestroy( 2, charsetBuf ); // htmlContentBuf |
|
417 } |
|
418 |
|
419 |
|
420 // End of File |