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: CCSXHRuntimeIndexing class definition |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <pathinfo.h> |
|
20 #include <utf.h> |
|
21 #include <bautils.h> |
|
22 #include <eikenv.h> |
|
23 #include <aknnotedialog.h> // for CAknNoteDialog |
|
24 #include <aknnotewrappers.h> |
|
25 #include <SenXmlUtils.h> |
|
26 #include <SenXmlConstants.h> |
|
27 |
|
28 #include "CSXHRuntimeIndexing.h" |
|
29 #include "CSXHHtmlTOC1.h" |
|
30 #include "csxhconstants.h" |
|
31 |
|
32 // buffer length of Drive information in index file |
|
33 // |
|
34 const TInt KMaxDriveInfo = 100; |
|
35 |
|
36 CCSXHRuntimeIndexing::CCSXHRuntimeIndexing() |
|
37 { |
|
38 iCoeEnv = CCoeEnv::Static(); |
|
39 } |
|
40 |
|
41 CCSXHRuntimeIndexing::~CCSXHRuntimeIndexing() |
|
42 { |
|
43 delete iFullDirName; |
|
44 iFile.Close(); |
|
45 } |
|
46 |
|
47 CCSXHRuntimeIndexing* CCSXHRuntimeIndexing::NewL() |
|
48 { |
|
49 CCSXHRuntimeIndexing* self = new ( ELeave ) CCSXHRuntimeIndexing(); |
|
50 CleanupStack::PushL( self ); |
|
51 self->ConstructL(); |
|
52 CleanupStack::Pop( self ); |
|
53 return self; |
|
54 } |
|
55 |
|
56 void CCSXHRuntimeIndexing::ConstructL() |
|
57 { |
|
58 RFs& fileSession = iCoeEnv->FsSession(); |
|
59 iFullDirName = HBufC::NewL( KMaxFileName ); |
|
60 |
|
61 TFileName fullDirName; |
|
62 |
|
63 GetPrivatePath( fullDirName ); |
|
64 if ( !BaflUtils::PathExists( fileSession, fullDirName ) ) |
|
65 { |
|
66 fileSession.CreatePrivatePath( EDriveC ); |
|
67 } |
|
68 |
|
69 TInt len = fullDirName.Length(); |
|
70 TDriveList dirList; |
|
71 if( fileSession.DriveList( dirList ) == KErrNone ) |
|
72 { |
|
73 TDriveInfo info; |
|
74 TInt driveListLen = dirList.Length(); |
|
75 |
|
76 for ( TInt i = 0; i < driveListLen; i++ ) |
|
77 { |
|
78 // make separate folder for C/D/E/... drive |
|
79 // e.g. C:\\private\\10005234\\C\\ |
|
80 |
|
81 TInt err = fileSession.Drive( info, i ); |
|
82 if ( err == KErrNone && |
|
83 info.iType != EMediaNotPresent ) |
|
84 { |
|
85 TChar driveChar; |
|
86 RFs::DriveToChar( i, driveChar ); |
|
87 fullDirName.Append( driveChar ); |
|
88 fullDirName.Append( KFwdSlash ); |
|
89 fileSession.MkDir( fullDirName ); |
|
90 fullDirName.Delete( len, 3 ); |
|
91 } |
|
92 } |
|
93 |
|
94 } |
|
95 } |
|
96 |
|
97 TBool CCSXHRuntimeIndexing::IndexFileExistsL() |
|
98 { |
|
99 RFs& fileSession = iCoeEnv->FsSession(); |
|
100 TBuf<KMaxFileName> fileName; |
|
101 GetPrivatePath( fileName ); |
|
102 fileName.Append( _L("Z\\") ); |
|
103 AppendLocaleL( fileName ); |
|
104 fileName.Append( KMasterMetaFile ); |
|
105 |
|
106 // Now the dirName is C:\\private\\<app-uid>\\Z\\index.xml |
|
107 // check if it exists, if yes, runtime indexing must be launched before |
|
108 // since Z based Help content must be delivered with cell phone |
|
109 // |
|
110 return BaflUtils::FileExists( fileSession, fileName ); |
|
111 |
|
112 } |
|
113 |
|
114 void CCSXHRuntimeIndexing::BeginIndexFileL( const TChar& aDrive ) |
|
115 { |
|
116 RFs& fileSession = iCoeEnv->FsSession(); |
|
117 TPtr des = iFullDirName->Des(); |
|
118 iDriveLetter = aDrive; |
|
119 des.Zero(); |
|
120 GetPrivatePath( des ); |
|
121 des.Append( aDrive ); |
|
122 des.Append( KFwdSlash ); |
|
123 AppendLocaleL( des ); |
|
124 if ( !BaflUtils::PathExists( fileSession, des ) ) |
|
125 { |
|
126 // generate C:\\private\\<help-uid>\\<aDrive>\\ folder |
|
127 // |
|
128 fileSession.MkDir( des ); |
|
129 } |
|
130 |
|
131 // for temporary usage, once it's finished successfully, |
|
132 // rename to index.xml. otherwise, the old index file still exists. |
|
133 // |
|
134 des.Append( KMasterMetaTmpFile ); |
|
135 iFile.Replace( fileSession, des, EFileWrite ); |
|
136 |
|
137 HBufC8* driveInfo = HBufC8::NewLC( KMaxDriveInfo ); |
|
138 TPtr8 ptr = driveInfo->Des(); |
|
139 ptr.Append( KIndexXMLVesion ); |
|
140 ptr.Append( _L( "<collections drive=\"" ) ); |
|
141 ptr.Append( aDrive); |
|
142 ptr.Append( _L( "\">\r\n" ) ); |
|
143 iFile.Write( *driveInfo ); |
|
144 CleanupStack::PopAndDestroy( driveInfo ); |
|
145 } |
|
146 |
|
147 void CCSXHRuntimeIndexing::FinishAndCloseIndexFileL() |
|
148 { |
|
149 RFs& fileSession = iCoeEnv->FsSession(); |
|
150 iFile.Write( KIndexCollectEnd ); |
|
151 iFile.Close(); |
|
152 |
|
153 TTime time; |
|
154 // Replace the index.xml with temporary file, in case it fails, will have no impact |
|
155 // the original index.xml, it's a backup solution |
|
156 // |
|
157 TBuf<KMaxFileName> newName; |
|
158 TInt err = KErrNone; |
|
159 newName.Copy( *iFullDirName ); |
|
160 TInt pos = newName.LocateReverse( TChar('\\') ); |
|
161 newName.Delete( pos + 1, newName.Length() - pos - 1 ); // remove the temp name |
|
162 newName.Append( KMasterMetaFile ); // and append index.xml |
|
163 |
|
164 err = fileSession.Replace( *iFullDirName, newName ); |
|
165 |
|
166 if ( err == KErrNone ) |
|
167 { |
|
168 // set the modified date of master index.xml |
|
169 // to be the same with related help content folder |
|
170 // e.g. C:\\resource\\xhtml\\01\\ modified time is 2009.3.1 |
|
171 // C:\\private\\10005234\\C\\01\\index.xml will be 2009.3.1 |
|
172 // this will make sure once help content folder changed, index.xml can be |
|
173 // determined to change. |
|
174 TBuf<KMaxFileName> helpDir; |
|
175 helpDir.Append( iDriveLetter ); |
|
176 helpDir.Append( KInstallPath ); |
|
177 // append locale information |
|
178 AppendLocaleL( helpDir ); |
|
179 |
|
180 fileSession.Modified( helpDir, time ); |
|
181 err = fileSession.SetModified( newName, time ); |
|
182 |
|
183 } |
|
184 |
|
185 } |
|
186 |
|
187 void CCSXHRuntimeIndexing::RuntimeGenerateIndexL( const CCSXHHtmlTOC1& aToc1, const TDesC& aFeature ) |
|
188 { |
|
189 // Form into an entry, like |
|
190 // <collection FeatureID="-1" id="0x10005951" navtitle="Bluetooth"></collection> |
|
191 HBufC8* appName = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aToc1.GetName() ); |
|
192 CleanupStack::PushL(appName); |
|
193 TRAPD( err, SenXmlUtils::LeaveOnXmlEscapesL( *appName ) ); |
|
194 TInt length = KMaxIndexEntryExclude; |
|
195 TBuf8<KMaxUidLength> buffUid; |
|
196 |
|
197 buffUid.Append( KHexPrefix ); |
|
198 buffUid.AppendNumFixedWidth( aToc1.GetAppUid().iUid, EHex, 8 ); |
|
199 length += appName->Length(); |
|
200 length += aFeature.Length(); |
|
201 HBufC8* entry = HBufC8::NewLC( length ); |
|
202 TPtr8 des = entry->Des(); |
|
203 // Append entry tag |
|
204 des.Append( KIndexXMLEntryBegin ); |
|
205 // Append feature id attribute "FeatureID" |
|
206 des.Append( KAppFeatureIDTag ); |
|
207 des.Append( KIndexQuoteBegin ); |
|
208 // Append feature id |
|
209 des.Append( aFeature ); |
|
210 des.Append( KIndexQuoteEnd ); |
|
211 // Append app id attribute "id" |
|
212 des.Append( KMasterCollection_idTag ); |
|
213 des.Append( KIndexQuoteBegin ); |
|
214 // Append app id |
|
215 des.Append( buffUid ); |
|
216 des.Append( KIndexQuoteEnd ); |
|
217 // Append app priority |
|
218 des.Append( KPriorityTag ); |
|
219 des.Append( KIndexQuoteBegin ); |
|
220 des.AppendNum(aToc1.Priority()); |
|
221 des.Append( KIndexQuoteEnd ); |
|
222 // Append app name attribut "navtitle" |
|
223 des.Append( KTOC2NameTag ); |
|
224 des.Append( KIndexQuoteBegin ); |
|
225 if ( err == KErrSenInvalidCharacters ) |
|
226 { |
|
227 // special handling to the XML-Escaped char |
|
228 HBufC8* newElement = SenXmlUtils::EncodeHttpCharactersLC( *appName ); |
|
229 des.Append( *newElement ); |
|
230 CleanupStack::PopAndDestroy( newElement ); |
|
231 } |
|
232 else |
|
233 { |
|
234 des.Append( *appName ); |
|
235 } |
|
236 |
|
237 des.Append( KIndexXMLEntryEnd ); |
|
238 iFile.Write( *entry ); |
|
239 |
|
240 CleanupStack::PopAndDestroy( entry ); |
|
241 CleanupStack::PopAndDestroy( appName ); |
|
242 |
|
243 } |
|
244 |
|
245 void CCSXHRuntimeIndexing::GetPrivatePath( TDes& aName ) |
|
246 { |
|
247 RFs& fileSession = iCoeEnv->FsSession(); |
|
248 TBuf<KMaxFileName> privatePath; |
|
249 TChar drive; |
|
250 RFs::DriveToChar( EDriveC, drive ); |
|
251 |
|
252 fileSession.PrivatePath( privatePath ); |
|
253 aName.Append( drive ); |
|
254 aName.Append( TChar(':') ); |
|
255 aName.Append( privatePath ); |
|
256 } |
|
257 |
|
258 void CCSXHRuntimeIndexing::AppendLocaleL( TDes& aDir ) |
|
259 { |
|
260 RFs& fileSession = iCoeEnv->FsSession(); |
|
261 RArray<TLanguage> langs; |
|
262 BaflUtils::GetDowngradePathL( fileSession, User::Language(), langs ); |
|
263 TInt len = aDir.Length(); |
|
264 |
|
265 if ( len > 0 ) |
|
266 { |
|
267 TLanguage lang = langs[0]; |
|
268 if(lang < 10) |
|
269 { |
|
270 aDir.AppendNumFixedWidth( lang, EDecimal,2 ); |
|
271 } |
|
272 else |
|
273 { |
|
274 aDir.AppendNum( lang ); |
|
275 } |
|
276 } |
|
277 else |
|
278 { |
|
279 // rarely case, if no current language, use English |
|
280 aDir.Append( _L("01") ); |
|
281 } |
|
282 |
|
283 aDir.Append( KFwdSlash ); |
|
284 langs.Reset(); |
|
285 } |
|
286 |
|
287 void CCSXHRuntimeIndexing::DeleteIndexFileL( const TChar& aDrive ) |
|
288 { |
|
289 RFs& fileSession = iCoeEnv->FsSession(); |
|
290 TBuf<KMaxFileName> des; |
|
291 GetPrivatePath( des ); |
|
292 des.Append( aDrive ); |
|
293 des.Append( KFwdSlash ); |
|
294 AppendLocaleL( des ); |
|
295 // C:\\private\\<app-uid>\\<drive letter>\\<language-id>\\index.xml |
|
296 des.Append( KMasterMetaFile ); |
|
297 |
|
298 if ( BaflUtils::FileExists( fileSession, des ) ) |
|
299 { |
|
300 fileSession.Delete( des ); |
|
301 } |
|
302 |
|
303 } |
|
304 |
|
305 TInt CCSXHRuntimeIndexing::CheckDirChangeL( const TChar& aDrive ) |
|
306 { |
|
307 RFs& fsSession = iCoeEnv->FsSession(); |
|
308 |
|
309 // Begin to search help content folder to see if there are date modify |
|
310 // meanwhile, compare to the related folder in private directory |
|
311 TFileName dirName; |
|
312 dirName.Append( aDrive ); |
|
313 dirName.Append( KInstallPath ); |
|
314 |
|
315 // Begin to append locale, note this will append current locale, |
|
316 // thru which, app can determine if it's caused by user changed locales |
|
317 AppendLocaleL( dirName ); |
|
318 |
|
319 TTime dirModified(0); |
|
320 TTime fileModified(0); |
|
321 |
|
322 if ( BaflUtils::PathExists( fsSession, dirName ) ) |
|
323 { |
|
324 // here is modified time of help content folder |
|
325 fsSession.Modified( dirName, dirModified ); |
|
326 } |
|
327 else |
|
328 { |
|
329 // fast return, no need to go on checking |
|
330 return KNoDirExist; |
|
331 } |
|
332 |
|
333 TFileName filename; |
|
334 GetPrivatePath( filename ); |
|
335 filename.Append( aDrive ); |
|
336 filename.Append( KFwdSlash ); |
|
337 AppendLocaleL( filename ); |
|
338 filename.Append( KMasterMetaFile ); |
|
339 |
|
340 if ( BaflUtils::FileExists( fsSession, filename ) ) |
|
341 { |
|
342 // here is modified time of index.xml |
|
343 // |
|
344 fsSession.Modified( filename, fileModified ); |
|
345 } |
|
346 else |
|
347 { |
|
348 return KNoIndexExist; |
|
349 } |
|
350 |
|
351 if ( fileModified != dirModified ) |
|
352 { |
|
353 // folder changed, return it |
|
354 TInt ret = KErrNotFound; |
|
355 RFs::CharToDrive( aDrive, ret ); |
|
356 return ret; |
|
357 } |
|
358 |
|
359 return KNoChange; |
|
360 } |
|