30 #include <caluser.h> |
30 #include <caluser.h> |
31 #include <calentryview.h> |
31 #include <calentryview.h> |
32 #include <etelmm.h> |
32 #include <etelmm.h> |
33 #include <e32math.h> |
33 #include <e32math.h> |
34 #include <calrrule.h> |
34 #include <calrrule.h> |
|
35 #include <cmrmailboxutils.h> |
35 #include <featmgr.h> |
36 #include <featmgr.h> |
|
37 #include <MeetingRequestUids.hrh> |
36 #include <ecom/ecom.h> |
38 #include <ecom/ecom.h> |
37 #include <utf.h> |
39 #include <utf.h> |
38 #include <openssl/md5.h> |
40 #include <openssl/md5.h> |
39 #include <string.h> |
41 #include <string.h> |
40 |
42 |
41 #include "CleanupResetAndDestroy.h" |
43 #include "CleanupResetAndDestroy.h" |
42 #include "RImplInfoPtrArrayOwn.inl" |
44 #include "RImplInfoPtrArrayOwn.inl" |
43 #include "CalenEcomWatcher.h" // Watches for ECOM registry changes |
45 #include "CalenEcomWatcher.h" // Watches for ECOM registry changes |
44 |
46 |
45 // 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 |
46 /// Unnamed namespace for local definitions |
55 /// Unnamed namespace for local definitions |
47 namespace { |
56 namespace { |
48 |
57 |
49 #ifdef __WINSCW__ |
58 #ifdef __WINSCW__ |
50 _LIT( KEmulatorImei, "123456789012345" ); |
59 _LIT( KEmulatorImei, "123456789012345" ); |
51 #endif |
60 #endif |
52 |
61 |
53 const TInt KImeiLength = 15; // 15 chars from left of imei |
62 const TInt KImeiLength = 15; // 15 chars from left of imei |
54 |
63 const TInt KAsciiFirstNumber = 48; // ASCII character 48 = '0'. |
55 const TInt KAsciiFirstNumber = 48; // ASCII character 48 = '0'. |
|
56 const TInt KAsciiFirstLowercaseLetter = 97; // ASCII character 97 = 'a'. |
64 const TInt KAsciiFirstLowercaseLetter = 97; // ASCII character 97 = 'a'. |
57 |
65 |
58 } // namespace |
66 } // namespace |
59 |
67 |
60 // ---------------------------------------------------------------------------- |
68 // ---------------------------------------------------------------------------- |
272 |
283 |
273 // Loosely using UID generation algorithm from |
284 // Loosely using UID generation algorithm from |
274 // http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt |
285 // http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt |
275 |
286 |
276 // Number of 100ns ticks since Oct 15 1582. |
287 // Number of 100ns ticks since Oct 15 1582. |
277 TInt64 timeStamp = GetTicksFromGregorianCalendarStartL(); |
288 TInt64 timeStamp; |
278 |
289 GetSystemTime(timeStamp); |
|
290 |
279 // 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. |
280 TUint32 clockSeq = Math::Random(); |
292 TUint32 clockSeq = Math::Random(); |
281 // IMEI is read the first time this is called, and stored for subsequent calls. |
293 |
282 if(!iImeiNode) |
294 // IMEI is read the first time this is called, and stored for subsequent calls. |
283 { |
295 if(!iImeiNode) |
284 iImeiNode = GetImeiAsNodeValueL(); |
296 { |
285 } |
297 iImeiNode = GetImeiAsNodeValueL(); |
|
298 } |
286 |
299 |
287 HBufC8* resultBuf = DoCreateUidLC(clockSeq, timeStamp, iImeiNode); |
300 HBufC8* resultBuf = DoCreateUidLC(clockSeq, timeStamp, iImeiNode); |
288 CleanupStack::Pop(resultBuf); |
301 CleanupStack::Pop(resultBuf); |
289 |
302 |
290 TRACE_EXIT_POINT; |
303 TRACE_EXIT_POINT; |
306 TDateTime gregorianStartDT(1582, EOctober, 15, 0, 0, 0, 0); |
319 TDateTime gregorianStartDT(1582, EOctober, 15, 0, 0, 0, 0); |
307 TTime gregorianStart(gregorianStartDT); |
320 TTime gregorianStart(gregorianStartDT); |
308 TTimeIntervalMicroSeconds msDifference = timeNow.MicroSecondsFrom(gregorianStart); |
321 TTimeIntervalMicroSeconds msDifference = timeNow.MicroSecondsFrom(gregorianStart); |
309 |
322 |
310 TRACE_EXIT_POINT; |
323 TRACE_EXIT_POINT; |
311 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; |
312 } |
364 } |
313 |
365 |
314 // ----------------------------------------------------------------------------- |
366 // ----------------------------------------------------------------------------- |
315 // CCalenInterimUtils2Impl::GetImeiAsNodeValueL() |
367 // CCalenInterimUtils2Impl::GetImeiAsNodeValueL() |
316 // Formats the IMEI returned from GetImeiL() into a 64-bit integer. |
368 // Formats the IMEI returned from GetImeiL() into a 64-bit integer. |
363 const TUint64& aNodeValue ) |
415 const TUint64& aNodeValue ) |
364 { |
416 { |
365 TRACE_ENTRY_POINT; |
417 TRACE_ENTRY_POINT; |
366 |
418 |
367 // 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. |
368 TUint32 time_low = aTimeStamp & 0xFFFFFFFF; |
420 SUuid uuid; |
369 TUint16 time_mid = (aTimeStamp >> 32) & 0xFFFF; |
421 TUint8 hash[16]; |
370 TUint16 time_high = (aTimeStamp >> 48) & 0x0FFF; |
422 |
371 time_high |= (1 << 12); |
423 uuid.time_low = aTimeStamp & 0xFFFFFFFF; |
372 TUint8 clock_seq_low = aClockSeq & 0xFF; |
424 uuid.time_mid = (aTimeStamp >> 32) & 0xFFFF; |
373 TUint8 clock_seq_high = (aClockSeq & 0x3F00) >> 8; |
425 uuid.time_high_and_version = (aTimeStamp >> 48) & 0x0FFF; |
374 clock_seq_high |= 0x80; |
426 uuid.time_high_and_version |= (1 << 12); |
375 |
427 uuid.clock_seq_low = aClockSeq & 0xFF; |
376 // 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; |
377 CArrayFixFlat<TUint8> *node = new (ELeave) CArrayFixFlat<TUint8>(6); |
429 uuid.clock_seq_hi_and_reserved |= 0x80; |
378 CleanupStack::PushL(node); |
430 |
379 |
|
380 // The rest of the function is mapping the 64, 32 and 16 bit numbers to 8 bit numbers |
|
381 // while losing as little data as possible. |
|
382 |
|
383 TUint64 mask = 0xFF0000000000; |
431 TUint64 mask = 0xFF0000000000; |
384 for(TInt i=0; i<=6; ++i) |
432 for(TInt i=0; i<=6; ++i) |
385 { |
433 { |
386 TInt64 temp = aNodeValue & mask; |
434 TInt64 temp = aNodeValue & mask; |
387 temp >>= ((5-i)*8); |
435 temp >>= ((5-i)*8); |
388 node->AppendL(temp); |
436 uuid.node[i] = temp; |
389 mask = mask >> 8; |
437 mask = mask >> 8; |
390 } |
438 } |
391 |
439 |
392 TBuf8<16> rawOutput; |
440 //md5 context |
393 |
441 MD5_CTX context; |
394 rawOutput.Append( (time_low & 0xFF000000) >> 24 ); |
|
395 rawOutput.Append( (time_low & 0x00FF0000) >> 16 ); |
|
396 rawOutput.Append( (time_low & 0x0000FF00) >> 8 ); |
|
397 rawOutput.Append( (time_low & 0x000000FF) ); |
|
398 |
|
399 rawOutput.Append( (time_mid & 0xFF00) >> 8 ); |
|
400 rawOutput.Append( (time_mid & 0x00FF) ); |
|
401 |
|
402 rawOutput.Append( (time_high & 0xFF00) >> 8 ); |
|
403 rawOutput.Append( (time_high & 0x00FF) ); |
|
404 |
|
405 rawOutput.Append( clock_seq_low ); |
|
406 rawOutput.Append( clock_seq_high ); |
|
407 |
|
408 for(TInt i=0; i<6; ++i) |
|
409 { |
|
410 rawOutput.Append( node->At(i) ); |
|
411 } |
|
412 CleanupStack::PopAndDestroy(); // node |
|
413 |
|
414 TUint8 digest[16]; |
|
415 HBufC8* resultBuf = rawOutput.AllocLC(); |
|
416 TPtr8 resultBufPtr = resultBuf->Des(); |
|
417 TUint length = resultBufPtr.Length(); |
|
418 |
|
419 // Create a new buffer to provide space for '\0' |
|
420 HBufC8* newBuf = HBufC8::NewLC( length + 1 );//+1 space for '\0' |
|
421 TPtr8 newBufPtr = newBuf->Des(); |
|
422 newBufPtr.Copy(resultBufPtr); |
|
423 |
|
424 // Appends a zero terminator onto the end of this descriptor's data |
|
425 // and returns a pointer to the data. |
|
426 char* chPtrTemp = ( char*)newBufPtr.PtrZ(); |
|
427 char* chPtr = ( char*) User::AllocL( length + 1 ); |
|
428 strcpy( chPtr , chPtrTemp ); |
|
429 |
|
430 //md5 context |
|
431 MD5_CTX* context = new MD5_CTX(); |
|
432 //initialize the context |
442 //initialize the context |
433 MD5_Init(context); |
443 MD5_Init(&context); |
434 //Append a string to the message |
444 //Append a string to the message |
435 MD5_Update(context, chPtr, length ); |
445 MD5_Update(&context, &uuid, sizeof(uuid) ); |
436 //Finish the message and return the digest. |
446 //Finish the message and return the digest. |
437 MD5_Final(digest, context ); |
447 MD5_Final(hash, &context ); |
438 |
|
439 // 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. |
440 digest[6] = digest[6] & 0x0F; |
449 hash[6] = hash[6] & 0x0F; |
441 digest[6] |= (3 << 4); |
450 hash[6] |= (3 << 4); |
442 |
451 |
443 //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. |
444 digest[9] = digest[9] & 0x3F; |
453 hash[8] = hash[8] & 0x3F; |
445 digest[9] |= 0x80; |
454 hash[8] |= 0x80; |
446 |
455 |
447 delete chPtr; |
|
448 delete context; |
|
449 CleanupStack::PopAndDestroy( newBuf ); |
|
450 CleanupStack::PopAndDestroy( resultBuf ); |
|
451 TBuf8<36> output; |
456 TBuf8<36> output; |
452 TInt i; |
457 TInt i; |
453 for(i=0; i<16; ++i) |
458 for(i=0; i<16; ++i) |
454 { |
459 { |
455 output.Append( ConvertToCharacterL( FirstFourBits( digest[i] ) ) ); |
460 output.Append( ConvertToCharacterL( FirstFourBits( hash[i] ) ) ); |
456 output.Append( ConvertToCharacterL( LastFourBits( digest[i] ) ) ); |
461 output.Append( ConvertToCharacterL( LastFourBits( hash[i] ) ) ); |
457 if(i == 3 || i == 5 || i == 7 ||i == 9) |
462 if(i == 3 || i == 5 || i == 7 ||i == 9) |
458 { |
463 { |
459 output.Append( '-' ); |
464 output.Append( '-' ); |
460 } |
465 } |
461 } |
466 } |
462 HBufC8* md5ResultBuf = output.AllocLC(); |
467 HBufC8* retBuf = output.AllocLC(); |
463 |
468 |
464 TRACE_EXIT_POINT; |
469 TRACE_EXIT_POINT; |
465 return md5ResultBuf; |
470 return retBuf; |
|
471 |
466 } |
472 } |
467 |
473 |
468 // ----------------------------------------------------------------------------- |
474 // ----------------------------------------------------------------------------- |
469 // CCalenInterimUtils2Impl::ConvertToCharacterL() |
475 // CCalenInterimUtils2Impl::ConvertToCharacterL() |
470 // 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. |
559 // Checks to see if Meeting Request Viewer functionality |
565 // Checks to see if Meeting Request Viewer functionality |
560 // is enabled and an implementation is available to use |
566 // is enabled and an implementation is available to use |
561 // (other items were commented in a header). |
567 // (other items were commented in a header). |
562 // ----------------------------------------------------------------------------- |
568 // ----------------------------------------------------------------------------- |
563 // |
569 // |
564 TBool CCalenInterimUtils2Impl::MRViewersEnabledL(TBool /*aForceCheck*/) |
570 TBool CCalenInterimUtils2Impl::MRViewersEnabledL(TBool aForceCheck) |
565 { |
571 { |
566 TRACE_ENTRY_POINT; |
572 TRACE_ENTRY_POINT; |
567 // Need to implement it once we have meeting request viewer in 10.1 |
573 if( aForceCheck || iMrEnabledCheck ) |
568 TRACE_EXIT_POINT; |
574 { |
569 return false; |
575 iMrEnabled = EFalse; |
|
576 iMrEnabledCheck = EFalse; |
|
577 |
|
578 PIM_TRAPD_HANDLE( DoMRViewersEnabledL() ); |
|
579 } |
|
580 |
|
581 TRACE_EXIT_POINT; |
|
582 return iMrEnabled; |
570 } |
583 } |
571 // ----------------------------------------------------------------------------- |
584 // ----------------------------------------------------------------------------- |
572 // CCalenInterimUtils2Impl::DoMRViewersEnabledL() |
585 // CCalenInterimUtils2Impl::DoMRViewersEnabledL() |
573 // Checks to see if Meeting Request Viewer functionality |
586 // Checks to see if Meeting Request Viewer functionality |
574 // is enabled and an implementation is available to use |
587 // is enabled and an implementation is available to use |
576 // ----------------------------------------------------------------------------- |
589 // ----------------------------------------------------------------------------- |
577 // |
590 // |
578 void CCalenInterimUtils2Impl::DoMRViewersEnabledL() |
591 void CCalenInterimUtils2Impl::DoMRViewersEnabledL() |
579 { |
592 { |
580 TRACE_ENTRY_POINT; |
593 TRACE_ENTRY_POINT; |
581 // Need to implement it once we have meeting request viewer in 10.1 |
594 |
582 TRACE_EXIT_POINT; |
595 // We ignore any leaves because iMrEnabled and iMrEnabledCheck are already set to |
|
596 // EFalse, so if the function leaves it will return EFalse this time and any future |
|
597 // calls will not force a check (unless aForceCheck is ETrue). |
|
598 if (FeatureManager::FeatureSupported(KFeatureIdMeetingRequestSupport)) |
|
599 { |
|
600 // Full meeting request solution |
|
601 // As long as we have at least one mailbox we can return true |
|
602 CMRMailboxUtils *mbUtils = CMRMailboxUtils::NewL(); |
|
603 CleanupStack::PushL( mbUtils ); |
|
604 |
|
605 RArray<CMRMailboxUtils::TMailboxInfo> mailboxes; |
|
606 CleanupClosePushL(mailboxes); |
|
607 mbUtils->ListMailBoxesL(mailboxes); |
|
608 if(mailboxes.Count() > 0) |
|
609 { |
|
610 iMrEnabled = ETrue; // && 1 mailbox |
|
611 } |
|
612 |
|
613 CleanupStack::PopAndDestroy(); // mailboxes |
|
614 CleanupStack::PopAndDestroy(); // mbUtils |
|
615 } |
|
616 else |
|
617 { |
|
618 if (FeatureManager::FeatureSupported(KFeatureIdMeetingRequestEnabler)) |
|
619 { |
|
620 // Meeting request enablers solution |
|
621 //Check for: |
|
622 // At least one mailbox exists on the terminal |
|
623 // At least one MRViewer implementation, with an id matching a mailbox, |
|
624 // exists on the terminal |
|
625 // At least one MRUtils implementation exists on the terminal |
|
626 CMRMailboxUtils *mbUtils = CMRMailboxUtils::NewL(); |
|
627 CleanupStack::PushL( mbUtils ); |
|
628 |
|
629 RArray<CMRMailboxUtils::TMailboxInfo> mailboxes; |
|
630 CleanupClosePushL(mailboxes); |
|
631 |
|
632 mbUtils->ListMailBoxesL(mailboxes); |
|
633 if(mailboxes.Count() > 0) |
|
634 { |
|
635 RImplInfoPtrArrayOwn implArray; |
|
636 CleanupClosePushL( implArray ); |
|
637 |
|
638 //Check for a MRViewers Implementation |
|
639 const TUid mrViewersIface = {KMRViewersInterfaceUID}; |
|
640 REComSession::ListImplementationsL(mrViewersIface, implArray ); |
|
641 if ( implArray.Count() > 0 ) |
|
642 { |
|
643 // MRViewers implementations exist. We need to see if any are |
|
644 // associated with an existing mailbox |
|
645 TBool mrImplMatchesMailbox = EFalse; |
|
646 for (TInt i=0; i<implArray.Count(); ++i) |
|
647 { |
|
648 for(TInt j=0; j<mailboxes.Count(); ++j) |
|
649 { |
|
650 TBuf16<KMaxUidName> mbName; |
|
651 CnvUtfConverter::ConvertToUnicodeFromUtf8( mbName, implArray[i]->DataType() ); |
|
652 if(mailboxes[j].iMtmUid.Name().CompareF(mbName) == 0) |
|
653 { |
|
654 mrImplMatchesMailbox = ETrue; |
|
655 //One match is enough for this decision to be true |
|
656 break; |
|
657 } |
|
658 } |
|
659 if (mrImplMatchesMailbox) |
|
660 { |
|
661 break; |
|
662 } |
|
663 } |
|
664 |
|
665 // Reset the viewer implementation array. This will be reused |
|
666 // if we need to check for mr utils implementations |
|
667 implArray.ResetAndDestroy(); |
|
668 |
|
669 if (mrImplMatchesMailbox) |
|
670 { |
|
671 // We have at least one MRViewer implementation with an associated |
|
672 // mailbox. Check for a matching MR utils implementation |
|
673 const TUid mrUtilsIface = {KMRUtilsInterfaceUID}; |
|
674 REComSession::ListImplementationsL(mrUtilsIface, implArray ); |
|
675 if (implArray.Count() > 0) |
|
676 { |
|
677 // Meeting request functionality is available on this device |
|
678 iMrEnabled = ETrue; |
|
679 } |
|
680 } |
|
681 |
|
682 } |
|
683 CleanupStack::PopAndDestroy(); // implArray |
|
684 } |
|
685 |
|
686 CleanupStack::PopAndDestroy(); // mailboxes |
|
687 CleanupStack::PopAndDestroy(); // mbUtils |
|
688 } |
|
689 } |
583 } |
690 } |
584 |
691 |
585 // ----------------------------------------------------------------------------- |
692 // ----------------------------------------------------------------------------- |
586 // CCalenInterimUtils2Impl::HasTimeOrDateChangedL() |
693 // CCalenInterimUtils2Impl::HasTimeOrDateChangedL() |
587 // Checks to see if the date or time has changed from the given entry to the |
694 // Checks to see if the date or time has changed from the given entry to the |