43 #include "CleanupResetAndDestroy.h" |
43 #include "CleanupResetAndDestroy.h" |
44 #include "RImplInfoPtrArrayOwn.inl" |
44 #include "RImplInfoPtrArrayOwn.inl" |
45 #include "CalenEcomWatcher.h" // Watches for ECOM registry changes |
45 #include "CalenEcomWatcher.h" // Watches for ECOM registry changes |
46 |
46 |
47 // CONSTANTS |
47 // CONSTANTS |
|
48 |
|
49 /* set the following to the number of 100ns ticks of the actual |
|
50 resolution of your system's clock. |
|
51 800MHZ means 1s->800*(10^6) clock cycles |
|
52 100ns->80 clock cycles*/ |
|
53 const TUint16 UUIDS_PER_TICK = 80; |
|
54 |
48 /// Unnamed namespace for local definitions |
55 /// Unnamed namespace for local definitions |
49 namespace { |
56 namespace { |
50 |
57 |
51 #ifdef __WINSCW__ |
58 #ifdef __WINSCW__ |
52 _LIT( KEmulatorImei, "123456789012345" ); |
59 _LIT( KEmulatorImei, "123456789012345" ); |
53 #endif |
60 #endif |
54 |
61 |
55 const TInt KImeiLength = 15; // 15 chars from left of imei |
62 const TInt KImeiLength = 15; // 15 chars from left of imei |
56 |
63 const TInt KAsciiFirstNumber = 48; // ASCII character 48 = '0'. |
57 const TInt KAsciiFirstNumber = 48; // ASCII character 48 = '0'. |
|
58 const TInt KAsciiFirstLowercaseLetter = 97; // ASCII character 97 = 'a'. |
64 const TInt KAsciiFirstLowercaseLetter = 97; // ASCII character 97 = 'a'. |
59 |
65 |
60 } // namespace |
66 } // namespace |
61 |
67 |
62 // ---------------------------------------------------------------------------- |
68 // ---------------------------------------------------------------------------- |
277 |
283 |
278 // Loosely using UID generation algorithm from |
284 // Loosely using UID generation algorithm from |
279 // http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt |
285 // http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt |
280 |
286 |
281 // Number of 100ns ticks since Oct 15 1582. |
287 // Number of 100ns ticks since Oct 15 1582. |
282 TInt64 timeStamp = GetTicksFromGregorianCalendarStartL(); |
288 TInt64 timeStamp; |
283 |
289 GetSystemTime(timeStamp); |
|
290 |
284 // This differs slightly from the spec in that the clock sequence is just a pseudo-random number. |
291 // This differs slightly from the spec in that the clock sequence is just a pseudo-random number. |
285 TUint32 clockSeq = Math::Random(); |
292 TUint32 clockSeq = Math::Random(); |
286 // IMEI is read the first time this is called, and stored for subsequent calls. |
293 |
287 if(!iImeiNode) |
294 // IMEI is read the first time this is called, and stored for subsequent calls. |
288 { |
295 if(!iImeiNode) |
289 iImeiNode = GetImeiAsNodeValueL(); |
296 { |
290 } |
297 iImeiNode = GetImeiAsNodeValueL(); |
|
298 } |
291 |
299 |
292 HBufC8* resultBuf = DoCreateUidLC(clockSeq, timeStamp, iImeiNode); |
300 HBufC8* resultBuf = DoCreateUidLC(clockSeq, timeStamp, iImeiNode); |
293 CleanupStack::Pop(resultBuf); |
301 CleanupStack::Pop(resultBuf); |
294 |
302 |
295 TRACE_EXIT_POINT; |
303 TRACE_EXIT_POINT; |
311 TDateTime gregorianStartDT(1582, EOctober, 15, 0, 0, 0, 0); |
319 TDateTime gregorianStartDT(1582, EOctober, 15, 0, 0, 0, 0); |
312 TTime gregorianStart(gregorianStartDT); |
320 TTime gregorianStart(gregorianStartDT); |
313 TTimeIntervalMicroSeconds msDifference = timeNow.MicroSecondsFrom(gregorianStart); |
321 TTimeIntervalMicroSeconds msDifference = timeNow.MicroSecondsFrom(gregorianStart); |
314 |
322 |
315 TRACE_EXIT_POINT; |
323 TRACE_EXIT_POINT; |
316 return msDifference.Int64() * 10; // * 10 to convert from micro sec (==1000 ns) count to 100ns count. |
324 return ( timeNow.Int64() + msDifference.Int64() ) * 10; // * 10 to convert from micro sec (==1000 ns) count to 100ns count. |
|
325 } |
|
326 |
|
327 // ----------------------------------------------------------------------------- |
|
328 // CCalenInterimUtils2Impl::GetSystemTime() |
|
329 // This function returns the system time. |
|
330 // (other items were commented in a header). |
|
331 // ----------------------------------------------------------------------------- |
|
332 // |
|
333 void CCalenInterimUtils2Impl::GetSystemTime(TInt64& aTimeStamp) |
|
334 { |
|
335 TRACE_ENTRY_POINT; |
|
336 |
|
337 if (!iInited) |
|
338 { |
|
339 aTimeStamp = GetTicksFromGregorianCalendarStartL(); |
|
340 iThisTick = UUIDS_PER_TICK; |
|
341 iInited = ETrue; |
|
342 } |
|
343 for( ; ; ) |
|
344 { |
|
345 aTimeStamp = GetTicksFromGregorianCalendarStartL(); |
|
346 //if clock reading changed since last UUID generated... |
|
347 if( iTimeLast != aTimeStamp ) |
|
348 { |
|
349 //reset count of uuids gen'd with this clock reading |
|
350 iThisTick = 0; |
|
351 iTimeLast = aTimeStamp; |
|
352 break; |
|
353 } |
|
354 if( iThisTick < UUIDS_PER_TICK ) |
|
355 { |
|
356 iThisTick++; |
|
357 break; |
|
358 } |
|
359 } |
|
360 //add the count of uuids to low order bits of the clock reading |
|
361 aTimeStamp += iThisTick; |
|
362 |
|
363 TRACE_EXIT_POINT; |
317 } |
364 } |
318 |
365 |
319 // ----------------------------------------------------------------------------- |
366 // ----------------------------------------------------------------------------- |
320 // CCalenInterimUtils2Impl::GetImeiAsNodeValueL() |
367 // CCalenInterimUtils2Impl::GetImeiAsNodeValueL() |
321 // Formats the IMEI returned from GetImeiL() into a 64-bit integer. |
368 // Formats the IMEI returned from GetImeiL() into a 64-bit integer. |
368 const TUint64& aNodeValue ) |
415 const TUint64& aNodeValue ) |
369 { |
416 { |
370 TRACE_ENTRY_POINT; |
417 TRACE_ENTRY_POINT; |
371 |
418 |
372 // The roast beef of the algorithm. Does all the shifting about as described in the web draft. |
419 // The roast beef of the algorithm. Does all the shifting about as described in the web draft. |
373 TUint32 time_low = aTimeStamp & 0xFFFFFFFF; |
420 SUuid uuid; |
374 TUint16 time_mid = (aTimeStamp >> 32) & 0xFFFF; |
421 TUint8 hash[16]; |
375 TUint16 time_high = (aTimeStamp >> 48) & 0x0FFF; |
422 |
376 time_high |= (1 << 12); |
423 uuid.time_low = aTimeStamp & 0xFFFFFFFF; |
377 TUint8 clock_seq_low = aClockSeq & 0xFF; |
424 uuid.time_mid = (aTimeStamp >> 32) & 0xFFFF; |
378 TUint8 clock_seq_high = (aClockSeq & 0x3F00) >> 8; |
425 uuid.time_high_and_version = (aTimeStamp >> 48) & 0x0FFF; |
379 clock_seq_high |= 0x80; |
426 uuid.time_high_and_version |= (1 << 12); |
380 |
427 uuid.clock_seq_low = aClockSeq & 0xFF; |
381 // Can't use RArray as that's set up for minimum 4 bytes per item. |
428 uuid.clock_seq_hi_and_reserved = (aClockSeq & 0x3F00) >> 8; |
382 CArrayFixFlat<TUint8> *node = new (ELeave) CArrayFixFlat<TUint8>(6); |
429 uuid.clock_seq_hi_and_reserved |= 0x80; |
383 CleanupStack::PushL(node); |
430 |
384 |
|
385 // The rest of the function is mapping the 64, 32 and 16 bit numbers to 8 bit numbers |
|
386 // while losing as little data as possible. |
|
387 |
|
388 TUint64 mask = 0xFF0000000000; |
431 TUint64 mask = 0xFF0000000000; |
389 for(TInt i=0; i<=6; ++i) |
432 for(TInt i=0; i<=6; ++i) |
390 { |
433 { |
391 TInt64 temp = aNodeValue & mask; |
434 TInt64 temp = aNodeValue & mask; |
392 temp >>= ((5-i)*8); |
435 temp >>= ((5-i)*8); |
393 node->AppendL(temp); |
436 uuid.node[i] = temp; |
394 mask = mask >> 8; |
437 mask = mask >> 8; |
395 } |
438 } |
396 |
439 |
397 TBuf8<16> rawOutput; |
440 //md5 context |
398 |
441 MD5_CTX context; |
399 rawOutput.Append( (time_low & 0xFF000000) >> 24 ); |
|
400 rawOutput.Append( (time_low & 0x00FF0000) >> 16 ); |
|
401 rawOutput.Append( (time_low & 0x0000FF00) >> 8 ); |
|
402 rawOutput.Append( (time_low & 0x000000FF) ); |
|
403 |
|
404 rawOutput.Append( (time_mid & 0xFF00) >> 8 ); |
|
405 rawOutput.Append( (time_mid & 0x00FF) ); |
|
406 |
|
407 rawOutput.Append( (time_high & 0xFF00) >> 8 ); |
|
408 rawOutput.Append( (time_high & 0x00FF) ); |
|
409 |
|
410 rawOutput.Append( clock_seq_low ); |
|
411 rawOutput.Append( clock_seq_high ); |
|
412 |
|
413 for(TInt i=0; i<6; ++i) |
|
414 { |
|
415 rawOutput.Append( node->At(i) ); |
|
416 } |
|
417 CleanupStack::PopAndDestroy(); // node |
|
418 |
|
419 TUint8 digest[16]; |
|
420 HBufC8* resultBuf = rawOutput.AllocLC(); |
|
421 TPtr8 resultBufPtr = resultBuf->Des(); |
|
422 TUint length = resultBufPtr.Length(); |
|
423 |
|
424 // Create a new buffer to provide space for '\0' |
|
425 HBufC8* newBuf = HBufC8::NewLC( length + 1 );//+1 space for '\0' |
|
426 TPtr8 newBufPtr = newBuf->Des(); |
|
427 newBufPtr.Copy(resultBufPtr); |
|
428 |
|
429 // Appends a zero terminator onto the end of this descriptor's data |
|
430 // and returns a pointer to the data. |
|
431 char* chPtrTemp = ( char*)newBufPtr.PtrZ(); |
|
432 char* chPtr = ( char*) User::AllocL( length + 1 ); |
|
433 strcpy( chPtr , chPtrTemp ); |
|
434 |
|
435 //md5 context |
|
436 MD5_CTX* context = new MD5_CTX(); |
|
437 //initialize the context |
442 //initialize the context |
438 MD5_Init(context); |
443 MD5_Init(&context); |
439 //Append a string to the message |
444 //Append a string to the message |
440 MD5_Update(context, chPtr, length ); |
445 MD5_Update(&context, &uuid, sizeof(uuid) ); |
441 //Finish the message and return the digest. |
446 //Finish the message and return the digest. |
442 MD5_Final(digest, context ); |
447 MD5_Final(hash, &context ); |
443 |
|
444 // Add the version field in the msb 4 bits. The value of version is 3. |
448 // Add the version field in the msb 4 bits. The value of version is 3. |
445 digest[6] = digest[6] & 0x0F; |
449 hash[6] = hash[6] & 0x0F; |
446 digest[6] |= (3 << 4); |
450 hash[6] |= (3 << 4); |
447 |
451 |
448 //Add the variant field in the msb 2 bits. The value of variant is 2. |
452 //Add the variant field in the msb 2 bits. The value of variant is 2. |
449 digest[9] = digest[9] & 0x3F; |
453 hash[8] = hash[8] & 0x3F; |
450 digest[9] |= 0x80; |
454 hash[8] |= 0x80; |
451 |
455 |
452 delete chPtr; |
|
453 delete context; |
|
454 CleanupStack::PopAndDestroy( newBuf ); |
|
455 CleanupStack::PopAndDestroy( resultBuf ); |
|
456 TBuf8<36> output; |
456 TBuf8<36> output; |
457 TInt i; |
457 TInt i; |
458 for(i=0; i<16; ++i) |
458 for(i=0; i<16; ++i) |
459 { |
459 { |
460 output.Append( ConvertToCharacterL( FirstFourBits( digest[i] ) ) ); |
460 output.Append( ConvertToCharacterL( FirstFourBits( hash[i] ) ) ); |
461 output.Append( ConvertToCharacterL( LastFourBits( digest[i] ) ) ); |
461 output.Append( ConvertToCharacterL( LastFourBits( hash[i] ) ) ); |
462 if(i == 3 || i == 5 || i == 7 ||i == 9) |
462 if(i == 3 || i == 5 || i == 7 ||i == 9) |
463 { |
463 { |
464 output.Append( '-' ); |
464 output.Append( '-' ); |
465 } |
465 } |
466 } |
466 } |
467 HBufC8* md5ResultBuf = output.AllocLC(); |
467 HBufC8* retBuf = output.AllocLC(); |
468 |
468 |
469 TRACE_EXIT_POINT; |
469 TRACE_EXIT_POINT; |
470 return md5ResultBuf; |
470 return retBuf; |
|
471 |
471 } |
472 } |
472 |
473 |
473 // ----------------------------------------------------------------------------- |
474 // ----------------------------------------------------------------------------- |
474 // CCalenInterimUtils2Impl::ConvertToCharacterL() |
475 // CCalenInterimUtils2Impl::ConvertToCharacterL() |
475 // Converts from a number between 0-15 to a hexadecimal character representation. |
476 // Converts from a number between 0-15 to a hexadecimal character representation. |