- Timestamp:
- 07/09/07 10:02:18 (2 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
Mulberry/branches/v4.1d1/Sources_Common/Mail/Protocols/CAdbkProtocol.cp
r19 r86 23 23 #include "CActionManager.h" 24 24 #include "CAdbkClient.h" 25 #include "CAd bkList.h"25 #include "CAddressBook.h" 26 26 #include "CAddressBookManager.h" 27 27 #include "CConnectionManager.h" 28 28 #include "CIMSPClient.h" 29 29 #include "CLocalAdbkClient.h" 30 #include "CLocalVCardClient.h" 30 31 #if __dest_os == __mac_os || __dest_os == __mac_os_x 31 32 #if PP_Target_Carbon … … 34 35 #endif 35 36 #include "CPreferences.h" 36 #include "CRemoteAddressBook.h" 37 38 #include "CCardDAVVCardClient.h" 39 40 #include "CVCardStoreXML.h" // Share XML defintions with calendar store 41 42 #include "CVCardAddressBook.h" 43 #include "CVCardSync.h" 37 44 38 45 #include "cdfstream.h" 46 47 #include "XMLDocument.h" 48 #include "XMLNode.h" 49 #include "XMLObject.h" 50 #include "XMLSAXSimple.h" 51 52 #define USE_LOCAL_VCARDS 53 54 using namespace vcardstore; 39 55 40 56 // CAdbkProtocol: Handles quotas for all resources … … 42 58 // Constructor 43 59 CAdbkProtocol::CAdbkProtocol(CINETAccount* account) 44 : CINETProtocol(account) 60 : CINETProtocol(account), 61 mStoreRoot(this) 45 62 { 46 63 mClient = NULL; 47 mAdbkList = new CAdbkList(false); 48 49 // Only IMSP/ACAP servers can disconnect 64 mCacheClient = NULL; 65 mCacheIsPrimary = false; 66 mSyncingList = false; 67 68 // Only IMSP/ACAP/CardDAV servers can disconnect 50 69 switch(GetAccountType()) 51 70 { 52 71 case CINETAccount::eIMSP: 53 72 case CINETAccount::eACAP: 54 SetFlags(eCanDisconnect, IsOfflineAllowed() &&55 GetAddressAccount()->GetDisconnected());73 case CINETAccount::eCardDAVAdbk: 74 SetFlags(eCanDisconnect, IsOfflineAllowed() && GetAddressAccount()->GetDisconnected()); 56 75 break; 57 76 default: … … 61 80 } 62 81 82 // If not login at startup but it can disconnect, set to force disconnect mode 83 mFlags.Set(eForceDisconnect, !GetAddressAccount()->GetLogonAtStart()); 84 85 switch(GetAccountType()) 86 { 87 case CINETAccount::eLocalAdbk: 88 case CINETAccount::eOSAdbk: 89 mDirDelim = os_dir_delim; 90 break; 91 case CINETAccount::eIMSP: 92 mDirDelim = '.'; 93 break; 94 case CINETAccount::eACAP: 95 case CINETAccount::eCardDAVAdbk: 96 mDirDelim = '/'; 97 break; 98 default: 99 mDirDelim = 0; 100 break; 101 } 102 63 103 mRecorder = NULL; 64 104 … … 68 108 // Copy constructor 69 109 CAdbkProtocol::CAdbkProtocol(const CAdbkProtocol& copy, bool force_local, bool force_remote) 70 : CINETProtocol(copy) 110 : CINETProtocol(copy), 111 mStoreRoot(this) 71 112 { 72 113 // Init instance variables 73 114 mClient = NULL; 74 mAdbkList = new CAdbkList(false); 115 mCacheClient = NULL; 116 mCacheIsPrimary = false; 75 117 76 118 mRecorder = NULL; // Only original proto uses this - clones do not 119 120 mDirDelim = copy.mDirDelim; 77 121 78 122 // Copy client 79 123 if (((GetAccountType() == CINETAccount::eIMSP) || 80 (GetAccountType() == CINETAccount::eACAP)) 124 (GetAccountType() == CINETAccount::eACAP) || 125 (GetAccountType() == CINETAccount::eCardDAVAdbk)) 81 126 && (force_local || force_remote)) 82 127 { … … 89 134 case CINETAccount::eIMSP: 90 135 mClient = new CIMSPClient(NULL, this); 136 if (CanDisconnect()) 137 { 138 InitOfflineCWD(); 139 mCacheClient = new CLocalVCardClient(this); 140 mCacheIsPrimary = false; 141 } 91 142 break; 92 143 case CINETAccount::eACAP: 93 144 mClient = new CACAPClient(NULL, this); 145 if (CanDisconnect()) 146 { 147 InitOfflineCWD(); 148 mCacheClient = new CLocalVCardClient(this); 149 mCacheIsPrimary = false; 150 } 151 break; 152 case CINETAccount::eCardDAVAdbk: 153 mClient = new CCardDAVVCardClient(this); 154 if (CanDisconnect()) 155 { 156 InitOfflineCWD(); 157 mCacheClient = new CLocalVCardClient(this); 158 mCacheIsPrimary = false; 159 } 94 160 break; 95 161 default:; … … 101 167 SetFlags(eDisconnected, true); 102 168 InitDisconnect(); 103 mClient = new CLocal AdbkClient(this);104 static_cast<CLocal AdbkClient*>(mClient)->SetRecorder(mRecorder);169 mClient = new CLocalVCardClient(this); 170 static_cast<CLocalVCardClient*>(mClient)->SetRecorder(mRecorder); 105 171 } 106 172 CINETProtocol::mClient = mClient; … … 114 180 CAdbkProtocol::~CAdbkProtocol() 115 181 { 182 // Clear nodes first to ensure any active nodes write themselves out before the 183 // client is deleted 184 mStoreRoot.Clear(); 185 116 186 // Delete client 117 187 RemoveClient(); 118 119 delete mAdbkList;120 mAdbkList = NULL;121 188 122 189 // Delete recorder … … 136 203 case CINETAccount::eIMSP: 137 204 case CINETAccount::eACAP: 205 case CINETAccount::eCardDAVAdbk: 138 206 SetFlags(eCanDisconnect, IsOfflineAllowed() && 139 207 GetAddressAccount()->GetDisconnected()); … … 144 212 } 145 213 214 switch(GetAccountType()) 215 { 216 case CINETAccount::eLocalAdbk: 217 case CINETAccount::eOSAdbk: 218 mDirDelim = os_dir_delim; 219 break; 220 case CINETAccount::eIMSP: 221 mDirDelim = '.'; 222 break; 223 case CINETAccount::eACAP: 224 case CINETAccount::eCardDAVAdbk: 225 mDirDelim = '/'; 226 break; 227 default: 228 mDirDelim = 0; 229 break; 230 } 231 232 // Look for change in account name 233 if (mStoreRoot.GetName() != GetAccountName()) 234 { 235 // Need to rename offline 236 if (mCacheClient != NULL) 237 { 238 RenameOffline(); 239 } 240 241 // Rename root 242 mStoreRoot.SetName(GetAccountName()); 243 } 244 245 if (mCacheClient != NULL) 246 { 247 // Don't allow throw 248 try 249 { 250 mCacheClient->Reset(); 251 } 252 catch (...) 253 { 254 CLOG_LOGCATCH(...); 255 } 256 } 257 258 } 259 260 void CAdbkProtocol::DirtyAccount() 261 { 262 // Must override in derived classes 263 switch(GetAccountType()) 264 { 265 case CINETAccount::eLocalAdbk: 266 case CINETAccount::eIMSP: 267 case CINETAccount::eACAP: 268 case CINETAccount::eCardDAVAdbk: 269 CPreferences::sPrefs->mAddressAccounts.SetDirty(); 270 break; 271 case CINETAccount::eOSAdbk: 272 CPreferences::sPrefs->mOSAdbkAccount.SetDirty(); 273 break; 274 default: 275 break; 276 } 146 277 } 147 278 … … 155 286 case CINETAccount::eIMSP: 156 287 case CINETAccount::eACAP: 157 if (CConnectionManager::sConnectionManager.IsConnected() || !CanDisconnect()) 288 case CINETAccount::eCardDAVAdbk: 289 if (CConnectionManager::sConnectionManager.IsConnected() && !IsForceDisconnect() || !CanDisconnect()) 158 290 { 159 291 SetFlags(eIsOffline, false); … … 163 295 case CINETAccount::eIMSP: 164 296 mClient = new CIMSPClient(NULL, this); 297 if (CanDisconnect()) 298 { 299 InitOfflineCWD(); 300 mCacheClient = new CLocalVCardClient(this); 301 mCacheIsPrimary = false; 302 } 165 303 break; 166 304 case CINETAccount::eACAP: 167 305 mClient = new CACAPClient(NULL, this); 306 if (CanDisconnect()) 307 { 308 InitOfflineCWD(); 309 mCacheClient = new CLocalVCardClient(this); 310 mCacheIsPrimary = false; 311 } 312 break; 313 case CINETAccount::eCardDAVAdbk: 314 mClient = new CCardDAVVCardClient(NULL, this); 315 if (CanDisconnect()) 316 { 317 InitOfflineCWD(); 318 mCacheClient = new CLocalVCardClient(this); 319 mCacheIsPrimary = false; 320 } 168 321 break; 169 322 default:; … … 175 328 SetFlags(eDisconnected, true); 176 329 InitDisconnect(); 177 mClient = new CLocal AdbkClient(this);178 static_cast<CLocal AdbkClient*>(mClient)->SetRecorder(mRecorder);330 mClient = new CLocalVCardClient(this); 331 static_cast<CLocalVCardClient*>(mClient)->SetRecorder(mRecorder); 179 332 } 180 333 break; … … 183 336 SetFlags(eDisconnected, false); 184 337 InitOffline(); 338 #ifdef USE_LOCAL_VCARDS 339 mClient = new CLocalVCardClient(this); 340 #else 185 341 mClient = new CLocalAdbkClient(this); 342 #endif 186 343 break; 187 344 #if __dest_os == __mac_os || __dest_os == __mac_os_x … … 210 367 else if (dynamic_cast<CACAPClient*>(copy_it)) 211 368 mClient = new CACAPClient(static_cast<const CACAPClient&>(*copy_it), NULL, this); 369 else if (dynamic_cast<CCardDAVVCardClient*>(copy_it)) 370 mClient = new CCardDAVVCardClient(static_cast<const CCardDAVVCardClient&>(*copy_it), this); 212 371 else if (dynamic_cast<CLocalAdbkClient*>(copy_it)) 213 372 mClient = new CLocalAdbkClient(static_cast<const CLocalAdbkClient&>(*copy_it), this); 373 else if (dynamic_cast<CLocalVCardClient*>(copy_it)) 374 mClient = new CLocalVCardClient(static_cast<const CLocalVCardClient&>(*copy_it), this); 214 375 #if __dest_os == __mac_os || __dest_os == __mac_os_x 215 376 #if PP_Target_Carbon … … 231 392 { 232 393 // Remove from local client 394 #ifdef USE_LOCAL_VCARDS 395 CLocalVCardClient* client = dynamic_cast<CLocalVCardClient*>(mClient); 396 #else 233 397 CLocalAdbkClient* client = dynamic_cast<CLocalAdbkClient*>(mClient); 398 #endif 234 399 if (client) 235 400 client->SetRecorder(NULL); … … 237 402 delete mRecorder; 238 403 mRecorder = NULL; 404 } 405 406 // Remove cache client 407 if (mCacheClient != NULL) 408 { 409 delete mCacheClient; 410 mCacheClient = NULL; 411 mCacheIsPrimary = false; 239 412 } 240 413 } … … 245 418 mClient = NULL; 246 419 CINETProtocol::mClient = NULL; 420 421 delete mCacheClient; 422 mCacheClient = NULL; 423 mCacheIsPrimary = false; 424 } 425 426 // Open connection to protocol server 427 void CAdbkProtocol::Open() 428 { 429 // Only bother if not already open 430 if (IsOpenAllowed() && IsNotOpen()) 431 { 432 // Get client to open 433 SetErrorProcess(false); 434 mClient->Open(); 435 if (mCacheClient != NULL) 436 mCacheClient->Open(); 437 mMPState = eINETOpen; 438 } 439 440 } 441 442 // Close connection to protocol server 443 void CAdbkProtocol::Close() 444 { 445 // Only bother if not already closed 446 if (IsNotOpen()) 447 return; 448 449 try 450 { 451 // Logoff if required 452 if (IsLoggedOn()) 453 Logoff(); 454 455 // Get client to close 456 mClient->Close(); 457 if (mCacheClient != NULL) 458 mCacheClient->Close(); 459 460 mMPState = eINETNotOpen; 461 SetErrorProcess(false); 462 463 // Clean any free connections in cache 464 CleanConnections(); 465 } 466 catch (...) 467 { 468 CLOG_LOGCATCH(...); 469 470 // Clean up and throw up 471 mMPState = eINETNotOpen; 472 SetErrorProcess(false); 473 474 // Clean any free connections in cache 475 CleanConnections(); 476 477 CLOG_LOGRETHROW; 478 throw; 479 } 480 } 481 482 // Logon to server 483 void CAdbkProtocol::Logon() 484 { 485 // No need to block since if its not logged in there can be no other network 486 // operation in progress. If it is logged in it won't issue a network call either. 487 488 if (IsOpenAllowed() && !IsLoggedOn()) 489 { 490 // Recovering after a failure should be on here as it can be turned off 491 // at logoff 492 SetNoRecovery(false); 493 494 // Get client to logon 495 mClient->Logon(); 496 if (mCacheClient != NULL) 497 mCacheClient->Logon(); 498 499 // Recache user id & password after successful logon 500 if (GetAccount()->GetAuthenticator().RequiresUserPswd()) 501 { 502 CAuthenticatorUserPswd* auth = GetAccount()->GetAuthenticatorUserPswd(); 503 504 // Only bother if it contains something 505 if (!auth->GetPswd().empty()) 506 SetCachedPswd(auth->GetUID(), auth->GetPswd()); 507 } 508 509 // Make copy of current authenticator 510 SetAuthenticatorUniqueness(GetAccount()->GetAuthenticator().GetUniqueness()); 511 512 // Add to list of periodic items 513 CMailControl::RegisterPeriodic(this, true); 514 515 mMPState = eINETLoggedOn; 516 SetErrorProcess(false); 517 518 // Broadcast change in state 519 Broadcast_Message(eBroadcast_Logon, this); 520 } 247 521 } 248 522 … … 250 524 void CAdbkProtocol::Logoff() 251 525 { 526 // Must block 527 cdmutex::lock_cdmutex _lock(_mutex); 528 252 529 if (IsLoggedOn()) 253 530 { 531 // Remove from list of periodic items 532 CMailControl::RegisterPeriodic(this, false); 533 534 // Do without errors appearing on screen as the user 535 // is not really interested in failures during logoff 536 bool old_error_alert = GetNoErrorAlert(); 537 SetNoErrorAlert(true); 538 539 // No point in recovering after a failure 540 SetNoRecovery(true); 541 254 542 try 255 543 { 256 // Tell listeners we are about to remove all address books 257 // Do this BEFORE logging out so that any pending address book changes can be committed 258 // whilst connection is still in place 259 Broadcast_Message(eBroadcast_ClearList, this); 260 261 // Do inherited 262 CINETProtocol::Logoff(); 263 264 // Remove address books 265 mAdbkList->erase_children(); 266 } 267 catch (...) 544 // Get client to logoff 545 mClient->Logoff(); 546 } 547 catch(...) 268 548 { 269 549 CLOG_LOGCATCH(...); 270 271 // Tell listeners we are about to remove all address books 272 Broadcast_Message(eBroadcast_ClearList, this); 273 274 // Always remove address books 275 mAdbkList->erase_children(); 276 277 CLOG_LOGRETHROW; 278 throw; 279 } 280 } 281 } 282 283 // Force off from protocol server 284 void CAdbkProtocol::Forceoff() 285 { 286 // Do inherited 287 CINETProtocol::Forceoff(); 288 289 // Tell listeners we are about to remove all address books 290 Broadcast_Message(eBroadcast_ClearList, this); 291 292 // Remove address books 293 mAdbkList->erase_children(); 294 } 295 296 // Set list title 297 void CAdbkProtocol::SetDescriptor(const char* desc) 298 { 299 cdstring* name = new cdstring(GetAccountName()); 300 mAdbkList->SetData(name); 301 302 CINETProtocol::SetDescriptor(desc); 303 } 304 305 char CAdbkProtocol::GetSeparator() const 306 { 307 switch(GetAccountType()) 308 { 309 case CINETAccount::eLocalAdbk: 310 case CINETAccount::eOSAdbk: 311 default: 312 return os_dir_delim; 313 case CINETAccount::eIMSP: 314 return '.'; 315 case CINETAccount::eACAP: 316 return '/'; 550 } 551 try 552 { 553 // Get client to logoff 554 if (mCacheClient != NULL) 555 mCacheClient->Logoff(); 556 } 557 catch(...) 558 { 559 CLOG_LOGCATCH(...); 560 } 561 SetNoErrorAlert(old_error_alert); 562 563 // Set flag 564 mMPState = eINETLoggedOff; 565 SetErrorProcess(false); 566 567 // Broadcast change in state 568 Broadcast_Message(eBroadcast_Logoff, this); 569 570 // Clean any free connections in cache 571 CleanConnections(); 317 572 } 318 573 } … … 325 580 case CINETAccount::eLocalAdbk: 326 581 case CINETAccount::eOSAdbk: 582 case CINETAccount::eCardDAVAdbk: 327 583 default: 328 584 return cdstring::null_str; … … 337 593 void CAdbkProtocol::LoadList() 338 594 { 339 // Check whether connected or not 340 if (IsDisconnected()) 595 // NB This protocol does not delete the list items when it logs out, so we 596 // need to do that here before reloading 597 598 // Tell listeners we are about to remove all calendar store nodes 599 Broadcast_Message(eBroadcast_ClearList, this); 600 601 // Remove calendar store nodes 602 mStoreRoot.Clear(); 603 604 // Check whether connected or not or whether we always read from local cache 605 if (IsDisconnected() || mCacheIsPrimary) 341 606 ReadAddressBooks(); 342 607 else 343 608 { 344 mClient->_FindAllAdbks(""); 609 mClient->_ListAddressBooks(&mStoreRoot); 610 611 // Always keep disconnected cache list in sync with server 612 if (mCacheClient != NULL) 613 { 614 DumpAddressBooks(); 615 } 345 616 346 617 // Look for default address book if remote … … 356 627 357 628 // Scan abooks for default 358 if (m AdbkList->HasChildren())359 for(CAd bkList::node_list::const_iterator niter = mAdbkList->GetChildren()->begin();360 !has_default && (niter != m AdbkList->GetChildren()->end()); niter++)629 if (mStoreRoot.CountDescendants()) 630 for(CAddressBookList::const_iterator niter = mStoreRoot.GetChildren()->begin(); 631 !has_default && (niter != mStoreRoot.GetChildren()->end()); niter++) 361 632 { 362 if ((*niter)->Is Selectable() && ((*niter)->GetSelectData()->GetName() == default_name))633 if ((*niter)->IsAdbk() && ((*niter)->GetName() == default_name)) 363 634 has_default = true; 364 635 } … … 368 639 { 369 640 // Add adress book to list 370 C RemoteAddressBook* adbk = new CRemoteAddressBook(this, default_name);641 CAddressBook* adbk = new CAddressBook(this, &mStoreRoot, true, false, default_name); 371 642 372 643 // Policy: