|
1 /* |
|
2 * Copyright (c) 2004-2005 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 /** @file |
|
19 @internalComponent */ |
|
20 |
|
21 #include "ImageDisplayResolvrUtils.h" |
|
22 |
|
23 // |
|
24 // COpaqueDataParse |
|
25 // Class for reading and processing opaque data from the ECOM resource file |
|
26 // We store this as follows: |
|
27 // Version (1 byte) |
|
28 // flags (2 bytes) |
|
29 // Main Uid (4 bytes) |
|
30 // Sub Uid (4 bytes) |
|
31 // Number extensions (1 byte) |
|
32 // { ".XXX" \r } (x number extensions) |
|
33 // Number mime types (1 byte) |
|
34 // [ "mimetype" \r ] (for each mimetype) |
|
35 // |
|
36 |
|
37 // Note to avoid overhead, we only read the extensions and mime types on demand |
|
38 // Until EnsureExtnsReadL() is called, ExtnsCount() and Extn is invalid. Similarly |
|
39 // for mime types. |
|
40 |
|
41 COpaqueDataParse* COpaqueDataParse::NewL(const TDesC8& aOpaqueData) |
|
42 { |
|
43 COpaqueDataParse* result = COpaqueDataParse::NewLC(aOpaqueData); |
|
44 CleanupStack::Pop(result); |
|
45 return result; |
|
46 } |
|
47 |
|
48 COpaqueDataParse* COpaqueDataParse::NewLC(const TDesC8& aOpaqueData) |
|
49 { |
|
50 COpaqueDataParse* result = new (ELeave) COpaqueDataParse(aOpaqueData); |
|
51 CleanupStack::PushL(result); |
|
52 result->ConstructL(); |
|
53 return result; |
|
54 } |
|
55 |
|
56 COpaqueDataParse::COpaqueDataParse(const TDesC8& aOpaqueData): |
|
57 iOpaqueData(aOpaqueData) |
|
58 { |
|
59 } |
|
60 |
|
61 void COpaqueDataParse::ConstructL() |
|
62 { |
|
63 ReadVersion(); |
|
64 if (iVersion < KIclPluginFrameworkVersionOne || |
|
65 iVersion > KIclPluginFrameworkVersionMax) |
|
66 User::Leave(KErrNotSupported); |
|
67 ReadFlags(); |
|
68 ReadUids(); |
|
69 } |
|
70 |
|
71 COpaqueDataParse::~COpaqueDataParse() |
|
72 { |
|
73 iArray.Close(); |
|
74 } |
|
75 |
|
76 // Extract the Version number |
|
77 void COpaqueDataParse::ReadVersion() |
|
78 { |
|
79 ASSERT(iState<=EVersionProcessed); // should only call this on construction |
|
80 ASSERT(iOpaqueData.Length() >= KIndexForVersion + 1); |
|
81 //The version is one byte |
|
82 iVersion = iOpaqueData[KIndexForVersion]; |
|
83 iState = EVersionProcessed; |
|
84 } |
|
85 |
|
86 |
|
87 // Extract the (optional) flags |
|
88 void COpaqueDataParse::ReadFlags() |
|
89 { |
|
90 ASSERT(iState<EFlagsProcessed); |
|
91 |
|
92 switch(iVersion) |
|
93 { |
|
94 case KIclPluginFrameworkVersionOne: |
|
95 ASSERT(iOpaqueData.Length() >= KIndexForFlags + 2); // opaque data not valid otherwise |
|
96 iFlags = (iOpaqueData[KIndexForFlags+0] << 8) | (iOpaqueData[KIndexForFlags+1]); |
|
97 iLenOfFlags = 2; |
|
98 break; |
|
99 } |
|
100 |
|
101 iStartOfUids = 1 + iLenOfFlags; |
|
102 iStartOfNumberOfExtns = 1 + iLenOfFlags + 8; |
|
103 iState = EFlagsProcessed; |
|
104 } |
|
105 |
|
106 // Extract the two Uids |
|
107 void COpaqueDataParse::ReadUids() |
|
108 { |
|
109 ASSERT(iState<EUidsProcessed); |
|
110 ASSERT(iOpaqueData.Length() >= iStartOfUids + 4); // opaque data not valid otherwise |
|
111 // A given OpaqueData should either contain one Uid, in 4 bytes, |
|
112 // highest to lowest, with an implied second Uid set to KNullUid, |
|
113 // or two consecutive Uids, in 4 bytes each - 8 in all - main type followed by sub-type. |
|
114 // The 8 bytes may be followed, for basic types, by info on the file extensions |
|
115 // and MIME typesassociated with this plugin but this info is ignored here. |
|
116 iImageTypeUid.iUid = (iOpaqueData[iStartOfUids] << 24) | (iOpaqueData[iStartOfUids+1] << 16) | (iOpaqueData[iStartOfUids+2] << 8) | (iOpaqueData[iStartOfUids+3]); |
|
117 if (iOpaqueData.Length() == iStartOfUids + 4) |
|
118 { |
|
119 iImageSubTypeUid = KNullUid; |
|
120 } |
|
121 else |
|
122 { |
|
123 ASSERT(iOpaqueData.Length() >= iStartOfUids + 8); |
|
124 iImageSubTypeUid.iUid = (iOpaqueData[iStartOfUids+4] << 24) | (iOpaqueData[iStartOfUids+5] << 16) + (iOpaqueData[iStartOfUids+6] << 8) + (iOpaqueData[iStartOfUids+7]); |
|
125 } |
|
126 iState = EUidsProcessed; |
|
127 } |
|
128 |
|
129 // read in the Extns from the opaque data |
|
130 void COpaqueDataParse::EnsureExtnsReadL() |
|
131 { |
|
132 // if we've already read in the extensions, is a NOP |
|
133 if (iState>=EExtnsProcessed) |
|
134 { |
|
135 return; |
|
136 } |
|
137 |
|
138 ASSERT(iArray.Count()==0); // assume nothing in there at the moment |
|
139 |
|
140 iExtnCount = iOpaqueData[iStartOfNumberOfExtns]; |
|
141 TInt pos = iStartOfNumberOfExtns+1; // start just after the extn count byte |
|
142 |
|
143 for (TInt index=0; index<iExtnCount; index++) |
|
144 { |
|
145 TPtrC8 restOfData = iOpaqueData.Mid(pos); |
|
146 TInt endPos = restOfData.Locate(TChar('\r')); // \r is used to terminate each suffix |
|
147 ASSERT(endPos != KErrNotFound); // if we have -1, would not have found the CR |
|
148 TPtrC8 extn = restOfData.Left(endPos); |
|
149 User::LeaveIfError(iArray.Append(extn)); |
|
150 pos += endPos + 1; // skip over the CR |
|
151 } |
|
152 iStartOfMimeTypes = pos; |
|
153 iState = EExtnsProcessed; |
|
154 ASSERT(iArray.Count()==iExtnCount); |
|
155 } |
|
156 |
|
157 void COpaqueDataParse::EnsureMIMETypesReadL() |
|
158 { |
|
159 // if we've already read in the mime types, is a NOP |
|
160 if (iState>=EMIMETypesProcessed) |
|
161 return; |
|
162 |
|
163 EnsureExtnsReadL(); |
|
164 ASSERT(iState==EExtnsProcessed); |
|
165 |
|
166 TInt pos = iStartOfMimeTypes; |
|
167 const TInt numMimeTypes = iOpaqueData[pos]; |
|
168 pos += 1; |
|
169 |
|
170 for (TInt index=0; index<numMimeTypes; index++) |
|
171 { |
|
172 TPtrC8 restOfData = iOpaqueData.Mid(pos); |
|
173 TInt endPos = restOfData.Locate(TChar('\r')); // \r is used to terminate each suffix |
|
174 ASSERT(endPos != KErrNotFound); // if we have -1, would not have found the CR |
|
175 TPtrC8 mimeType = restOfData.Left(endPos); |
|
176 User::LeaveIfError(iArray.Append(mimeType)); |
|
177 pos += endPos + 1; // skip over the CR |
|
178 } |
|
179 iState = EMIMETypesProcessed; |
|
180 ASSERT(iArray.Count()==iExtnCount+numMimeTypes); |
|
181 } |
|
182 |
|
183 TBool COpaqueDataParse::CompareMIMETypes(const TDesC8& aMimeType1, const TDesC8& aMimeType2) |
|
184 { |
|
185 if (aMimeType1.Length() != aMimeType2.Length()) |
|
186 { |
|
187 return EFalse; |
|
188 } |
|
189 return aMimeType1.CompareF(aMimeType2)==0; // true if exactly the same, if we ignore the case |
|
190 } |
|
191 |
|
192 TBool COpaqueDataParse::CompareFileSuffixL(const TDesC& aFileSuffix1, const TDesC8& aFileSuffix2) |
|
193 { |
|
194 //First do a quick compare |
|
195 if (aFileSuffix1.Length() != aFileSuffix2.Length()) |
|
196 { |
|
197 return EFalse; |
|
198 } |
|
199 |
|
200 //Change aFileSuffix2 from TDesC8 to TDesC |
|
201 HBufC* fileSuffix = HBufC::NewL(aFileSuffix2.Length()); //Not on CleanupStack since nothing can leave |
|
202 TPtr fileSuffixPtr(fileSuffix->Des()); |
|
203 fileSuffixPtr.Copy(aFileSuffix2); |
|
204 |
|
205 const TBool result = aFileSuffix1.CompareF(*fileSuffix)==0; // true if exactly the same, if we ignore the case |
|
206 delete fileSuffix; |
|
207 |
|
208 return result; |
|
209 } |
|
210 |
|
211 /* |
|
212 * |
|
213 * Searches for a match of aPluginString in aClientString. Match returns ETrue |
|
214 * if aPluginString is found within aImplementationType according to the |
|
215 * following rules: |
|
216 * 1) All bytes in aClientString are exact but instances of '?' (0x3F) in |
|
217 * aPluginString are treated as wildcards - matching any byte value at that |
|
218 * position in aClientString. |
|
219 * 2) If aClientString is longer than aPluginString, ignore any excess bytes. |
|
220 * 3) aClientString is treated as a single descriptor - the '||' delimiters |
|
221 * are not recognised. |
|
222 * 4) ETrue is returned if aPluginString matches the start of aClientString |
|
223 * exactly, subject to wildcards. |
|
224 * 5) aBytesMatched will be filled in with the number of non-wildcard bytes in |
|
225 * aPluginString. This is used to rank matches. |
|
226 * |
|
227 * @param "const TDesC8& aClientString" |
|
228 * The string from the client to search for a match |
|
229 * @param "const TDesC8& aPluginString" |
|
230 * The data to search for from the plugin |
|
231 * @param "TInt& aBytesMatched" |
|
232 * The number of non-wildcard bytes matched, or "1" if the match pattern contains only "?" |
|
233 i.e. should match any data |
|
234 * @return "TBool" |
|
235 * ETrue if a match was found, EFalse otherwise |
|
236 */ |
|
237 TBool CImageDisplayResolverUtils::Match(const TDesC8& aClientString, const TDesC8& aPluginString, TInt& aBytesMatched) |
|
238 { |
|
239 TInt pluginStringLength = aPluginString.Length(); |
|
240 aBytesMatched = 0; |
|
241 while (pluginStringLength>1 && (aPluginString[pluginStringLength - 1] == '?')) |
|
242 { // Clip extraneous '?' wildcards off the end of the plugin match string |
|
243 pluginStringLength--; |
|
244 } |
|
245 if (pluginStringLength == 0) |
|
246 { // Plugin has no match string |
|
247 return EFalse; |
|
248 } |
|
249 if (aClientString.Length() < pluginStringLength) |
|
250 { // Client string too short - can't match |
|
251 return EFalse; |
|
252 } |
|
253 // Now let's run along the string |
|
254 for (TInt index = 0; index < pluginStringLength; index++) |
|
255 { |
|
256 const TUint8 pluginChar = aPluginString[index]; |
|
257 if (pluginChar=='?') // just ignore a wildchar |
|
258 { |
|
259 continue; |
|
260 } |
|
261 if (aClientString[index] != pluginChar) |
|
262 { |
|
263 return EFalse; |
|
264 } |
|
265 // else we've matched expected byte, so keep going |
|
266 aBytesMatched += 1; |
|
267 } |
|
268 aBytesMatched += (aPluginString[0]=='?' && pluginStringLength==1); |
|
269 ASSERT(aBytesMatched>0); // if we get this far, must have matched something - since we no match string can't be empty |
|
270 return ETrue; |
|
271 } |
|
272 |