From f318d43d685eda47b653a28c82a5baffbfc7edd4 Mon Sep 17 00:00:00 2001 From: Steve Brokenshire Date: Sun, 4 Sep 2016 20:36:23 +0100 Subject: [PATCH] Implemented GetContactList in CardDAV2 class --- source/carddav2/carddav2.cpp | 279 +++++++++++++++++++++++++++++++++++ source/carddav2/carddav2.h | 1 + 2 files changed, 280 insertions(+) diff --git a/source/carddav2/carddav2.cpp b/source/carddav2/carddav2.cpp index 1d8f632..536afac 100644 --- a/source/carddav2/carddav2.cpp +++ b/source/carddav2/carddav2.cpp @@ -1172,6 +1172,126 @@ COServerResponse CardDAV2::GetContact(std::string Location, std::string *Contact COContactList CardDAV2::GetContactList(std::string SyncToken){ + COContactList ServerContactList; + + // Check if authentication was successful, otherwise don't do anything. + + if (AuthPassed == false){ + ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED; + ServerContactList.ServerResponse.EntityTag = ""; + ServerContactList.ServerResponse.SessionCode = 0; + ServerContactList.ServerResponse.ResultCode = 0; + ServerContactList.ServerResponse.ResultMessage = ""; + return ServerContactList; + } + + ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true); + ResetResults(); + + std::string SyncData; + + // TODO: Copy old code from CardDAV class as needed. + + if (SyncToken.size() > 0){ + + SyncData = "\n" + "\n" + ""; + SyncData.append(SyncToken); + SyncData.append("\n" + "1\n" + "\n" + " \n" + "\n" + ""); + + } else { + + SyncData = "\n" + "\n" + "1\n" + "\n" + " \n" + "\n" + ""; + + } + + string ServerAddressURL = BuildURL(ServerPrefix); + + std::cout << SyncData << std::endl; + + curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str()); + curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, SyncData.c_str()); + curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(SyncData.c_str())); + curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT"); + + HeaderList = curl_slist_append(HeaderList, "Content-Type: application/xml; charset=utf-8"); + HeaderList = curl_slist_append(HeaderList, "Depth: 1"); + + curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList); + + if (TestMode == true){ + SessionResult = curl_easy_perform(ConnectionSession); + } else { + SessionResult = curl_easy_perform(ConnectionSession); + } + + switch(SessionResult){ + case CURLE_OK: + SSLStatus = true; + SSLVerified = COSSL_VERIFIED; + break; + case CURLE_SSL_CACERT: + case CURLE_SSL_CONNECT_ERROR: + SSLStatus = true; + SSLVerified = COSSL_UNABLETOVERIFY; + break; + default: + break; + }; + + long SessionResponseCode = 0; + + curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode); + + if (SessionResponseCode == 207){ + AuthPassed = true; + ValidResponse = true; + } else if (SessionResponseCode == 403){ + AuthPassed = false; + ValidResponse = true; + } else if (SessionResponseCode >= 400){ + AuthPassed = false; + ValidResponse = true; + } else { + AuthPassed = false; + ValidResponse = false; + } + + if (ValidResponse == false || AuthPassed == false){ + ServerContactList.ServerResponse.RequestResult = COREQUEST_ERROR_SERVER; + ServerContactList.ServerResponse.EntityTag = ""; + ServerContactList.ServerResponse.SessionCode = SessionResult; + ServerContactList.ServerResponse.ResultCode = SessionResponseCode; + ServerContactList.ServerResponse.ResultMessage = ""; + return ServerContactList; + } + + CanProcess = true; + + ProcessContactData(&ServerContactList); + + ServerContactList.ServerResponse.RequestResult = COREQUEST_OK; + ServerContactList.ServerResponse.EntityTag = ""; + ServerContactList.ServerResponse.SessionCode = SessionResult; + ServerContactList.ServerResponse.ResultCode = SessionResponseCode; + ServerContactList.ServerResponse.ResultMessage = SessionErrorBuffer; + + return ServerContactList; + } bool CardDAV2::CanDoProcessing(){ @@ -1630,4 +1750,163 @@ vector CardDAV2::GetDAVHeader(){ return DAVHeaderList; +} + +void CardDAV2::ProcessContactData(COContactList *ContactList){ + + xmlDocPtr xmlCardDAVDoc; + xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0); + + xmlNodePtr MultiStatusNode; + xmlNodePtr ResponseNode; + xmlNodePtr ResponseDataNode; + xmlNodePtr PropStatNode; + xmlNodePtr ValueNode; + xmlNodePtr ETagNode; + xmlNodePtr StatusNode; + + std::string HREFValue; + std::string ETagValue; + std::string StatusValue; + std::string SyncValue; + + // Go through the document! + + MultiStatusNode = xmlCardDAVDoc->children; + + if (MultiStatusNode == nullptr){ + return; + } + + bool SyncTokenFound = false; + + // Tranverse through the catacombs of the response to get our ETag for the file and + // the server syncronisation token. + + for (ResponseNode = MultiStatusNode->children; + ResponseNode != nullptr; + ResponseNode = ResponseNode->next){ + + // Check if tag is response or sync-token. + + if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"response") || + !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:response") || + !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:response")){ + + COContactStatus ContactStatus = COCS_UNKNOWN; + + for (ResponseDataNode = ResponseNode->children; + ResponseDataNode != nullptr; + ResponseDataNode = ResponseDataNode->next){ + + if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"href") || + !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:href") || + !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:href")){ + + HREFValue = (const char*)ResponseDataNode->children->content; + + // Get the filename after the last forward slash. + + int LastSlash = 0; + + for (int HREFValueSeek = 0; HREFValueSeek < HREFValue.size(); HREFValueSeek++){ + + if (HREFValue[HREFValueSeek] == '/'){ + + LastSlash = HREFValueSeek; + + } + + } + + HREFValue = HREFValue.substr((LastSlash + 1)); + + } else if (!xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"propstat") || + !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"d:propstat") || + !xmlStrcmp(ResponseDataNode->name, (const xmlChar *)"D:propstat")){ + + for (PropStatNode = ResponseDataNode->children; + PropStatNode != nullptr; + PropStatNode = PropStatNode->next){ + + if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"prop") || + !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:prop") || + !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:prop")){ + + for (ETagNode = PropStatNode->children; + ETagNode != nullptr; + ETagNode = ETagNode->next){ + + if (!xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") || + !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag") || + !xmlStrcmp(ETagNode->name, (const xmlChar *)"getetag")){ + + ETagValue = (const char*)ETagNode->children->content; + + if (ETagValue.size() > 2 && ETagValue.substr(0,1) == "\""){ + ETagValue.erase((ETagValue.size() - 1),1); + ETagValue.erase(0,1); + } + + } + + + } + + } else if (!xmlStrcmp(PropStatNode->name, (const xmlChar *)"status") || + !xmlStrcmp(PropStatNode->name, (const xmlChar *)"d:status") || + !xmlStrcmp(PropStatNode->name, (const xmlChar *)"D:status")){ + + StatusValue = (const char*)PropStatNode->children->content; + + if (StatusValue == "HTTP/1.1 200 OK"){ + + ContactStatus = COCS_UPDATED; + + } else if (StatusValue == "HTTP/1.1 404 Not Found"){ + + ContactStatus = COCS_DELETED; + + } else { + + ContactStatus = COCS_UNKNOWN; + + } + + } + + } + + } + + } + + COContactData ContactInformation; + + ContactInformation.Location = HREFValue; + ContactInformation.Data = ETagValue; + ContactInformation.Status = ContactStatus; + + HREFValue.clear(); + ETagValue.clear(); + StatusValue.clear(); + + ContactList->ListData.push_back(ContactInformation); + + } else if (!xmlStrcmp(ResponseNode->name, (const xmlChar *)"sync-token") || + !xmlStrcmp(ResponseNode->name, (const xmlChar *)"d:sync-token") || + !xmlStrcmp(ResponseNode->name, (const xmlChar *)"D:sync-token")){ + + SyncValue = (const char*)ResponseNode->children->content; + + } + + } + + ContactList->SyncToken = SyncValue; + + xmlFreeDoc(xmlCardDAVDoc); + + return; + } \ No newline at end of file diff --git a/source/carddav2/carddav2.h b/source/carddav2/carddav2.h index ceca5c2..2698d5a 100644 --- a/source/carddav2/carddav2.h +++ b/source/carddav2/carddav2.h @@ -104,6 +104,7 @@ class CardDAV2 : public ConnectionObject { std::string GetUserPrincipalURI(); std::string GetAddressBookHomeURI(); std::string GetDefaultAddressBookURI(); + void ProcessContactData(COContactList *ContactList); #if defined(__APPLE__) #elif defined(__WIN32__) -- 2.39.2