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/AddressBook/CAddressBook.cp

    r19 r86  
    2525 
    2626#include "CAddressBookManager.h" 
     27#include "CAdbkProtocol.h" 
    2728#include "CCharSpecials.h" 
     29#include "CLog.h" 
    2830#include "CMailControl.h" 
    2931#include "CPreferences.h" 
    3032#include "CStringUtils.h" 
    3133 
     34#include "CVCardStoreXML.h"                                     // Share XML defintions with calendar store 
     35#include "CVCardMapper.h" 
     36 
     37#include "CVCardAddressBook.h" 
     38#include "CVCardVCard.h" 
     39 
    3240#include <strstream> 
    3341 
     42#include "XMLDocument.h" 
     43#include "XMLNode.h" 
     44#include "XMLObject.h" 
     45 
     46using namespace vcardstore; 
     47 
    3448cdmutex CAddressBook::_mutex;                                                                           // Used for locks 
    3549 
    36 // Copy constructor 
    37 CAddressBook::CAddressBook(const CAddressBook& copy) 
    38 { 
    39         InitAddressBook(); 
    40          
    41         mAdbkName = copy.mAdbkName; 
    42         mFlags = copy.mFlags; 
     50// This constructs the address book manager root 
     51CAddressBook::CAddressBook() 
     52{ 
     53        mProtocol = NULL; 
     54        mParent = NULL; 
     55        mChildren = new CAddressBookList;                               // Root must always have list 
     56        mChildren->set_delete_data(false); 
     57        SetFlags(eIsProtocol, true); 
     58        SetFlags(eIsDirectory, true); 
     59        SetFlags(eHasExpanded, true); 
     60        mShortName = mName.c_str(); 
     61        mSize = ULONG_MAX; 
     62        mLastSync = 0; 
     63        mACLs = NULL; 
     64        mRefCount = 0; 
     65        mVCardAdbk = NULL; 
     66} 
     67 
     68// This constructs the root of a protocol 
     69CAddressBook::CAddressBook(CAdbkProtocol* proto) 
     70{ 
     71        mProtocol = proto; 
     72        mParent = &CAddressBookManager::sAddressBookManager->GetRoot(); 
     73        mChildren = NULL; 
     74        SetFlags(eIsProtocol, true); 
     75        SetFlags(eIsDirectory, true); 
     76        SetFlags(eHasExpanded, true); 
     77        mName = proto->GetAccountName(); 
     78        mShortName = mName.c_str(); 
     79        mSize = ULONG_MAX; 
     80        mLastSync = 0; 
     81        mACLs = NULL; 
     82        mVCardAdbk = NULL; 
     83} 
     84 
     85// This constructs an actual node 
     86CAddressBook::CAddressBook(CAdbkProtocol* proto, CAddressBook* parent, bool is_adbk, bool is_dir, const cdstring& name) 
     87{ 
     88        mProtocol = proto; 
     89        mParent = parent; 
     90        mChildren = NULL;                               // Root must always have list 
     91        SetFlags(eIsAdbk, is_adbk); 
     92        SetFlags(eIsDirectory, is_dir); 
     93        mName = name; 
     94        mSize = ULONG_MAX; 
     95        mLastSync = 0; 
     96        mACLs = NULL; 
     97        mRefCount = 0; 
     98        mVCardAdbk = NULL; 
     99 
     100        SetShortName(); 
    43101} 
    44102 
     
    46104CAddressBook::~CAddressBook() 
    47105{ 
    48         CAddressBookManager::sAddressBookManager->SyncAddressBook(this, false); 
    49  
     106        // Do not sync the store root 
     107        if (mProtocol != NULL) 
     108                CAddressBookManager::sAddressBookManager->SyncAddressBook(this, false); 
     109 
     110        // Deactivate/delete all children 
     111        Clear(); 
     112        ClearContents(); 
     113         
     114        delete mACLs; 
    50115        mACLs = NULL; 
    51116} 
    52117 
    53 // Initialization 
    54 void CAddressBook::InitAddressBook() 
    55 { 
    56         mACLs = NULL; 
    57         mRefCount = 0; 
     118cdstring CAddressBook::GetAccountName(bool multi) const 
     119{ 
     120        cdstring name; 
     121        if (multi) 
     122        { 
     123                name = mProtocol->GetAccountName(); 
     124                name += cMailAccountSeparator; 
     125        } 
     126        name += GetName(); 
     127        return name; 
     128} 
     129 
     130void CAddressBook::CheckSize() 
     131{ 
     132        GetProtocol()->SizeAdbk(this); 
     133} 
     134 
     135void CAddressBook::SyncNow() const 
     136{ 
     137        time_t now = ::time(NULL); 
     138        mLastSync = ::mktime(::gmtime(&now)); 
     139} 
     140 
     141bool CAddressBook::IsCached() const 
     142{ 
     143        // Cached if not disconnected or known to have  
     144        return !GetProtocol()->IsDisconnected() || mFlags.IsSet(eIsCached); 
     145} 
     146 
     147cdstring CAddressBook::GetURL(bool full) const 
     148{ 
     149        cdstring ruri = GetName(); 
     150        ruri.EncodeURL(GetProtocol()->GetDirDelim()); 
     151 
     152        cdstring result = mProtocol->GetURL(full); 
     153        result += "/"; 
     154        result += ruri; 
     155        return result; 
     156} 
     157 
     158void CAddressBook::AddChild(CAddressBook* child, bool sort) 
     159{ 
     160        // Create if required 
     161        if (mChildren == NULL) 
     162                mChildren = new CAddressBookList; 
     163        mChildren->push_back(child); 
     164        child->mParent = this; 
     165         
     166        // Setting a child means it has been expanded 
     167        SetFlags(eHasExpanded, true); 
     168         
     169        // Do sort if requested 
     170        if (sort) 
     171                SortChildren(); 
     172} 
     173 
     174void CAddressBook::AddChildHierarchy(CAddressBook* child, bool sort) 
     175{ 
     176        // Only do this if its the protocol root 
     177        if (mParent != &CAddressBookManager::sAddressBookManager->GetRoot()) 
     178                return; 
     179 
     180        // Break the name down into components 
     181        cdstrvect names; 
     182        const char* start = child->GetName().c_str(); 
     183        const char* end = ::strchr(start, mProtocol->GetDirDelim()); 
     184        while(end != NULL) 
     185        { 
     186                names.push_back(cdstring(start, end - start)); 
     187                start = end + 1; 
     188                end = ::strchr(start, mProtocol->GetDirDelim()); 
     189        } 
     190 
     191        // Find each path component 
     192        CAddressBook* parent = this; 
     193        cdstring path; 
     194        for(cdstrvect::const_iterator iter1 = names.begin(); iter1 != names.end(); iter1++) 
     195        { 
     196                // Get path component 
     197                if (!path.empty()) 
     198                        path += mProtocol->GetDirDelim(); 
     199                path += *iter1; 
     200                 
     201                // Find the node 
     202                bool found = false; 
     203                for(CAddressBookList::iterator iter2 = parent->GetChildren()->begin(); iter2 != parent->GetChildren()->end(); iter2++) 
     204                { 
     205                        if ((*iter2)->GetName() == path) 
     206                        { 
     207                                parent = *iter2; 
     208                                found = true; 
     209                                break; 
     210                        } 
     211                } 
     212                 
     213                // If not found, create a directory and make it the new parent 
     214                if (!found) 
     215                { 
     216                        CAddressBook* adbk = new CAddressBook(mProtocol, parent, false, true, path); 
     217                        parent->AddChild(adbk, sort); 
     218                        parent = adbk; 
     219                } 
     220        } 
     221 
     222        // Now add to actual parent 
     223        parent->AddChild(child, sort); 
     224} 
     225 
     226void CAddressBook::InsertChild(CAddressBook* child, uint32_t index, bool sort) 
     227{ 
     228        // Do ordinary add if no children or insert at end 
     229        if ((mChildren == NULL) || (index >= mChildren->size())) 
     230                AddChild(child, sort); 
     231        else 
     232        { 
     233                mChildren->insert(mChildren->begin() + index, child); 
     234                child->mParent = this; 
     235                 
     236                // Do sort if requested 
     237                if (sort) 
     238                        SortChildren(); 
     239        } 
     240} 
     241 
     242void CAddressBook::SortChildren() 
     243{ 
     244        if (mChildren == NULL) 
     245                return; 
     246         
     247        std::sort(mChildren->begin(), mChildren->end(), sort_by_name); 
     248} 
     249 
     250bool CAddressBook::sort_by_name(const CAddressBook* s1, const CAddressBook* s2) 
     251{ 
     252        return ::strcmpnocase(s1->GetShortName(), s2->GetShortName()) < 0; 
     253} 
     254 
     255CAddressBook* CAddressBook::FindNode(cdstrvect& hierarchy, bool discover) const 
     256{ 
     257        // Find top-level item matching last item in hierarchy 
     258        if (mChildren) 
     259        { 
     260                for(CAddressBookList::iterator iter = mChildren->begin(); iter != mChildren->end(); iter++) 
     261                { 
     262                        if (hierarchy.back() == (*iter)->GetShortName()) 
     263                        { 
     264                                hierarchy.pop_back(); 
     265                                if (hierarchy.empty()) 
     266                                        return *iter; 
     267                                else 
     268                                { 
     269                                        // May need discovery 
     270                                        if (discover && (*iter)->IsDirectory() && !(*iter)->HasExpanded()) 
     271                                                GetProtocol()->LoadSubList(*iter, false);                                        
     272                                        return (*iter)->FindNode(hierarchy, discover); 
     273                                } 
     274                        } 
     275                } 
     276        } 
     277         
     278        return NULL; 
     279} 
     280 
     281// Remove node from parent withtout deleting the node 
     282void CAddressBook::RemoveFromParent() 
     283{ 
     284        if (mParent) 
     285        { 
     286                CAddressBookList* list = mParent->GetChildren(); 
     287                CAddressBookList::iterator found = ::find(list->begin(), list->end(), this); 
     288                if (found != list->end()) 
     289                { 
     290                        // NULL it out so that the node is not deleted, then erase 
     291                        *found = NULL; 
     292                        list->erase(found); 
     293                } 
     294                 
     295                mParent = NULL; 
     296        } 
     297} 
     298 
     299void CAddressBook::Clear() 
     300{ 
     301        if (mChildren != NULL) 
     302        { 
     303                // Erase children 
     304                delete mChildren; 
     305                mChildren = NULL; 
     306        } 
     307} 
     308 
     309uint32_t CAddressBook::GetRow() const 
     310{ 
     311        // Look for sibling 
     312        uint32_t row = GetParentOffset(); 
     313        const CAddressBook* parent = mParent; 
     314        while(parent != NULL) 
     315        { 
     316                row += parent->GetParentOffset(); 
     317                parent = parent->mParent; 
     318        } 
     319         
     320        return row; 
     321} 
     322 
     323uint32_t CAddressBook::CountDescendants() const 
     324{ 
     325        uint32_t result = 0; 
     326        if (mChildren != NULL) 
     327        { 
     328                for(CAddressBookList::iterator iter = mChildren->begin(); iter != mChildren->end(); iter++) 
     329                        result += (*iter)->CountDescendants() + 1; 
     330        } 
     331         
     332        return result; 
     333} 
     334 
     335uint32_t CAddressBook::GetParentOffset() const 
     336{ 
     337        uint32_t result = 0; 
     338        if ((mParent != NULL) && mParent->HasInferiors()) 
     339        { 
     340                result++; 
     341                for(CAddressBookList::iterator iter = mParent->GetChildren()->begin(); iter != mParent->GetChildren()->end(); iter++) 
     342                { 
     343                        if (*iter == this) 
     344                                break; 
     345                         
     346                        result += (*iter)->CountDescendants() + 1; 
     347                } 
     348        } 
     349         
     350        return result; 
     351} 
     352 
     353const CAddressBook* CAddressBook::GetSibling() const 
     354{ 
     355        const CAddressBook* result = NULL; 
     356        if ((mParent != NULL) && mParent->HasInferiors()) 
     357        { 
     358                for(CAddressBookList::iterator iter = mParent->GetChildren()->begin(); iter != mParent->GetChildren()->end(); iter++) 
     359                { 
     360                        if (*iter == this) 
     361                                break; 
     362                         
     363                        result = *iter; 
     364                } 
     365        } 
     366         
     367        return result; 
     368} 
     369 
     370void CAddressBook::GetInsertRows(uint32_t& parent_row, uint32_t& sibling_row) const 
     371{ 
     372        // Get parent's row 
     373        parent_row = (mParent ? mParent->GetRow() : 0); 
     374 
     375        // Now get the sibling row 
     376        uint32_t parent_offset = GetParentOffset(); 
     377        if ((parent_offset != 0) && (GetSibling() != NULL)) 
     378        { 
     379                sibling_row = parent_row + parent_offset - GetSibling()->CountDescendants() - 1; 
     380        } 
     381        else 
     382                sibling_row = 0; 
     383} 
     384 
     385// Set pointer to short name 
     386void CAddressBook::SetShortName() 
     387{ 
     388        // Determine last directory break 
     389        const char* p = NULL; 
     390        if ((GetProtocol()->GetDirDelim() != 0) && ((p = ::strrchr(mName.c_str(), mProtocol->GetDirDelim())) != NULL)) 
     391                mShortName = ++p; 
     392        else 
     393                mShortName = mName.c_str(); 
     394} 
     395 
     396// Tell this and children to adjust names 
     397void CAddressBook::NewName(const cdstring& name) 
     398{ 
     399        // Adjust this one 
     400        SetName(name); 
     401         
     402        // Now iterate over children doing rename 
     403        if (mChildren != NULL) 
     404        { 
     405                for(CAddressBookList::iterator iter = mChildren->begin(); iter != mChildren->end(); iter++) 
     406                { 
     407                        (*iter)->ParentRenamed(); 
     408                } 
     409        } 
     410} 
     411 
     412// Tell children to adjust names when parent moves 
     413void CAddressBook::ParentRenamed() 
     414{ 
     415        // Must have a parent 
     416        if (mParent == NULL) 
     417                return; 
     418 
     419        // Adjust this node 
     420        cdstring new_name; 
     421        new_name = mParent->GetName(); 
     422        if (GetProtocol()->GetDirDelim()) 
     423                new_name += GetProtocol()->GetDirDelim(); 
     424        new_name += GetShortName(); 
     425        SetName(new_name); 
     426         
     427        // Now iterate over children doing rename 
     428        if (mChildren != NULL) 
     429        { 
     430                for(CAddressBookList::iterator iter = mChildren->begin(); iter != mChildren->end(); iter++) 
     431                { 
     432                        (*iter)->ParentRenamed(); 
     433                } 
     434        } 
     435} 
     436 
     437void CAddressBook::MoveAddressBook(const CAddressBook* dir, bool sibling) 
     438{ 
     439#ifdef TODO 
     440#endif 
     441} 
     442 
     443// Copy this address book into another one 
     444void CAddressBook::CopyAddressBook(CAddressBook* node) 
     445{ 
     446#ifdef TODO 
     447#endif 
     448} 
     449 
     450// Copy this address book's items into another one 
     451void CAddressBook::CopyAddressBookContents(CAddressBook* node) 
     452{ 
     453#ifdef TODO 
     454#endif 
     455} 
     456 
     457// Switch into disconnected mode 
     458void CAddressBook::TestDisconnectCache() 
     459{ 
     460        if (mChildren != NULL) 
     461        { 
     462                // Test each child recursively 
     463                for(CAddressBookList::iterator iter = mChildren->begin(); iter != mChildren->end(); iter++) 
     464                        (*iter)->TestDisconnectCache(); 
     465        } 
     466 
     467        // See if it exists locally 
     468        if (IsAdbk()) 
     469                SetFlags(eIsCached, mProtocol->TestAdbk(this)); 
    58470} 
    59471 
    60472#pragma mark ____________________________Opening/Closing 
    61473 
    62 void CAddressBook::SetName(const char* name) 
     474void CAddressBook::SetName(const cdstring& name) 
    63475{ 
    64476        // Remove from manager's cache 
    65         if (mAdbkName.length()) 
     477        if (mName.length()) 
    66478                CAddressBookManager::sAddressBookManager->SyncAddressBook(this, false); 
    67479 
    68         mAdbkName = name; 
    69         CAddressBookManager::sAddressBookManager->RefreshAddressBook(this); 
     480        mName = name; 
     481        SetShortName(); 
     482        //CAddressBookManager::sAddressBookManager->RefreshAddressBook(this); 
    70483 
    71484        // Add to manager's cache 
     
    93506} 
    94507 
    95 // New visual address book on source 
    96 void CAddressBook::New() 
    97 { 
    98         SetFlags(eOpen); 
    99 } 
    100  
    101508// Open visual address book from source 
    102509void CAddressBook::Open() 
    103510{ 
     511        // Bump reference count and open only if not already done 
     512        if (!OpenCount()) 
     513                return; 
     514 
     515        try 
     516        { 
     517                // NB We might have a vCard adbk if we've done searches whilst the address book is closed. 
     518                // If that is the case we want to discard everything and start from scratch. 
     519                if (mVCardAdbk != NULL) 
     520                        mVCardAdbk->Clear(); 
     521                else 
     522                        mVCardAdbk = new vCard::CVCardAddressBook(); 
     523 
     524                // Must remove any cached address lookups 
     525                mAddresses.clear(); 
     526                mGroups.clear(); 
     527 
     528                // Now open 
     529                mProtocol->OpenAdbk(this); 
     530 
     531                // Mark as open 
    104532        SetFlags(eOpen); 
    105  
    106         // Remove any cached addresses 
    107         //mAddresses.erase_all(); 
    108         //mGroups.erase_all(); 
    109 } 
    110  
    111 // Read in addresses 
    112 void CAddressBook::Read() 
    113 { 
    114         SetFlags(eLoaded); 
    115 } 
    116  
    117 // Save addresses 
    118 void CAddressBook::Save() 
    119 { 
     533        } 
     534        catch (...) 
     535        { 
     536                CLOG_LOGCATCH(...); 
     537                 
     538                delete mVCardAdbk; 
     539                mVCardAdbk = NULL; 
     540        } 
    120541} 
    121542 
     
    127548                return; 
    128549 
     550        // Bump reference count and close only if not open elsewhere 
     551        if (!CloseCount()) 
     552                return; 
     553 
     554        mProtocol->CloseAdbk(this); 
     555 
    129556        // Clean up the UI 
    130557        CMailControl::AddressBookClosed(this); 
    131558 
    132559        SetFlags(eOpen, false); 
    133         SetFlags(eLoaded, false); 
    134          
    135         Clear(); 
     560         
     561        ClearContents(); 
     562 
     563        delete mVCardAdbk; 
     564        mVCardAdbk = NULL; 
    136565} 
    137566 
     
    139568void CAddressBook::Rename(cdstring& new_name) 
    140569{ 
     570        mProtocol->RenameAdbk(this, new_name); 
     571 
    141572        // Remove from manager's cache 
    142573        CAddressBookManager::sAddressBookManager->SyncAddressBook(this, false); 
     
    145576        CPreferences::sPrefs->ChangeAddressBookSearch(this, false); 
    146577 
    147         mAdbkName = new_name; 
     578        mName = new_name; 
    148579 
    149580        // Add to manager's cache 
     
    155586 
    156587// Clear addresses 
    157 void CAddressBook::Clear() 
     588void CAddressBook::ClearContents() 
    158589{ 
    159590        mAddresses.clear(); 
    160591        mGroups.clear(); 
     592        if (mVCardAdbk != NULL) 
     593                mVCardAdbk->Clear(); 
    161594} 
    162595 
     
    172605        CPreferences::sPrefs->ChangeAddressBookLookup(this, false); 
    173606        CPreferences::sPrefs->ChangeAddressBookSearch(this, false); 
     607 
     608        // Now delete on server 
     609        mProtocol->DeleteAdbk(this); 
     610 
     611        // Remove from manager 
     612        //CAddressBookManager::sAddressBookManager->RemoveAddressBook(this); 
    174613} 
    175614 
     
    177616void CAddressBook::Empty() 
    178617{ 
    179         Clear(); 
    180 } 
    181  
     618        // Delete and recreate 
     619        mProtocol->DeleteAdbk(this); 
     620        mProtocol->CreateAdbk(this); 
     621         
     622        ClearContents(); 
     623} 
     624 
     625// Synchronise to local 
     626void CAddressBook::Synchronise(bool fast) 
     627{ 
     628        // Tell protocol to synchronise it 
     629        mProtocol->SynchroniseRemote(this, fast); 
     630} 
     631 
     632// Clear disconnected cache 
     633void CAddressBook::ClearDisconnect() 
     634{ 
     635        mProtocol->ClearDisconnect(this); 
     636} 
     637 
     638#ifdef _TODO 
    182639// Copy addresses and groups to another address book 
    183640void CAddressBook::CopyAll(CAddressBook* adbk) 
     
    201658void CAddressBook::Synchronise(bool fast) 
    202659{ 
     660        // Tell protocol to synchronise it 
     661        mProtocol->SynchroniseRemote(this, fast); 
    203662} 
    204663 
     
    206665void CAddressBook::ClearDisconnect() 
    207666{ 
     667        mProtocol->ClearDisconnect(this); 
    208668} 
    209669 
     
    211671void CAddressBook::SwitchDisconnect(CAdbkProtocol* local) 
    212672{ 
    213 } 
     673        // See if going into disconnected mode (i.e. local != NULL) 
     674        if (local) 
     675        { 
     676                // Set local flag 
     677                SetFlags(CAddressBook::eLocalAdbk); 
     678 
     679                // See if it exists locally 
     680                if (local->TestAdbk(this)) 
     681                        SetFlags(CAddressBook::eCachedAdbk); 
     682        } 
     683        else 
     684                // Remove disconnected flags 
     685                SetFlags(static_cast<CAddressBook::EFlags>(CAddressBook::eLocalAdbk | CAddressBook::eCachedAdbk), false); 
     686} 
     687#endif 
    214688 
    215689CAdbkAddress* CAddressBook::FindAddress(const char* name) 
     
    278752void CAddressBook::AddAddress(CAddressList* addrs, bool sorted) 
    279753{ 
     754        // Always update the internal cache and map the address to a vCard 
    280755        for(CAddressList::const_iterator iter = addrs->begin(); iter != addrs->end(); iter++) 
    281756        { 
    282                 if (IsLoaded()) 
    283                 { 
     757                if (IsOpen()) 
     758                { 
     759                        // Update internal cache 
    284760                        if (sorted) 
    285761                                mAddresses.push_back_sorted(*iter); 
    286762                        else 
    287763                                mAddresses.push_back(*iter); 
    288                 } 
    289                 else 
     764                         
     765                        // Map to vCard 
     766                        auto_ptr<vCard::CVCardVCard> vcard(vcardstore::GenerateVCard(GetVCardAdbk()->GetRef(), static_cast<CAdbkAddress*>(*iter), true)); 
     767                        GetVCardAdbk()->AddNewVCard(vcard.release()); 
     768                } 
     769        } 
     770 
     771        mProtocol->AddAddress(this, addrs); 
     772 
     773        // Do change notification 
     774        CMailControl::AddressAdded(this, addrs); 
     775 
     776        // Awlays delete data if not needed 
     777        for(CAddressList::const_iterator iter = addrs->begin(); iter != addrs->end(); iter++) 
     778        { 
     779                if (!IsOpen()) 
    290780                        delete *iter; 
    291781        } 
     
    295785void CAddressBook::AddUniqueAddresses(CAddressList& add) 
    296786{ 
    297