// CardDAV2.cpp - CardDAV v2 class
//
// (c) 2012-2016 Xestia Software Development.
//
// This file is part of Xestia Address Book.
//
// Xestia Address Book is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by the
// Free Software Foundation, version 3 of the license.
//
// Xestia Address Book is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with Xestia Address Book. If not, see
#include "carddav2.h"
using namespace std;
CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL){
this->ServerAddress = ServerAddress;
this->ServerPort = ServerPort;
this->ServerUser = ServerUser;
this->ServerPass = ServerPass;
this->ServerSSL = ServerSSL;
TestMode = true;
this->SetupConnectionObject();
}
CardDAV2::CardDAV2(string ServerAddress, int ServerPort, string ServerUser, string ServerPass, bool ServerSSL, string ServerPrefix, string ServerAccount){
this->ServerAddress = ServerAddress;
this->ServerPort = ServerPort;
this->ServerUser = ServerUser;
this->ServerPass = ServerPass;
this->ServerSSL = ServerSSL;
this->ServerPrefix = ServerPrefix;
this->ServerAccount = ServerAccount;
TestMode = false;
this->SetupConnectionObject();
}
size_t CardDAV2::WritebackFunc(char *ptr, size_t size, size_t nmemb, void *stream){
return static_cast(stream)->CardDAV2Object->WritebackFuncImplementation(ptr, size, nmemb, stream);
}
size_t CardDAV2::WritebackFuncImplementation(char *ptr, size_t size, size_t nmemb, void *stream){
// Writeback function for the CardDAV object.
CardDAV2PassObject *data = static_cast(stream);
data->DataSetting->append(ptr);
// Get the SSL engine pointer and trust if required on certain operating systems.
if (data->ServerUsingSSL == true) {
#if defined(__APPLE__)
const struct curl_tlssessioninfo *TLSInfo;
CURLcode TLSCode;
TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
SecTrustRef CertificateData;
if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &CertificateData);
data->SSLContext = CertificateData;
}
#elif defined(__WIN32__)
const struct curl_tlssessioninfo *TLSInfo;
CURLcode TLSCode;
TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo);
if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) {
// Free the previous certificate data.
//CertFreeCertificateContext(CertificateData);
PCCERT_CONTEXT CertificateData;
PCtxtHandle SSLHandle = (PCtxtHandle)TLSInfo->internals;
SECURITY_STATUS GetData = QueryContextAttributes(SSLHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &CertificateData);
data->SSLContext = CertificateData;
}
#endif
}
return size * nmemb;
}
void CardDAV2::SetCertificateData() {
}
CardDAV2::~CardDAV2(){
curl_easy_cleanup(ConnectionSession);
ConnectionSession = nullptr;
if (HeaderList != nullptr){
curl_slist_free_all(HeaderList);
HeaderList = nullptr;
}
#if defined(__WIN32__)
if (CertificateData != nullptr) {
CertFreeCertificateContext(CertificateData);
}
#endif
}
#if defined(__APPLE__)
SecTrustRef CardDAV2::BuildSSLCollection(){
return CertificateData;
}
#elif defined(__WIN32__)
PCCERT_CONTEXT CardDAV2::BuildSSLCollection(){
return CertificateData;
}
#else
SSLCertCollectionString CardDAV2::BuildSSLCollection(){
// Build and return the SSL collection.
SSLCertCollectionString SSLCertInfo;
// Grab the certificate data.
union {
struct curl_slist *certdata;
struct curl_certinfo *certinfo;
} certptr;
certptr.certdata = NULL;
CURLcode result = curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo);
std::string CertPropName;
std::string CertPropValue;
for (int i = 0; i < certptr.certinfo->num_of_certs; i++){
struct curl_slist *slist;
SSLCertDataString SSLCertDataInc;
for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){
// Using wxStringTokenizer from wxWidgets.
wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":");
// Get first token as the property name.
CertPropName = CertDataInc.GetNextToken().ToStdString();
// Get remaining tokens as the property value.
while(CertDataInc.HasMoreTokens()){
CertPropValue.append(CertDataInc.GetNextToken());
}
SSLCertDataInc.CertData.insert(std::make_pair(CertPropName, CertPropValue));
CertPropName.clear();
CertPropValue.clear();
}
SSLCertInfo.SSLCollection.insert(std::make_pair(i, SSLCertDataInc));
}
return SSLCertInfo;
}
#endif
void CardDAV2::BypassSSLVerification(bool EnableBypass) {
EnableSSLBypass = EnableBypass;
SSLSelfSigned = EnableBypass;
}
void CardDAV2::SetupConnectionObject(){
ConnectionSession = curl_easy_init();
}
bool CardDAV2::IsTaskCompleted(){
return false;
}
COConnectResult CardDAV2::Connect(bool DoAuthentication){
ServerSSL ? SetupDefaultParametersSSL(DoAuthentication) : SetupDefaultParametersNonSSL(DoAuthentication);
ResetResults();
COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL;
string ServerAddressURL = BuildURL("/principals/");
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
if (TestMode == true){
SessionResult = curl_easy_perform(ConnectionSession);
} else {
SessionResult = curl_easy_perform(ConnectionSession);
}
switch(SessionResult){
case CURLE_OK:
case CURLE_HTTP_RETURNED_ERROR:
SSLStatus = true;
SSLVerified = COSSL_VERIFIED;
ConnectResult = COCONNECT_OK;
break;
case CURLE_SSL_CACERT:
case CURLE_SSL_CONNECT_ERROR:
SSLStatus = true;
ConnectResult = COCONNECT_OK;
SSLVerified = COSSL_UNABLETOVERIFY;
break;
default:
ConnectResult = COCONNECT_INVALID;
break;
};
// Set the certificate data (if required).
#if defined(__APPLE__)
if (ServerSSL) {
CertificateData = PageHeaderObject.SSLContext;
}
#elif defined(__WIN32__)
if (ServerSSL) {
CertificateData = PageHeaderObject.SSLContext;
}
#endif
// Check if an error occured before continuing.
// Check if authentication was successful.
long SessionResponseCode = 0;
curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
if (DoAuthentication == true){
// Get the HTTP status code (Should be 200 and not 403).
// Return error otherwise.
if (SessionResponseCode == 200){
ConnectResult = COCONNECT_OK;
AuthPassed = true;
ValidResponse = true;
} else if (SessionResponseCode == 401){
ConnectResult = COCONNECT_AUTHFAIL;
AuthPassed = false;
ValidResponse = true;
} else if (SessionResponseCode >= 200) {
ConnectResult = COCONNECT_INVALID;
AuthPassed = false;
ValidResponse = true;
} else {
ConnectResult = COCONNECT_INVALID;
AuthPassed = false;
ValidResponse = false;
}
} else {
ValidResponse = true;
}
// Check the header to see if CardDAV is supported.
vector DAVHeaderValues = GetDAVHeader();
for (vector::iterator DAVHeaderValuesIter = DAVHeaderValues.begin();
DAVHeaderValuesIter != DAVHeaderValues.end(); DAVHeaderValuesIter++){
if ((*DAVHeaderValuesIter) == "addressbook"){
CanProcess = true;
break;
}
}
return ConnectResult;
}
COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
// Need to do three requests:
// 1. Get the current user principal URI.
// 2. Get the address book home URI.
// 3. Get the default address book URI.
// Setup the first query finding out where the principal URL is.
const char* CurrentUserPrincipalXMLQuery = "\n"
"\n"
" "
" \n"
" "
"";
// Setup the second query finding out where the address book home URL is.
const char* AddressBookHomeXMLQuery = "\n"
"\n"
" \n"
" \n"
" \n"
"";
// Setup the third query finding out where the default address book URL is.
const char* DefaultAddressBookXMLQuery = "\n"
"\n"
" \n"
" \n"
" \n"
"";
string ServerAddressURL = BuildURL("/principals/");
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, CurrentUserPrincipalXMLQuery);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(CurrentUserPrincipalXMLQuery));
if (TestMode == true){
SessionResult = curl_easy_perform(ConnectionSession);
} else {
}
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 == 200 || 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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
// Process the first response.
string UserPrincipalURI = GetUserPrincipalURI();
// Cleanup and reset for the second connection.
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
ServerAddressURL = BuildURL(UserPrincipalURI);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, AddressBookHomeXMLQuery);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(AddressBookHomeXMLQuery));
if (TestMode == true){
SessionResult = curl_easy_perform(ConnectionSession);
} else {
}
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;
};
SessionResponseCode = 0;
curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
if (SessionResponseCode == 200 || 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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
// Process the second response.
string AddressBookHomeURI = GetAddressBookHomeURI();
// Cleanup and reset for the second connection.
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
ServerAddressURL = BuildURL(AddressBookHomeURI);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PROPFIND");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, DefaultAddressBookXMLQuery);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(DefaultAddressBookXMLQuery));
if (TestMode == true){
SessionResult = curl_easy_perform(ConnectionSession);
} else {
}
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;
};
SessionResponseCode = 0;
curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode);
if (SessionResponseCode == 200 || SessionResponseCode == 207){
AuthPassed = true;
ValidResponse = true;
} else if (SessionResponseCode == 403){
AuthPassed = false;
ValidResponse = true;
} else if (SessionResponseCode >= 200) {
AuthPassed = false;
ValidResponse = true;
} else {
AuthPassed = false;
ValidResponse = false;
}
if (ValidResponse == false || AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
// Process the second response.
(*ServerPrefix) = GetDefaultAddressBookURI();
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
return ServerResponse;
}
std::string CardDAV2::GetUserPrincipalURI(){
xmlDocPtr xmlCardDAVDoc;
xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
string UserPrincipalURI = "";
xmlNodePtr nodeLevel1;
xmlNodePtr nodeLevel2;
xmlNodePtr nodeLevel3;
xmlNodePtr nodeLevel4;
xmlNodePtr nodeLevel5;
xmlNodePtr nodeLevel6;
xmlNodePtr nodeLevel7;
for (nodeLevel1 = xmlCardDAVDoc->children;
nodeLevel1 != NULL;
nodeLevel1 = nodeLevel1->next)
{
for (nodeLevel2 = nodeLevel1->children;
nodeLevel2 != NULL;
nodeLevel2 = nodeLevel2->next)
{
for (nodeLevel3 = nodeLevel2->children;
nodeLevel3 != NULL;
nodeLevel3 = nodeLevel3->next)
{
for (nodeLevel4 = nodeLevel3->children;
nodeLevel4 != NULL;
nodeLevel4 = nodeLevel4->next)
{
for (nodeLevel5 = nodeLevel4->children;
nodeLevel5 != NULL;
nodeLevel5 = nodeLevel5->next)
{
for (nodeLevel6 = nodeLevel5->children;
nodeLevel6 != NULL;
nodeLevel6 = nodeLevel6->next)
{
if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
){
// Found the part so extract the principal URL address.
for (nodeLevel7 = nodeLevel6->children;
nodeLevel7 != NULL;
nodeLevel7 = nodeLevel7->next)
{
UserPrincipalURI = ((const char*)nodeLevel7->content);
}
}
}
}
}
}
}
}
xmlFreeDoc(xmlCardDAVDoc);
return UserPrincipalURI;
}
std::string CardDAV2::GetAddressBookHomeURI(){
xmlDocPtr xmlCardDAVDoc;
xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
string AddressBookHomeURI = "";
xmlNodePtr nodeLevel1;
xmlNodePtr nodeLevel2;
xmlNodePtr nodeLevel3;
xmlNodePtr nodeLevel4;
xmlNodePtr nodeLevel5;
xmlNodePtr nodeLevel6;
xmlNodePtr nodeLevel7;
for (nodeLevel1 = xmlCardDAVDoc->children;
nodeLevel1 != NULL;
nodeLevel1 = nodeLevel1->next)
{
for (nodeLevel2 = nodeLevel1->children;
nodeLevel2 != NULL;
nodeLevel2 = nodeLevel2->next)
{
for (nodeLevel3 = nodeLevel2->children;
nodeLevel3 != NULL;
nodeLevel3 = nodeLevel3->next)
{
for (nodeLevel4 = nodeLevel3->children;
nodeLevel4 != NULL;
nodeLevel4 = nodeLevel4->next)
{
for (nodeLevel5 = nodeLevel4->children;
nodeLevel5 != NULL;
nodeLevel5 = nodeLevel5->next)
{
for (nodeLevel6 = nodeLevel5->children;
nodeLevel6 != NULL;
nodeLevel6 = nodeLevel6->next)
{
if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
){
// Found the part so extract the principal URL address.
for (nodeLevel7 = nodeLevel6->children;
nodeLevel7 != NULL;
nodeLevel7 = nodeLevel7->next)
{
AddressBookHomeURI = ((const char*)nodeLevel7->content);
}
}
}
}
}
}
}
}
xmlFreeDoc(xmlCardDAVDoc);
return AddressBookHomeURI;
}
std::string CardDAV2::GetDefaultAddressBookURI(){
xmlDocPtr xmlCardDAVDoc;
xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
string DefaultAddressBookURI = "";
xmlNodePtr nodeLevel1;
xmlNodePtr nodeLevel2;
xmlNodePtr nodeLevel3;
xmlNodePtr nodeLevel4;
xmlNodePtr nodeLevel5;
xmlNodePtr nodeLevel6;
xmlNodePtr nodeLevel7;
for (nodeLevel1 = xmlCardDAVDoc->children;
nodeLevel1 != NULL;
nodeLevel1 = nodeLevel1->next)
{
for (nodeLevel2 = nodeLevel1->children;
nodeLevel2 != NULL;
nodeLevel2 = nodeLevel2->next)
{
for (nodeLevel3 = nodeLevel2->children;
nodeLevel3 != NULL;
nodeLevel3 = nodeLevel3->next)
{
for (nodeLevel4 = nodeLevel3->children;
nodeLevel4 != NULL;
nodeLevel4 = nodeLevel4->next)
{
for (nodeLevel5 = nodeLevel4->children;
nodeLevel5 != NULL;
nodeLevel5 = nodeLevel5->next)
{
for (nodeLevel6 = nodeLevel5->children;
nodeLevel6 != NULL;
nodeLevel6 = nodeLevel6->next)
{
if (!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"d:href") ||
!xmlStrcmp(nodeLevel6->name, (const xmlChar *)"D:href")
){
// Found the part so extract the principal URL address.
for (nodeLevel7 = nodeLevel6->children;
nodeLevel7 != NULL;
nodeLevel7 = nodeLevel7->next)
{
DefaultAddressBookURI = ((const char*)nodeLevel7->content);
}
}
}
}
}
}
}
}
xmlFreeDoc(xmlCardDAVDoc);
return DefaultAddressBookURI;
}
COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
string ServerAddressURL = BuildURL(ServerPrefix + Location);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
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 == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
return ServerResponse;
}
COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
string ServerAddressURL = BuildURL(ServerPrefix + Location);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, Data.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(Data.c_str()));
HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8");
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 == 200 || SessionResponseCode == 201 || SessionResponseCode == 204){
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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
return ServerResponse;
}
COServerResponse CardDAV2::DeleteContact(std::string Location){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
string ServerAddressURL = BuildURL(ServerPrefix + Location);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE");
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 == 200 || SessionResponseCode == 202 || SessionResponseCode == 204){
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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
return ServerResponse;
}
COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
static const char* GetETagQuery =
""
""
""
""
""
"";
string ServerAddressURL = BuildURL(ServerPrefix + Location);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "REPORT");
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, GetETagQuery);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, strlen(GetETagQuery));
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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = GetETagValue();
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
return ServerResponse;
}
COServerResponse CardDAV2::GetContact(std::string Location, std::string *ContactData){
// Check if authentication was successful, otherwise don't do anything.
COServerResponse ServerResponse;
if (AuthPassed == false){
ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = 0;
ServerResponse.ResultCode = 0;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true);
ResetResults();
string ServerAddressURL = BuildURL(ServerPrefix + Location);
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
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 == 200){
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){
ServerResponse.RequestResult = COREQUEST_ERROR_SERVER;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = "";
return ServerResponse;
}
CanProcess = true;
ServerResponse.RequestResult = COREQUEST_OK;
ServerResponse.EntityTag = "";
ServerResponse.SessionCode = SessionResult;
ServerResponse.ResultCode = SessionResponseCode;
ServerResponse.ResultMessage = SessionErrorBuffer;
(*ContactData) = PageData;
return ServerResponse;
}
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);
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(){
return CanProcess;
}
bool CardDAV2::CanDoSSL(){
return SSLStatus;
}
COSSLVerified CardDAV2::SSLVerify(){
return SSLVerified;
}
bool CardDAV2::AbleToLogin(){
return AuthPassed;
}
bool CardDAV2::HasValidResponse(){
return ValidResponse;
}
bool CardDAV2::IsSelfSigned(){
return SSLSelfSigned;
}
void CardDAV2::SetupDefaultParametersNonSSL(bool DoAuthentication){
std::string ServerAddress = "";
string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/";
string UsernamePassword = ServerUser + ":" + ServerPass;
PageDataObject.CardDAV2Object = this;
PageDataObject.ConnectionSessionObject = ConnectionSession;
PageDataObject.DataSetting = &PageData;
PageDataObject.ServerUsingSSL = false;
PageHeaderObject.CardDAV2Object = this;
PageHeaderObject.ConnectionSessionObject = ConnectionSession;
PageHeaderObject.DataSetting = &PageHeader;
PageHeaderObject.ServerUsingSSL = false;
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, true);
curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
if (DoAuthentication == true){
curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
} else {
curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
}
}
void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){
// Setup the default parameters.
string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/";
string UsernamePassword = ServerUser + ":" + ServerPass;
PageDataObject.CardDAV2Object = this;
PageDataObject.ConnectionSessionObject = ConnectionSession;
PageDataObject.DataSetting = &PageData;
PageDataObject.ServerUsingSSL = true;
PageHeaderObject.CardDAV2Object = this;
PageHeaderObject.ConnectionSessionObject = ConnectionSession;
PageHeaderObject.DataSetting = &PageHeader;
PageHeaderObject.ServerUsingSSL = true;
curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str());
curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1L);
curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
curl_easy_setopt(ConnectionSession, CURLOPT_TIMEOUT, 60);
curl_easy_setopt(ConnectionSession, CURLOPT_FAILONERROR, 0L);
curl_easy_setopt(ConnectionSession, CURLOPT_USERAGENT, XSDAB_USERAGENT);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEFUNCTION, CardDAV2::WritebackFunc);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEDATA, &PageDataObject);
curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeaderObject);
curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer);
curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDS, nullptr);
curl_easy_setopt(ConnectionSession, CURLOPT_POSTFIELDSIZE, 0L);
if (DoAuthentication == true){
curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str());
} else {
curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, NULL);
}
if (EnableSSLBypass == true){
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L);
} else {
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 1L);
}
#if !defined(__APPLE__) || defined(__WIN32__)
if (TestMode == false && ServerAccount.size() > 0){
// Check if the server certificate file exists.
string CertificateFilename = GetAccountDir(ServerAccount, true);
if (wxFile::Exists(CertificateFilename)){
curl_easy_setopt(ConnectionSession, CURLOPT_CAINFO, CertificateFilename.c_str());
}
}
#endif
}
string CardDAV2::BuildURL(string URI){
string ServerAddressURL;
if (ServerSSL == true){
ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI;
} else {
ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + URI;
}
return ServerAddressURL;
}
string CardDAV2::GetErrorMessage(){
ErrorMessage = SessionErrorBuffer;
return ErrorMessage;
}
void CardDAV2::ResetResults(){
SSLStatus = false;
COSSLVerified SSLVerified = COSSL_NORESULT;
ValidResponse = false;
AuthPassed = false;
CanProcess = false;
SSLSelfSigned = false;
TaskCompleted = false;
ErrorMessage = "";
SessionErrorBuffer[0] = '\0';
SessionResult = CURLE_OK;
PageData = "";
PageHeader = "";
if (HeaderList != nullptr){
curl_slist_free_all(HeaderList);
HeaderList = nullptr;
}
}
string CardDAV2::GetETagValue(){
xmlDocPtr xmlCardDAVDoc;
xmlCardDAVDoc = xmlReadMemory(PageData.c_str(), (int)PageData.size(), "noname.xml", NULL, 0);
xmlNodePtr nodeLevel1;
xmlNodePtr nodeLevel2;
xmlNodePtr nodeLevel3;
xmlNodePtr nodeLevel4;
xmlNodePtr nodeLevel5;
xmlNodePtr nodeLevel6;
//std::map xmlDataMap;
std::string DataFilename;
std::string ETagData;
std::string xmlStringSafe;
std::string ETagValue;
// Tranverse through the catacombs of the response to get our ETag for the file.
for (nodeLevel1 = xmlCardDAVDoc->children;
nodeLevel1 != NULL;
nodeLevel1 = nodeLevel1->next)
{
bool HREFFound = FALSE;
bool ETagFound = FALSE;
for (nodeLevel2 = nodeLevel1->children;
nodeLevel2 != NULL;
nodeLevel2 = nodeLevel2->next)
{
for (nodeLevel3 = nodeLevel2->children;
nodeLevel3 != NULL;
nodeLevel3 = nodeLevel3->next)
{
if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"href") ||
!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:href") ||
!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:href")
){
// Get the filename.
for (nodeLevel4 = nodeLevel3->children;
nodeLevel4 != NULL;
nodeLevel4 = nodeLevel4->next)
{
if (!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"text") ||
!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"d:text") ||
!xmlStrcmp(nodeLevel4->name, (const xmlChar *)"D:text")
){
DataFilename = wxString::FromUTF8((const char*)nodeLevel4->content);
wxStringTokenizer wSTDFilename(DataFilename, wxT("/"));
while (wSTDFilename.HasMoreTokens()){
DataFilename = wSTDFilename.GetNextToken().ToStdString();
}
HREFFound = TRUE;
}
}
} else {
for (nodeLevel4 = nodeLevel3->children;
nodeLevel4 != NULL;
nodeLevel4 = nodeLevel4->next)
{
for (nodeLevel5 = nodeLevel4->children;
nodeLevel5 != NULL;
nodeLevel5 = nodeLevel5->next)
{
if (!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"getetag") ||
!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"d:getetag") ||
!xmlStrcmp(nodeLevel5->name, (const xmlChar *)"D:getetag")
){
for (nodeLevel6 = nodeLevel5->children;
nodeLevel6 != NULL;
nodeLevel6 = nodeLevel6->next)
{
// Strip the quotes from the ETag.
ETagData = (const char*)nodeLevel6->content;
if (ETagData[0] == '"' && ETagData[(ETagData.size() - 1)] == '"'){
ETagData.erase(0, 1);
ETagData.erase((ETagData.size() - 1));
}
ETagFound = TRUE;
}
}
}
}
}
}
}
if (HREFFound == TRUE && ETagFound == TRUE){
// Add to the map data.
ETagValue = ETagData;
HREFFound = FALSE;
ETagFound = FALSE;
break;
}
}
xmlFreeDoc(xmlCardDAVDoc);
return ETagValue;
}
string CardDAV2::GetETagHeader(){
// Go through each of the lines looking for the
// 'DAV:' section.
string HeaderName;
string HeaderValue;
bool FastForward = false;
for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
if (FastForward == true){
if (PageHeader[HeaderSeek] == '\n'){
FastForward = false;
}
continue;
}
try {
PageHeader.substr(HeaderSeek, 5) == "ETag:";
}
catch (const out_of_range &oor){
break;
}
if (PageHeader.substr(HeaderSeek, 5) == "ETag:"){
int CharacterSeek = 5;
while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
break;
}
HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
CharacterSeek++;
}
break;
} else {
FastForward = true;
continue;
}
if (PageHeader[HeaderSeek] == '\n'){
HeaderName = "";
}
//HeaderName += PageHeader.substr(HeaderSeek, 1);
}
// Check for quotation marks at the start and end and strip
// them out.
if (HeaderValue.size() >= 2){
if (HeaderValue[0] == '"'){
HeaderValue.erase((HeaderValue.size() - 1));
HeaderValue.erase(0);
}
}
return HeaderValue;
}
vector CardDAV2::GetDAVHeader(){
// Go through each of the lines looking for the
// 'DAV:' section.
string HeaderName;
string HeaderValue;
bool FastForward = false;
vector DAVHeaderList;
for (int HeaderSeek = 0; HeaderSeek < PageHeader.size(); HeaderSeek++){
if (FastForward == true){
if (PageHeader[HeaderSeek] == '\n'){
FastForward = false;
}
continue;
}
try {
PageHeader.substr(HeaderSeek, 4) == "DAV:";
}
catch (const out_of_range &oor){
break;
}
if (PageHeader.substr(HeaderSeek, 4) == "DAV:"){
int CharacterSeek = 5;
while ((HeaderSeek + CharacterSeek) < PageHeader.size()){
if (PageHeader.substr((HeaderSeek + CharacterSeek), 2) == "\r\n"){
break;
}
HeaderValue += PageHeader.substr((HeaderSeek + CharacterSeek), 1);
CharacterSeek++;
}
break;
} else {
FastForward = true;
continue;
}
if (PageHeader[HeaderSeek] == '\n'){
HeaderName = "";
}
//HeaderName += PageHeader.substr(HeaderSeek, 1);
}
// Split the header data.
std::string DAVHeaderValue;
for (int HeaderSeek = 0; HeaderSeek < HeaderValue.size(); HeaderSeek++){
if (HeaderValue.substr(HeaderSeek, 1) == ","){
DAVHeaderList.push_back(DAVHeaderValue);
DAVHeaderValue = "";
HeaderSeek++;
continue;
}
DAVHeaderValue += HeaderValue[HeaderSeek];
}
if (DAVHeaderValue.size() > 0){
DAVHeaderList.push_back(DAVHeaderValue);
}
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;
}