Show
Ignore:
Timestamp:
07/09/07 10:02:18 (2 years ago)
Author:
daboo
Message:

Some 4.1 changes. Mostly vCard/CardDAV and CalDAV scheduling support.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Mulberry/branches/v4.1d1/Sources_Common/Mail/Protocols/CAdbkProtocol.cp

    r19 r86  
    2323#include "CActionManager.h" 
    2424#include "CAdbkClient.h" 
    25 #include "CAdbkList.h" 
     25#include "CAddressBook.h" 
    2626#include "CAddressBookManager.h" 
    2727#include "CConnectionManager.h" 
    2828#include "CIMSPClient.h" 
    2929#include "CLocalAdbkClient.h" 
     30#include "CLocalVCardClient.h" 
    3031#if __dest_os == __mac_os || __dest_os == __mac_os_x 
    3132#if PP_Target_Carbon 
     
    3435#endif 
    3536#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" 
    3744 
    3845#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 
     54using namespace vcardstore; 
    3955 
    4056// CAdbkProtocol: Handles quotas for all resources 
     
    4258// Constructor 
    4359CAdbkProtocol::CAdbkProtocol(CINETAccount* account) 
    44         : CINETProtocol(account) 
     60        : CINETProtocol(account), 
     61                mStoreRoot(this) 
    4562{ 
    4663        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 
    5069        switch(GetAccountType()) 
    5170        { 
    5271        case CINETAccount::eIMSP: 
    5372        case CINETAccount::eACAP: 
    54                 SetFlags(eCanDisconnect, IsOfflineAllowed() && 
    55                                                                         GetAddressAccount()->GetDisconnected()); 
     73        case CINETAccount::eCardDAVAdbk: 
     74                SetFlags(eCanDisconnect, IsOfflineAllowed() && GetAddressAccount()->GetDisconnected()); 
    5675                break; 
    5776        default: 
     
    6180        } 
    6281 
     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 
    63103        mRecorder = NULL; 
    64104 
     
    68108// Copy constructor 
    69109CAdbkProtocol::CAdbkProtocol(const CAdbkProtocol& copy, bool force_local, bool force_remote) 
    70         : CINETProtocol(copy) 
     110        : CINETProtocol(copy), 
     111                mStoreRoot(this) 
    71112{ 
    72113        // Init instance variables 
    73114        mClient = NULL; 
    74         mAdbkList = new CAdbkList(false); 
     115        mCacheClient = NULL; 
     116        mCacheIsPrimary = false; 
    75117 
    76118        mRecorder = NULL;                               // Only original proto uses this - clones do not 
     119 
     120        mDirDelim = copy.mDirDelim; 
    77121 
    78122        // Copy client 
    79123        if (((GetAccountType() == CINETAccount::eIMSP) || 
    80                  (GetAccountType() == CINETAccount::eACAP)) 
     124                 (GetAccountType() == CINETAccount::eACAP) || 
     125                 (GetAccountType() == CINETAccount::eCardDAVAdbk)) 
    81126                && (force_local || force_remote)) 
    82127        { 
     
    89134                        case CINETAccount::eIMSP: 
    90135                                mClient = new CIMSPClient(NULL, this); 
     136                                if (CanDisconnect()) 
     137                                { 
     138                                        InitOfflineCWD(); 
     139                                        mCacheClient = new CLocalVCardClient(this); 
     140                                        mCacheIsPrimary = false; 
     141                                } 
    91142                                break; 
    92143                        case CINETAccount::eACAP: 
    93144                                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                                } 
    94160                                break; 
    95161                        default:; 
     
    101167                        SetFlags(eDisconnected, true); 
    102168                        InitDisconnect(); 
    103                         mClient = new CLocalAdbkClient(this); 
    104                         static_cast<CLocalAdbkClient*>(mClient)->SetRecorder(mRecorder); 
     169                        mClient = new CLocalVCardClient(this); 
     170                        static_cast<CLocalVCardClient*>(mClient)->SetRecorder(mRecorder); 
    105171                } 
    106172                CINETProtocol::mClient = mClient; 
     
    114180CAdbkProtocol::~CAdbkProtocol() 
    115181{ 
     182        // Clear nodes first to ensure any active nodes write themselves out before the 
     183        // client is deleted 
     184        mStoreRoot.Clear(); 
     185 
    116186        // Delete client 
    117187        RemoveClient(); 
    118  
    119         delete mAdbkList; 
    120         mAdbkList = NULL; 
    121188 
    122189        // Delete recorder 
     
    136203        case CINETAccount::eIMSP: 
    137204        case CINETAccount::eACAP: 
     205        case CINETAccount::eCardDAVAdbk: 
    138206                SetFlags(eCanDisconnect, IsOfflineAllowed() && 
    139207                                                                        GetAddressAccount()->GetDisconnected()); 
     
    144212        } 
    145213 
     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 
     260void 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        } 
    146277} 
    147278 
     
    155286        case CINETAccount::eIMSP: 
    156287        case CINETAccount::eACAP: 
    157                 if (CConnectionManager::sConnectionManager.IsConnected() || !CanDisconnect()) 
     288        case CINETAccount::eCardDAVAdbk: 
     289                if (CConnectionManager::sConnectionManager.IsConnected() && !IsForceDisconnect() || !CanDisconnect()) 
    158290                { 
    159291                        SetFlags(eIsOffline, false); 
     
    163295                        case CINETAccount::eIMSP: 
    164296                                mClient = new CIMSPClient(NULL, this); 
     297                                if (CanDisconnect()) 
     298                                { 
     299                                        InitOfflineCWD(); 
     300                                        mCacheClient = new CLocalVCardClient(this); 
     301                                        mCacheIsPrimary = false; 
     302                                } 
    165303                                break; 
    166304                        case CINETAccount::eACAP: 
    167305                                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                                } 
    168321                                break; 
    169322                        default:; 
     
    175328                        SetFlags(eDisconnected, true); 
    176329                        InitDisconnect(); 
    177                         mClient = new CLocalAdbkClient(this); 
    178                         static_cast<CLocalAdbkClient*>(mClient)->SetRecorder(mRecorder); 
     330                        mClient = new CLocalVCardClient(this); 
     331                        static_cast<CLocalVCardClient*>(mClient)->SetRecorder(mRecorder); 
    179332                } 
    180333                break; 
     
    183336                SetFlags(eDisconnected, false); 
    184337                InitOffline(); 
     338#ifdef USE_LOCAL_VCARDS 
     339                mClient = new CLocalVCardClient(this); 
     340#else 
    185341                mClient = new CLocalAdbkClient(this); 
     342#endif 
    186343                break; 
    187344#if __dest_os == __mac_os || __dest_os == __mac_os_x 
     
    210367        else if (dynamic_cast<CACAPClient*>(copy_it)) 
    211368                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); 
    212371        else if (dynamic_cast<CLocalAdbkClient*>(copy_it)) 
    213372                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); 
    214375#if __dest_os == __mac_os || __dest_os == __mac_os_x 
    215376#if PP_Target_Carbon 
     
    231392        { 
    232393                // Remove from local client 
     394#ifdef USE_LOCAL_VCARDS 
     395                CLocalVCardClient* client = dynamic_cast<CLocalVCardClient*>(mClient); 
     396#else 
    233397                CLocalAdbkClient* client = dynamic_cast<CLocalAdbkClient*>(mClient); 
     398#endif 
    234399                if (client) 
    235400                        client->SetRecorder(NULL); 
     
    237402                delete mRecorder; 
    238403                mRecorder = NULL; 
     404        } 
     405         
     406        // Remove cache client 
     407        if (mCacheClient != NULL) 
     408        { 
     409                delete mCacheClient; 
     410                mCacheClient = NULL; 
     411                mCacheIsPrimary = false; 
    239412        } 
    240413} 
     
    245418        mClient = NULL; 
    246419        CINETProtocol::mClient = NULL; 
     420         
     421        delete mCacheClient; 
     422        mCacheClient = NULL; 
     423        mCacheIsPrimary = false; 
     424} 
     425 
     426// Open connection to protocol server 
     427void 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 
     443void 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 
     483void 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        } 
    247521} 
    248522 
     
    250524void CAdbkProtocol::Logoff() 
    251525{ 
     526        // Must block 
     527        cdmutex::lock_cdmutex _lock(_mutex); 
     528 
    252529        if (IsLoggedOn()) 
    253530        { 
     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 
    254542                try 
    255543                { 
    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(...) 
    268548                { 
    269549                        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(); 
    317572        } 
    318573} 
     
    325580        case CINETAccount::eLocalAdbk: 
    326581        case CINETAccount::eOSAdbk: 
     582        case CINETAccount::eCardDAVAdbk: 
    327583        default: 
    328584                return cdstring::null_str; 
     
    337593void CAdbkProtocol::LoadList() 
    338594{ 
    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) 
    341606                ReadAddressBooks(); 
    342607        else 
    343608        { 
    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                } 
    345616 
    346617                // Look for default address book if remote 
     
    356627 
    357628                        // Scan abooks for default 
    358                         if (mAdbkList->HasChildren()) 
    359                                 for(CAdbkList::node_list::const_iterator niter = mAdbkList->GetChildren()->begin(); 
    360                                         !has_default && (niter != mAdbkList->GetChildren()->end()); niter++) 
     629                        if (mStoreRoot.CountDescendants()) 
     630                                for(CAddressBookList::const_iterator niter = mStoreRoot.GetChildren()->begin(); 
     631                                        !has_default && (niter != mStoreRoot.GetChildren()->end()); niter++) 
    361632                                { 
    362                                         if ((*niter)->IsSelectable() && ((*niter)->GetSelectData()->GetName() == default_name)) 
     633                                        if ((*niter)->IsAdbk() && ((*niter)->GetName() == default_name)) 
    363634                                                has_default = true; 
    364635                                } 
     
    368639                        { 
    369640                                // Add adress book to list 
    370                                 CRemoteAddressBook* adbk = new CRemoteAddressBook(this, default_name); 
     641                                CAddressBook* adbk = new CAddressBook(this, &mStoreRoot, true, false, default_name); 
    371642                                 
    372643                                // Policy: