|
1 /* |
|
2 * Copyright (c) 2008 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 |
|
19 // INCLUDE FILES |
|
20 #include "cstsuri.h" |
|
21 #include "stsapduconstants.h" |
|
22 #include "logger.h" |
|
23 |
|
24 namespace java |
|
25 { |
|
26 namespace satsa |
|
27 { |
|
28 |
|
29 // CONSTANTS |
|
30 const TInt KSTSAIDMaxLength = 16; |
|
31 const TInt KSTSAIDMinLength = 5; |
|
32 |
|
33 const TInt KSTSMinURILength = 15;//(SAT uri without slot number) |
|
34 const TInt KSTSMaxURILength = 61;//(AID uri with slot and maximum AID) |
|
35 |
|
36 const TUint8 KSTSErrNotAHexNumber = 255; |
|
37 |
|
38 const TInt KSTSApduUriPrefixLength = 5; // "apdu:" takes 5 characters |
|
39 |
|
40 const TUint8 KSTSApduUriSlotTargetSeparator = ';'; |
|
41 const TUint8 KSTSApduUriAIDSeparator = '.'; |
|
42 const TUint8 KSTSSmallA = 'a'; |
|
43 const TUint8 KSTSBigA = 'A'; |
|
44 const TInt KSTSValueOfHexA = 0x0A; |
|
45 const TInt KSTSMaxHexValue = 0x0F; |
|
46 const TInt KSTSLengthOfSingleHexDigitInBits = 4; |
|
47 |
|
48 _LIT(KSTSUriTargetPrefix, "target="); |
|
49 _LIT(KSTSUriTargetSAT, "SAT"); |
|
50 |
|
51 // ============================ MEMBER FUNCTIONS =============================== |
|
52 |
|
53 |
|
54 CSTSURI::CSTSURI() |
|
55 { |
|
56 } |
|
57 |
|
58 void CSTSURI::ConstructL(const TDesC& aURIString) |
|
59 { |
|
60 LOG(ESATSA, EInfo, "CSTSURI::ConstructL++"); |
|
61 // does URI conform to the BNF syntax |
|
62 if (!CheckURIL(aURIString)) |
|
63 { |
|
64 ELOG(ESATSA, "CSTSURI::ConstructL: URI does not conform to BNF sntax"); |
|
65 // IllegalArgumentException |
|
66 User::Leave(KSTSErrIllegalArgument + KSTSErrIAInvalidParam); |
|
67 } |
|
68 } |
|
69 |
|
70 CSTSURI* CSTSURI::NewLC(const TDesC& aURIString) |
|
71 { |
|
72 LOG(ESATSA, EInfo, "CSTSURI::NewLC++"); |
|
73 CSTSURI* self = new(ELeave) CSTSURI(); |
|
74 CleanupStack::PushL(self); |
|
75 self->ConstructL(aURIString); |
|
76 LOG(ESATSA, EInfo, "CSTSURI::NewLC---"); |
|
77 return self; |
|
78 } |
|
79 |
|
80 CSTSURI::~CSTSURI() |
|
81 { |
|
82 delete iAID; |
|
83 } |
|
84 |
|
85 // ----------------------------------------------------------------------------- |
|
86 // CSTSURI::AID |
|
87 // Getter for AID value |
|
88 // ----------------------------------------------------------------------------- |
|
89 const TDesC8& CSTSURI::AID() const |
|
90 { |
|
91 return *iAID; |
|
92 } |
|
93 |
|
94 // ----------------------------------------------------------------------------- |
|
95 // CSTSURI::Slot |
|
96 // Getter for Slot |
|
97 // ----------------------------------------------------------------------------- |
|
98 TUint8 CSTSURI::Slot() const |
|
99 { |
|
100 return iSlot; |
|
101 } |
|
102 |
|
103 // ----------------------------------------------------------------------------- |
|
104 // CSTSURI::Type |
|
105 // Getter for URI type |
|
106 // ----------------------------------------------------------------------------- |
|
107 CSTSURI::TURIType CSTSURI::Type() const |
|
108 { |
|
109 return iURIType; |
|
110 } |
|
111 |
|
112 // ----------------------------------------------------------------------------- |
|
113 // CSTSURI::CheckURIL |
|
114 // Checks uri and saves needed information to member variables |
|
115 // |
|
116 /* |
|
117 URI can be for example: "apdu:0;target=A0.0.0.67.4.7.1F.3.2C.3" |
|
118 or "apdu:0;target=SAT" |
|
119 |
|
120 <APDU_connection_string>::= "apdu:"<targetAddress> |
|
121 <targetAddress> ::= [slot];target |
|
122 <slot> ::= smart card slot number. (optional. Hexadecimal |
|
123 number identifying the smart card slot. Default |
|
124 slot assumed if left empty) |
|
125 <target> ::= "target="<AID>|"SAT" |
|
126 <AID> ::= < 5 - 16 bytes > |
|
127 An AID (Application Identifier) uniquely |
|
128 identifies a smart card application. It is |
|
129 represented by 5 to 16 hexadecimal bytes where |
|
130 each byte value is seperated by a ".". |
|
131 */ |
|
132 // (other items were commented in a header). |
|
133 // ----------------------------------------------------------------------------- |
|
134 // |
|
135 TBool CSTSURI::CheckURIL(const TDesC& aURI) |
|
136 { |
|
137 LOG(ESATSA, EInfo, "CSTSURI::CheckURIL"); |
|
138 const TInt uriLength = aURI.Length(); |
|
139 LOG1(ESATSA, EInfo, "CSTSURI::CheckURIL:The lenghth of URI is %d", uriLength); |
|
140 // check length |
|
141 if ((uriLength > KSTSMaxURILength) || (uriLength < KSTSMinURILength)) |
|
142 { |
|
143 ELOG(ESATSA, "CSTSURI::CheckURIL:wrong length of the URI"); |
|
144 return EFalse; |
|
145 } |
|
146 // uri is now between 15 and 61 characters |
|
147 // Connector has already parsed the scheme part of the uri, |
|
148 // so we don't need to |
|
149 |
|
150 // "apdu:" takes 5 first characters |
|
151 TInt pos = KSTSApduUriPrefixLength; |
|
152 |
|
153 // parse slot number |
|
154 TChar slotChar = aURI[pos++]; |
|
155 TUint8 slotInt = 0; |
|
156 //if slot number is gived |
|
157 if (slotChar != KSTSApduUriSlotTargetSeparator) |
|
158 { |
|
159 //create ptr which starts from slot number position |
|
160 TPtrC16 slotAndRest(aURI.Ptr() + KSTSApduUriPrefixLength, uriLength |
|
161 - KSTSApduUriPrefixLength); |
|
162 TLex slotLex(slotAndRest); |
|
163 TInt slotNumber; |
|
164 //parse slot number |
|
165 TInt err = slotLex.Val(slotNumber); |
|
166 if (err != KErrNone) |
|
167 { |
|
168 return EFalse; |
|
169 } |
|
170 |
|
171 slotInt = static_cast<TUint8>(slotNumber); |
|
172 |
|
173 //calculate amount of slot number digits |
|
174 HBufC8* slotBuf = HBufC8::NewL(KSTSMaxURILength); |
|
175 slotBuf->Des().AppendNum(slotNumber); |
|
176 TInt slotNumberLength = slotBuf->Des().Length(); |
|
177 delete slotBuf; |
|
178 |
|
179 //if digits of slotnumber are more that one |
|
180 slotChar = aURI[pos + (slotNumberLength - 1)]; |
|
181 pos += slotNumberLength; |
|
182 } |
|
183 |
|
184 if (slotChar != KSTSApduUriSlotTargetSeparator) |
|
185 { |
|
186 return EFalse; |
|
187 } |
|
188 |
|
189 // next should be "target=" |
|
190 if (aURI.Find(KSTSUriTargetPrefix()) != pos) |
|
191 { |
|
192 return EFalse; |
|
193 } |
|
194 pos += KSTSUriTargetPrefix().Length(); |
|
195 |
|
196 TURIType uriType = EAID; |
|
197 TBufC8<KSTSAIDMaxLength> aid; |
|
198 |
|
199 if (aURI.Find(KSTSUriTargetSAT()) == pos) |
|
200 { |
|
201 if (uriLength != (pos + KSTSUriTargetSAT().Length())) |
|
202 { |
|
203 return EFalse; |
|
204 } |
|
205 uriType = ESAT; |
|
206 } |
|
207 else |
|
208 { |
|
209 TPtr8 aidDes = aid.Des(); |
|
210 if (!ParseAID(aURI, pos, aidDes)) |
|
211 { |
|
212 return EFalse; |
|
213 } |
|
214 } |
|
215 |
|
216 iSlot = slotInt; |
|
217 iURIType = uriType; |
|
218 |
|
219 //copies data to the member buffer |
|
220 iAID = aid.AllocL(); |
|
221 LOG(ESATSA, EInfo, "CSTSURI::CheckURIL---"); |
|
222 return ETrue; |
|
223 } |
|
224 |
|
225 // ----------------------------------------------------------------------------- |
|
226 // CSTSURI::GetHexValue |
|
227 // returns an integer value of given hex character |
|
228 // ----------------------------------------------------------------------------- |
|
229 // |
|
230 TUint8 CSTSURI::GetHexValue(const TChar& aDigit) |
|
231 { |
|
232 // if aDigit is 0-9, we can use TChar::GetNumericValue directly |
|
233 if (aDigit.IsDigit()) |
|
234 { |
|
235 return static_cast<TUint8>(aDigit.GetNumericValue()); |
|
236 } |
|
237 |
|
238 // if aDigit is not a hexadecimal digit, it is an error |
|
239 if (!(aDigit.IsHexDigit())) |
|
240 { |
|
241 return KSTSErrNotAHexNumber; |
|
242 } |
|
243 |
|
244 // otherwise, aDigit is a-f or A-F |
|
245 TChar charA = KSTSSmallA; |
|
246 if (aDigit.IsUpper()) |
|
247 { |
|
248 charA = KSTSBigA; |
|
249 } |
|
250 |
|
251 // we can get the value by calculating the difference of the character |
|
252 // and character 'a', and adding the value of hex digit 'a'. |
|
253 TUint8 retVal = static_cast<TUint8>((aDigit - charA) + KSTSValueOfHexA); |
|
254 return retVal; |
|
255 } |
|
256 |
|
257 // ----------------------------------------------------------------------------- |
|
258 // CSTSURI::ParseAID |
|
259 // parses AID from URI |
|
260 // ----------------------------------------------------------------------------- |
|
261 // |
|
262 TBool CSTSURI::ParseAID(const TDesC& aURI, TInt aPos, TDes8& aAID) |
|
263 { |
|
264 TInt aidLength = aAID.Length(); |
|
265 TInt aidMaxLength = aAID.MaxLength(); |
|
266 TInt uriLength = aURI.Length(); |
|
267 TInt pos = aPos; |
|
268 TAidParserState aidState = EFirstDigit; |
|
269 TUint8 aidDigit = 0; |
|
270 while (pos < uriLength) |
|
271 { |
|
272 TChar digit = aURI[pos++]; |
|
273 ParseAIDCharacter(digit, aidState, aidDigit); |
|
274 switch (aidState) |
|
275 { |
|
276 case EFirstDigit: |
|
277 { |
|
278 if (++aidLength > aidMaxLength) |
|
279 { |
|
280 return EFalse; |
|
281 } |
|
282 aAID.Append(aidDigit); |
|
283 break; |
|
284 } |
|
285 case EERROR: |
|
286 { |
|
287 return EFalse; |
|
288 } |
|
289 default: |
|
290 { |
|
291 // other states don't require action |
|
292 } |
|
293 } |
|
294 } |
|
295 if (aidState == ESecondDigit) |
|
296 { |
|
297 // the uri ended after first digit, which is not yet added |
|
298 if (++aidLength > aidMaxLength) |
|
299 { |
|
300 return EFalse; |
|
301 } |
|
302 aAID.Append(aidDigit); |
|
303 } |
|
304 if (aidState == EFirstDigit) |
|
305 { |
|
306 // AID ended with a dot |
|
307 return EFalse; |
|
308 } |
|
309 |
|
310 if (aidState == EDot) |
|
311 { |
|
312 // Append also last digit |
|
313 aAID.Append(aidDigit); |
|
314 } |
|
315 |
|
316 if (aidLength < KSTSAIDMinLength) |
|
317 { |
|
318 return EFalse; |
|
319 } |
|
320 return ETrue; |
|
321 } |
|
322 |
|
323 // ----------------------------------------------------------------------------- |
|
324 // CSTSURI::ParseAIDCharacter |
|
325 // Implements AID parsing state machine |
|
326 // ----------------------------------------------------------------------------- |
|
327 void CSTSURI::ParseAIDCharacter(const TChar& aDigit, TAidParserState& aState, |
|
328 TUint8& aAIDDigit) |
|
329 { |
|
330 switch (aState) |
|
331 { |
|
332 case EFirstDigit: |
|
333 { |
|
334 aAIDDigit = GetHexValue(aDigit); |
|
335 if (aAIDDigit > KSTSMaxHexValue) |
|
336 { |
|
337 aState = EERROR; |
|
338 } |
|
339 else |
|
340 { |
|
341 aState = ESecondDigit; |
|
342 } |
|
343 break; |
|
344 } |
|
345 case ESecondDigit: |
|
346 { |
|
347 if (aDigit != KSTSApduUriAIDSeparator) |
|
348 { |
|
349 TUint8 secondDigit = GetHexValue(aDigit); |
|
350 if (secondDigit > KSTSMaxHexValue) |
|
351 { |
|
352 aState = EERROR; |
|
353 } |
|
354 else |
|
355 { |
|
356 aAIDDigit <<= KSTSLengthOfSingleHexDigitInBits; |
|
357 aAIDDigit |= secondDigit; |
|
358 aState = EDot; |
|
359 } |
|
360 } |
|
361 else |
|
362 { |
|
363 aState = EFirstDigit; |
|
364 } |
|
365 break; |
|
366 } |
|
367 case EDot: |
|
368 { |
|
369 if (aDigit != KSTSApduUriAIDSeparator) |
|
370 { |
|
371 aState = EERROR; |
|
372 } |
|
373 else |
|
374 { |
|
375 aState = EFirstDigit; |
|
376 } |
|
377 break; |
|
378 } |
|
379 default: |
|
380 { |
|
381 |
|
382 } |
|
383 } |
|
384 } |
|
385 |
|
386 } // namespace satsa |
|
387 } // namespace java |
|
388 // End of File |