|
1 /* |
|
2 * Copyright (c) 2008-2009 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 the License "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: |
|
15 * This file implements a package file parser for the Reference Installer. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "sifrefpkgparser.h" |
|
21 #include <f32file.h> |
|
22 #include "usiflog.h" |
|
23 #include <usif/usiferror.h> |
|
24 |
|
25 using namespace Usif; |
|
26 |
|
27 /** |
|
28 A set of helper functions for the parser. |
|
29 */ |
|
30 namespace |
|
31 { |
|
32 _LIT8(KTxtCRLF, "\r\n"); |
|
33 _LIT8(KTxtLanguages, "Languages"); |
|
34 _LIT8(KTxtComponentName, "ComponentName"); |
|
35 _LIT8(KTxtComponentVendor, "ComponentVendor"); |
|
36 _LIT8(KTxtComponentVersion, "ComponentVersion"); |
|
37 _LIT8(KTxtFile, "File"); |
|
38 |
|
39 /** Maximum length of a value string in a package file */ |
|
40 const TInt KMaxValueLength = 0xFF; |
|
41 |
|
42 void SplitLineL(const TPtrC8& aLine, TPtrC8& aName, TPtrC8& aValue) |
|
43 { |
|
44 const TInt colon = aLine.Locate(':'); |
|
45 if (colon == KErrNotFound) |
|
46 { |
|
47 DEBUG_PRINTF2(_L8("Missing colon in line: %S"), &aLine); |
|
48 User::Leave(KErrCorrupt); |
|
49 } |
|
50 |
|
51 aName.Set(aLine.Left(colon)); |
|
52 aValue.Set(aLine.Mid(colon+1)); |
|
53 } |
|
54 |
|
55 void SplitValuesL(const TPtrC8& aValues, RCHBufCArray& aValueArray) |
|
56 { |
|
57 TPtrC8 values(aValues); |
|
58 while (values.Size() > 0) |
|
59 { |
|
60 TInt quot = values.Locate('"'); |
|
61 if (quot == KErrNotFound) |
|
62 { |
|
63 return; |
|
64 } |
|
65 values.Set(values.Mid(quot+1)); |
|
66 quot = values.Locate('"'); |
|
67 if (quot == KErrNotFound) |
|
68 { |
|
69 DEBUG_PRINTF2(_L8("Missing closing quotation mark in line: %S"), &aValues); |
|
70 User::Leave(KErrCorrupt); |
|
71 } |
|
72 TPtrC8 token(values.Left(quot)); |
|
73 |
|
74 HBufC* value = HBufC::NewLC(KMaxValueLength); |
|
75 TPtr valPtr(value->Des()); |
|
76 valPtr.Copy(token); |
|
77 aValueArray.AppendL(value); |
|
78 CleanupStack::Pop(value); |
|
79 |
|
80 values.Set(values.Mid(quot+1)); |
|
81 } |
|
82 } |
|
83 |
|
84 void ParseComponentVersionL(const TPtrC8& aStringVersion, TVersion& aVersion) |
|
85 { |
|
86 // Check if already defined |
|
87 if (aVersion.iMajor || aVersion.iMinor || aVersion.iBuild) |
|
88 { |
|
89 DEBUG_PRINTF(_L8("Multiple definition of Component Version")); |
|
90 User::Leave(KErrCorrupt); |
|
91 } |
|
92 |
|
93 // Convert the major version number of Component Version |
|
94 TLex8 lex(aStringVersion); |
|
95 lex.SkipSpace(); |
|
96 TInt err = lex.Val(aVersion.iMajor); |
|
97 if (err != KErrNone) |
|
98 { |
|
99 DEBUG_PRINTF(_L8("Failed parsing the major version number of Component Version")); |
|
100 User::LeaveIfError(err); |
|
101 } |
|
102 lex.Inc(); |
|
103 |
|
104 // Convert the minor version number of Component Version |
|
105 err = lex.Val(aVersion.iMinor); |
|
106 if (err != KErrNone) |
|
107 { |
|
108 DEBUG_PRINTF(_L8("Failed parsing the minor version number of Component Version")); |
|
109 User::LeaveIfError(err); |
|
110 } |
|
111 lex.Inc(); |
|
112 |
|
113 // Convert the build version number of Component Version |
|
114 err = lex.Val(aVersion.iBuild); |
|
115 if (err != KErrNone) |
|
116 { |
|
117 DEBUG_PRINTF(_L8("Failed parsing the build version number of Component Version")); |
|
118 User::LeaveIfError(err); |
|
119 } |
|
120 } |
|
121 |
|
122 TLanguage LanguageMapL(TDesC& aLanguage) |
|
123 { |
|
124 if (aLanguage == _L("EN")) |
|
125 { |
|
126 return ELangEnglish; |
|
127 } |
|
128 else if (aLanguage == _L("HU")) |
|
129 { |
|
130 return ELangHungarian; |
|
131 } |
|
132 else if (aLanguage == _L("PL")) |
|
133 { |
|
134 return ELangPolish; |
|
135 } |
|
136 |
|
137 DEBUG_PRINTF2(_L8("Language %S is not supported by this Reference Installer"), &aLanguage); |
|
138 User::Leave(KErrSifUnsupportedLanguage); |
|
139 return ELangNone;// Suppress warning |
|
140 } |
|
141 } |
|
142 |
|
143 CSifRefPkgParser* CSifRefPkgParser::NewL(const TDesC& aFileName) |
|
144 { |
|
145 CSifRefPkgParser* self = new (ELeave) CSifRefPkgParser; |
|
146 CleanupStack::PushL(self); |
|
147 self->ParseL(aFileName); |
|
148 CleanupStack::Pop(self); |
|
149 return self; |
|
150 } |
|
151 |
|
152 CSifRefPkgParser::CSifRefPkgParser(): iVersion(0, 0, 0) |
|
153 { |
|
154 } |
|
155 |
|
156 CSifRefPkgParser::~CSifRefPkgParser() |
|
157 { |
|
158 iLanguages.Close(); |
|
159 iComponentNames.Close(); |
|
160 iVendorNames.Close(); |
|
161 iFiles.Close(); |
|
162 } |
|
163 |
|
164 const RLanguageArray& CSifRefPkgParser::Languages() const |
|
165 { |
|
166 return iLanguages; |
|
167 } |
|
168 |
|
169 const RCHBufCArray& CSifRefPkgParser::ComponentNames() const |
|
170 { |
|
171 return iComponentNames; |
|
172 } |
|
173 |
|
174 const RCHBufCArray& CSifRefPkgParser::VendorNames() const |
|
175 { |
|
176 return iVendorNames; |
|
177 } |
|
178 |
|
179 const TVersion& CSifRefPkgParser::Version() const |
|
180 { |
|
181 return iVersion; |
|
182 } |
|
183 |
|
184 const RCHBufCArray& CSifRefPkgParser::Files() const |
|
185 { |
|
186 return iFiles; |
|
187 } |
|
188 |
|
189 void CSifRefPkgParser::ParseL(const TDesC& aFileName) |
|
190 { |
|
191 RFs fs; |
|
192 RFile file; |
|
193 User::LeaveIfError(fs.Connect()); |
|
194 CleanupClosePushL(fs); |
|
195 TInt err = file.Open(fs, aFileName, EFileShareReadersOnly); |
|
196 if (err != KErrNone) |
|
197 { |
|
198 DEBUG_PRINTF3(_L8("Failed to open file: %S with error: %d"), &aFileName, err); |
|
199 User::Leave(err); |
|
200 } |
|
201 CleanupClosePushL(file); |
|
202 |
|
203 ParseL(file); |
|
204 |
|
205 CleanupStack::PopAndDestroy(2, &fs); |
|
206 } |
|
207 |
|
208 void CSifRefPkgParser::ParseL(RFile& aFileHandle) |
|
209 { |
|
210 // Read the file into the buffer |
|
211 TInt fileSize = 0; |
|
212 User::LeaveIfError(aFileHandle.Size(fileSize)); |
|
213 HBufC8* buffer = HBufC8::NewLC(fileSize); |
|
214 TPtr8 bufPtr = buffer->Des(); |
|
215 TInt err = aFileHandle.Read(bufPtr); |
|
216 if (err != KErrNone) |
|
217 { |
|
218 DEBUG_PRINTF2(_L8("Failed to read reference package file with err %d"), err); |
|
219 User::LeaveIfError(err); |
|
220 } |
|
221 |
|
222 // Iterate over the lines |
|
223 TPtrC8 lines(*buffer); |
|
224 const TInt crlfLen = TPtrC8(KTxtCRLF).Size(); |
|
225 while (lines.Size() > 0) |
|
226 { |
|
227 // Find next line |
|
228 TPtrC8 line; |
|
229 const TInt crlfPos = lines.Find(KTxtCRLF); |
|
230 if (crlfPos != KErrNotFound) |
|
231 { |
|
232 line.Set(lines.Left(crlfPos)); |
|
233 lines.Set(lines.Mid(crlfPos+crlfLen)); |
|
234 } |
|
235 else |
|
236 { |
|
237 if (lines.Size() > 0) |
|
238 { |
|
239 line.Set(lines); |
|
240 lines.Set(TPtrC8()); |
|
241 } |
|
242 } |
|
243 |
|
244 // Split the line into a pair of the name of a tag and its value |
|
245 TPtrC8 name, value; |
|
246 SplitLineL(line, name, value); |
|
247 |
|
248 // Hand over the pair to recognition |
|
249 LineHandlerL(name, value); |
|
250 } |
|
251 CleanupStack::PopAndDestroy(buffer); |
|
252 |
|
253 // Check whether the file we have just parsed wasn't corrupted |
|
254 CheckInvariantL(); |
|
255 } |
|
256 |
|
257 void CSifRefPkgParser::LineHandlerL(const TPtrC8& aName, const TPtrC8& aValue) |
|
258 { |
|
259 if (aName == KTxtLanguages) |
|
260 { |
|
261 if (iLanguages.Count() > 0) |
|
262 { |
|
263 DEBUG_PRINTF(_L8("Multiple definition of languages")); |
|
264 User::Leave(KErrCorrupt); |
|
265 } |
|
266 RCHBufCArray languages; |
|
267 CleanupClosePushL(languages); |
|
268 SplitValuesL(aValue, languages); |
|
269 const TInt count = languages.Count(); |
|
270 for (TInt i=0; i<count; ++i) |
|
271 { |
|
272 iLanguages.AppendL(LanguageMapL(*languages[i])); |
|
273 } |
|
274 CleanupStack::PopAndDestroy(&languages); |
|
275 } |
|
276 else if (aName == KTxtComponentName) |
|
277 { |
|
278 if (iComponentNames.Count() > 0) |
|
279 { |
|
280 DEBUG_PRINTF(_L8("Multiple definition of Component Name")); |
|
281 User::Leave(KErrCorrupt); |
|
282 } |
|
283 SplitValuesL(aValue, iComponentNames); |
|
284 } |
|
285 else if (aName == KTxtComponentVendor) |
|
286 { |
|
287 if (iVendorNames.Count() > 0) |
|
288 { |
|
289 DEBUG_PRINTF(_L8("Multiple definition of Component Vendor")); |
|
290 User::Leave(KErrCorrupt); |
|
291 } |
|
292 SplitValuesL(aValue, iVendorNames); |
|
293 } |
|
294 else if (aName == KTxtComponentVersion) |
|
295 { |
|
296 ParseComponentVersionL(aValue, iVersion); |
|
297 } |
|
298 else if (aName == KTxtFile) |
|
299 { |
|
300 HBufC* file = HBufC::NewLC(aValue.Size()); |
|
301 TPtr fileBuf = file->Des(); |
|
302 fileBuf.Copy(aValue); |
|
303 fileBuf.Trim(); |
|
304 iFiles.AppendL(file); |
|
305 CleanupStack::Pop(file); |
|
306 } |
|
307 else |
|
308 { |
|
309 DEBUG_PRINTF2(_L8("Failed due to unrecognized token: %S"), &aName); |
|
310 User::Leave(KErrCorrupt); |
|
311 } |
|
312 } |
|
313 |
|
314 TInt CSifRefPkgParser::GetLanguageIndex(TLanguage aLanguage) const |
|
315 { |
|
316 const TInt count = iLanguages.Count(); |
|
317 for (TInt i=0; i<count; ++i) |
|
318 { |
|
319 if (iLanguages[i] == aLanguage) |
|
320 { |
|
321 return i; |
|
322 } |
|
323 } |
|
324 return KErrNotFound; |
|
325 } |
|
326 |
|
327 void CSifRefPkgParser::CheckInvariantL() const |
|
328 { |
|
329 if (iVersion.iMajor == 0 && iVersion.iMinor == 0 && iVersion.iBuild == 0) |
|
330 { |
|
331 DEBUG_PRINTF(_L8("Version not specified!")); |
|
332 User::Leave(KErrCorrupt); |
|
333 } |
|
334 if (iLanguages.Count() == 0) |
|
335 { |
|
336 DEBUG_PRINTF(_L8("Language not specified!")); |
|
337 User::Leave(KErrCorrupt); |
|
338 } |
|
339 if (iLanguages.Count() != iComponentNames.Count()) |
|
340 { |
|
341 DEBUG_PRINTF(_L8("The number of languages and component names don't match!")); |
|
342 User::Leave(KErrCorrupt); |
|
343 } |
|
344 if (iLanguages.Count() != iVendorNames.Count()) |
|
345 { |
|
346 DEBUG_PRINTF(_L8("The number of languages and vendor names don't match!")); |
|
347 User::Leave(KErrCorrupt); |
|
348 } |
|
349 } |