Changeset 113

Show
Ignore:
Timestamp:
10/28/07 23:41:34 (1 year ago)
Author:
daboo
Message:

Calendar ctag handling. Don't list the calendars/address books when first starting up if
we have a fresh cache.

Location:
Mulberry/branches/v4.1d1/Sources_Common
Files:
25 modified

Legend:

Unmodified
Added
Removed
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/CCalendarStoreNode.cpp

    r86 r113  
    909909                xmllib::XMLObject::WriteValue(doc, xmlnode, cXMLElement_name, cdstring(GetShortName())); 
    910910                 
    911                 // Set last sync child node 
     911                // Set sync child nodes 
    912912                if (mLastSync != 0) 
    913913                        xmllib::XMLObject::WriteValue(doc, xmlnode, cXMLElement_lastsync, mLastSync); 
     
    974974                SetName(new_name); 
    975975 
    976                 // Get last sync 
     976                // Get sync details 
    977977                xmllib::XMLObject::ReadValue(xmlnode, cXMLElement_lastsync, mLastSync); 
    978978 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/CCalendarStoreNode.h

    r86 r113  
    264264        const char*                             mShortName;                                     // Pointer to the last part of the path name 
    265265        uint32_t                                mSize;                                          // Disk size 
    266         mutable uint32_t                mLastSync;                                      // Lasy sync time 
     266        mutable uint32_t                mLastSync;                                      // Last sync time 
    267267        SACLRight                               mMyRights;                                      // User's rights on this mailbox 
    268268        CCalendarACLList*               mACLs;                                          // List of ACLs on this mailbox 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/CCalendarStoreXML.cpp

    r19 r113  
    4141 
    4242        <!ELEMENT calendarlist  (calendarnode*) > 
    43         <!ATTLIST calendarlist  version                 CDATA   #REQUIRED > 
     43        <!ATTLIST calendarlist  version                 CDATA   #REQUIRED 
     44                                                        datestamp       CDATA   ""> 
    4445 
    4546        <!ELEMENT calendarnode  (name, last-sync?, webcal?, calendarnode*) > 
     
    6970const xmllib::XMLName cXMLElement_calendarlist("calendarlist"); 
    7071const char* cXMLAttribute_version = "version"; 
     72const char* cXMLAttribute_datestamp = "datestamp"; 
    7173 
    7274const xmllib::XMLName cXMLElement_calendarnode("calendarnode"); 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/CCalendarStoreXML.h

    r19 r113  
    3131extern const xmllib::XMLName cXMLElement_calendarlist; 
    3232extern const char*                       cXMLAttribute_version; 
     33extern const char*                       cXMLAttribute_datestamp; 
    3334extern const char*                       cXMLAttribute_has_expanded; 
    3435 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CCalDAVCalendarClient.cpp

    r96 r113  
    198198bool CCalDAVCalendarClient::_CalendarChanged(const CCalendarStoreNode& node, iCal::CICalendar& cal) 
    199199{ 
    200         // For CalDAV we always have to do a component sync 
    201         return true; 
     200        // Start UI action 
     201        StINETClientAction _action(this, "Status::Calendar::Checking", "Error::Calendar::OSErrCheckCalendar", "Error::Calendar::NoBadCheckCalendar", node.GetName()); 
     202 
     203        // Determine URL and lock 
     204        cdstring rurl = GetRURL(&node); 
     205        cdstring lock_token = GetLockToken(rurl); 
     206 
     207        // Get current CTag 
     208        cdstring ctag = GetProperty(rurl, lock_token, http::calendarserver::cProperty_getctag); 
     209         
     210        // Changed if ctags are different 
     211        return ctag.empty() || (ctag != cal.GetETag()); 
     212} 
     213 
     214void CCalDAVCalendarClient::_UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal) 
     215{ 
     216        // Start UI action 
     217        StINETClientAction _action(this, "Status::Calendar::Checking", "Error::Calendar::OSErrCheckCalendar", "Error::Calendar::NoBadCheckCalendar", node.GetName()); 
     218 
     219        // Determine URL and lock 
     220        cdstring rurl = GetRURL(&node); 
     221        cdstring lock_token = GetLockToken(rurl); 
     222 
     223        // Get current CTag 
     224        cdstring ctag = GetProperty(rurl, lock_token, http::calendarserver::cProperty_getctag); 
     225         
     226        cal.SetETag(ctag); 
    202227} 
    203228 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CCalDAVCalendarClient.h

    r86 r113  
    6262        virtual void _CreateCalendar(const CCalendarStoreNode& node); 
    6363        virtual bool _CalendarChanged(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
     64        virtual void _UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
    6465 
    6566        virtual void _ReadFullCalendar(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CCalendarClient.h

    r86 r113  
    6060        virtual bool _CheckCalendar(const CCalendarStoreNode& node, iCal::CICalendar& cal) = 0; 
    6161        virtual bool _CalendarChanged(const CCalendarStoreNode& node, iCal::CICalendar& cal) = 0; 
     62        virtual void _UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal) = 0; 
    6263        virtual void _SizeCalendar(CCalendarStoreNode& node) = 0; 
    6364 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CLocalCalendarClient.cpp

    r86 r113  
    486486} 
    487487 
     488void CLocalCalendarClient::_UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal) 
     489{ 
     490        // Nothing to do for local as this is only used when sync'ing with server 
     491} 
     492 
    488493void CLocalCalendarClient::_SizeCalendar(CCalendarStoreNode& node) 
    489494{ 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CLocalCalendarClient.h

    r86 r113  
    6868        virtual bool _CheckCalendar(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
    6969        virtual bool _CalendarChanged(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
     70        virtual void _UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
    7071        virtual void _SizeCalendar(CCalendarStoreNode& node); 
    7172         
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CWebDAVCalendarClient.cpp

    r96 r113  
    2929//#include "CDisplayItem.h" 
    3030#include "CGeneralException.h" 
     31#include "CPasswordManager.h" 
    3132#include "CStatusWindow.h" 
    3233#include "CStreamFilter.h" 
     
    568569} 
    569570 
     571void CWebDAVCalendarClient::_UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal) 
     572{ 
     573        // Start UI action 
     574        StINETClientAction _action(this, "Status::Calendar::Checking", "Error::Calendar::OSErrCheckCalendar", "Error::Calendar::NoBadCheckCalendar", node.GetName()); 
     575 
     576        // Determine URL and lock 
     577        cdstring rurl = GetRURL(&node); 
     578        cdstring lock_token = GetLockToken(rurl); 
     579 
     580        // Get current ETag 
     581        cdstring etag = GetETag(rurl, lock_token); 
     582         
     583        cal.SetETag(etag); 
     584} 
     585 
    570586void CWebDAVCalendarClient::_SizeCalendar(CCalendarStoreNode& node) 
    571587{ 
     
    11231139cdstring CWebDAVCalendarClient::GetETag(const cdstring& rurl, const cdstring& lock_token) 
    11241140{ 
     1141        cdstring result = GetProperty(rurl, lock_token, http::webdav::cProperty_getetag); 
     1142 
     1143        // Handle server bug: ETag value MUST be quoted per HTTP/1.1 €3.11 
     1144        if (!result.empty() && !result.isquoted()) 
     1145                result.quote(true); 
     1146 
     1147        return result; 
     1148} 
     1149 
     1150cdstring CWebDAVCalendarClient::GetProperty(const cdstring& rurl, const cdstring& lock_token, const xmllib::XMLName& property) 
     1151{ 
    11251152        cdstring result; 
    11261153 
    11271154        // Create WebDAV propfind 
    11281155        xmllib::XMLNameList props; 
    1129         props.push_back(http::webdav::cProperty_getetag); 
     1156        props.push_back(property); 
    11301157        auto_ptr<http::webdav::CWebDAVPropFind> request(new http::webdav::CWebDAVPropFind(this, rurl, http::webdav::eDepth0, props)); 
    11311158        http::CHTTPOutputDataString dout; 
     
    11421169 
    11431170                // Look at each propfind result and determine type of calendar 
     1171                cdstring decoded_rurl = rurl; 
     1172                decoded_rurl.DecodeURL(); 
    11441173                for(http::webdav::CWebDAVPropFindParser::CPropFindResults::const_iterator iter = parser.Results().begin(); iter != parser.Results().end(); iter++) 
    11451174                { 
     
    11491178                 
    11501179                        // Must match rurl 
    1151                         if (name.compare_end(rurl)) 
     1180                        if (name.compare_end(decoded_rurl)) 
    11521181                        { 
    1153                                 if ((*iter)->GetTextProperties().count(http::webdav::cProperty_getetag.FullName()) != 0) 
     1182                                if ((*iter)->GetTextProperties().count(property.FullName()) != 0) 
    11541183                                { 
    1155                                         result = (*(*iter)->GetTextProperties().find(http::webdav::cProperty_getetag.FullName())).second; 
    1156                                          
    1157                                         // Handle server bug: ETag value MUST be quoted per HTTP/1.1 €3.11 
    1158                                         if (!result.isquoted()) 
    1159                                                 result.quote(true); 
     1184                                        result = (*(*iter)->GetTextProperties().find(property.FullName())).second; 
    11601185                                        break; 
    11611186                                } 
     
    11661191        { 
    11671192                HandleHTTPError(request.get()); 
    1168                 return result; 
    11691193        } 
    11701194 
     
    11931217 
    11941218                // Look at each propfind result and extract any Hrefs 
     1219                cdstring decoded_rurl = rurl; 
     1220                decoded_rurl.DecodeURL(); 
    11951221                for(http::webdav::CWebDAVPropFindParser::CPropFindResults::const_iterator iter1 = parser.Results().begin(); iter1 != parser.Results().end(); iter1++) 
    11961222                { 
     
    12001226                 
    12011227                        // Must match rurl 
    1202                         if (name.compare_end(rurl)) 
     1228                        if (name.compare_end(decoded_rurl)) 
    12031229                        { 
    12041230                                if ((*iter1)->GetNodeProperties().count(propname.FullName()) != 0) 
     
    12421268 
    12431269                // Look at each principal-match result and return first one that is appropriate 
     1270                cdstring decoded_rurl = rurl; 
     1271                decoded_rurl.DecodeURL(); 
    12441272                for(http::webdav::CWebDAVPropFindParser::CPropFindResults::const_iterator iter1 = parser.Results().begin(); iter1 != parser.Results().end(); iter1++) 
    12451273                { 
     
    12471275                        cdstring name((*iter1)->GetResource()); 
    12481276                        name.DecodeURL(); 
    1249                         if ((parser.Results().size() > 1) && (name.find("/users/") == cdstring::npos)) 
    1250                                 continue; 
     1277                        //if ((parser.Results().size() > 1) && (name.find("/users/") == cdstring::npos)) 
     1278                        //      continue; 
    12511279                 
    12521280                        for(xmllib::XMLNameList::const_iterator iter2 = props.begin(); iter2 != props.end(); iter2++) 
     
    12631291                                } 
    12641292                        } 
     1293                         
     1294                        // We'll take the first one, whatever that is 
     1295                        break; 
    12651296                } 
    12661297        } 
     
    15281559                        return; 
    15291560                } 
     1561                 
     1562                // Recache user id & password after successful logon 
     1563                if (GetAccount()->GetAuthenticator().RequiresUserPswd()) 
     1564                { 
     1565                        CAuthenticatorUserPswd* auth = GetAccount()->GetAuthenticatorUserPswd(); 
     1566 
     1567                        // Only bother if it contains something 
     1568                        if (!auth->GetPswd().empty()) 
     1569                        { 
     1570                                CPasswordManager::GetManager()->AddPassword(GetAccount(), auth->GetPswd()); 
     1571                        } 
     1572                } 
    15301573        } 
    15311574         
     
    15561599 
    15571600                                // Get authorization object (prompt the user) and redo the request 
    1558                                 mAuthorization = GetAuthorization(first_time, request->GetResponseHeader(cHeaderWWWAuthenticate)); 
     1601                                cdstrvect hdrs; 
     1602                                mAuthorization = GetAuthorization(first_time, request->GetResponseHeaders(cHeaderWWWAuthenticate, hdrs)); 
    15591603                                 
    15601604                                // Check for auth cancellation 
     
    15741618                        } 
    15751619                         
     1620                        // Recache user id & password after successful logon 
     1621                        if (!first_time && GetAccount()->GetAuthenticator().RequiresUserPswd()) 
     1622                        { 
     1623                                CAuthenticatorUserPswd* auth = GetAccount()->GetAuthenticatorUserPswd(); 
     1624 
     1625                                // Only bother if it contains something 
     1626                                if (!auth->GetPswd().empty()) 
     1627                                { 
     1628                                        CPasswordManager::GetManager()->AddPassword(GetAccount(), auth->GetPswd()); 
     1629                                } 
     1630                        } 
     1631 
    15761632                        // If we get here we are complete with auth loop 
    15771633                        break; 
     
    16131669} 
    16141670 
    1615 CHTTPAuthorization* CWebDAVCalendarClient::GetAuthorization(bool first_time, const cdstring& www_authenticate) 
     1671CHTTPAuthorization* CWebDAVCalendarClient::GetAuthorization(bool first_time, const cdstrvect& www_authenticate) 
    16161672{ 
    16171673        // Loop while trying to authentciate 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CWebDAVCalendarClient.h

    r86 r113  
    7777        virtual bool _CheckCalendar(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
    7878        virtual bool _CalendarChanged(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
     79        virtual void _UpdateSyncToken(const CCalendarStoreNode& node, iCal::CICalendar& cal); 
    7980        virtual void _SizeCalendar(CCalendarStoreNode& node); 
    8081 
     
    121122        virtual void SetServerCapability(const cdstring& txt); 
    122123 
    123         virtual CHTTPAuthorization* GetAuthorization(bool first_time, const cdstring& www_authenticate); 
     124        virtual CHTTPAuthorization* GetAuthorization(bool first_time, const cdstrvect& www_authenticate); 
    124125                        bool CheckCurrentAuthorization() const; 
    125126        virtual void DoRequest(CHTTPRequestResponse* request); 
     
    141142 
    142143        cdstring GetETag(const cdstring& rurl, const cdstring& lock_token = cdstring::null_str); 
     144        cdstring GetProperty(const cdstring& rurl, const cdstring& lock_token, const xmllib::XMLName& property); 
    143145        cdstrvect GetHrefListProperty(const cdstring& rurl, const xmllib::XMLName& propname); 
    144146        bool GetSelfProperties(const cdstring& rurl, const xmllib::XMLNameList& props, cdstrmap& results); 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CWebDAVDefinitions.cpp

    r86 r113  
    195195} 
    196196 
    197 } 
     197namespace calendarserver 
     198{ 
     199const char*     cNamespace = "http://calendarserver.org/ns/"; 
     200 
     201        const xmllib::XMLName   cProperty_getctag("getctag", cNamespace); 
     202} 
     203 
     204} 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Clients/CWebDAVDefinitions.h

    r86 r113  
    196196} 
    197197 
     198namespace calendarserver 
     199{ 
     200extern const char*      cNamespace; 
     201 
     202        extern const xmllib::XMLName    cProperty_getctag; 
     203} 
     204 
    198205}       // namespace http 
    199206 
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Protocols/CCalendarProtocol.cpp

    r86 r113  
    3232#include "CConnectionManager.h" 
    3333#include "CLocalCalendarClient.h" 
     34#include "CPasswordManager.h" 
    3435#include "CPreferences.h" 
    3536#include "CWebDAVCalendarClient.h" 
     
    3839 
    3940#include "CICalendarSync.h" 
     41#include "CICalendarDateTime.h" 
     42#include "CICalendarDuration.h" 
    4043 
    4144#include "XMLDocument.h" 
     
    6063        mCacheIsPrimary = false; 
    6164        mSyncingList = false; 
     65        mListedFromCache = false; 
    6266 
    6367        // Only WebDAV servers can disconnect 
     
    482486                        // Only bother if it contains something 
    483487                        if (!auth->GetPswd().empty()) 
     488                        { 
    484489                                CCalendarProtocol::SetCachedPswd(auth->GetUID(), auth->GetPswd()); 
     490                                CPasswordManager::GetManager()->AddPassword(GetAccount(), auth->GetPswd()); 
     491                        } 
    485492                } 
    486493 
     
    569576        else 
    570577        { 
    571                 // Now get new list 
    572                 mClient->_ListCalendars(&mStoreRoot); 
    573  
    574                 // Always keep disconnected cache list in sync with server 
    575                 if (mCacheClient != NULL) 
    576                 { 
    577                         DumpCalendars(); 
    578                 } 
     578                // First try the disconnected cache - but only use if current 
     579                if (mListedFromCache || ((mCacheClient == NULL) || !ReadCalendars(true))) 
     580                { 
     581                        // Now get new list 
     582                        mClient->_ListCalendars(&mStoreRoot); 
     583 
     584                        // Always keep disconnected cache list in sync with server 
     585                        if (mCacheClient != NULL) 
     586                        { 
     587                                DumpCalendars(); 
     588                        } 
     589                } 
     590                else 
     591                        mListedFromCache = true; 
    579592        } 
    580593 
     
    10061019                //  2.1 Add new components to server and cache info 
    10071020                //  2.2 Remove deleted components from server and cached server info if still present on server 
    1008                 //  2.3 Cache info for changed items for later sync 
     1021                //  2.3 Cache info for changed items for later sync (or change them immediately if the server has not changed 
    10091022                // 
    10101023                // 3. Scan list of local components 
     
    10201033                // 4. Copy remaining items in server set to local cache - they are new items 
    10211034                // 
     1035                // We only need to do steps 3 & 4 if the data on the server is known to have changed. 
     1036                // 
    10221037                 
    10231038                // Now do it... 
     
    10251040                // Step 1 
    10261041                cdstrmap comps; 
    1027                 mClient->_GetComponentInfo(node, cal, comps); 
     1042                bool server_changed = mClient->_CalendarChanged(node, cal); 
     1043                if (server_changed) 
     1044                        mClient->_GetComponentInfo(node, cal, comps); 
     1045                else 
     1046                { 
     1047                        mCacheClient->_ReadFullCalendar(node, cal); 
     1048                } 
    10281049                 
    10291050                // Step 2 
     
    10631084                        // Step 2.3 
    10641085                        else if ((*iter).second.GetAction() == iCal::CICalendarComponentRecord::eChanged) 
    1065                                 cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1086                        { 
     1087                                if (server_changed) 
     1088                                        cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1089                                else 
     1090                                { 
     1091                                        // Change it on the server 
     1092                                        const iCal::CICalendarComponent* comp = cal.GetComponentByKey((*iter).first); 
     1093                                        mClient->_ChangeComponent(node, cal, *comp); 
     1094                                        cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1095                                } 
     1096                        } 
    10661097                } 
    10671098                 
    10681099                 
    10691100                // Now do sync 
    1070                  
    1071                 // Get component info from cache 
    1072                 iCal::CICalendarComponentDBList dbs;