calendarengines/caleninterimutils/src/CalenInterimUtils2Impl.cpp
branchRCL_3
changeset 48 bf573002ff72
parent 0 f979ecb2b13e
child 65 12af337248b1
equal deleted inserted replaced
36:9c5b1510919f 48:bf573002ff72
    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 // ----------------------------------------------------------------------------
    89 CCalenInterimUtils2Impl::CCalenInterimUtils2Impl()
    95 CCalenInterimUtils2Impl::CCalenInterimUtils2Impl()
    90     {
    96     {
    91     TRACE_ENTRY_POINT;
    97     TRACE_ENTRY_POINT;
    92 
    98 
    93     iMrEnabledCheck = ETrue;
    99     iMrEnabledCheck = ETrue;
    94     iMrEnabled = EFalse;
   100     iMrEnabled = EFalse;    
    95     
   101     iInited = EFalse;
    96     TRACE_EXIT_POINT;
   102     TRACE_EXIT_POINT;
    97     }
   103     }
    98 
   104 
    99 // -----------------------------------------------------------------------------
   105 // -----------------------------------------------------------------------------
   100 // CCalenInterimUtils2Impl::ConstructL()
   106 // CCalenInterimUtils2Impl::ConstructL()
   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.