X-Git-Url: http://Server1/repobrowser/?p=xestiaab%2F.git;a=blobdiff_plain;f=source%2Fcarddav2%2Fcarddav2.cpp;h=dd70bab9a6c030ebd5843fc61efef84eac3545dc;hp=494468c10b653a65c624c54fc39e2d52dfac6abf;hb=f61e0e5b738c51d4b4b7e329c1e31fb2a9b3e2c9;hpb=b1467ce3cde3c61f79030bf4329f7037904043e1 diff --git a/source/carddav2/carddav2.cpp b/source/carddav2/carddav2.cpp index 494468c..dd70bab 100644 --- a/source/carddav2/carddav2.cpp +++ b/source/carddav2/carddav2.cpp @@ -18,64 +18,100 @@ #include "carddav2.h" -#include - 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)->WritebackFuncImplementation(ptr, size, nmemb, 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. - string *data = static_cast(stream); - data->append(ptr); + CardDAV2PassObject *data = static_cast(stream); + data->DataSetting->append(ptr); // Get the SSL engine pointer and trust if required on certain operating systems. - - if (ServerSSL){ - + + if (data->ServerUsingSSL == true) { + #if defined(__APPLE__) - + const struct curl_tlssessioninfo *TLSInfo; CURLcode TLSCode; - CURL *Connection = GetConnectionObject(); - TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo); - - if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){ - SSLCopyPeerTrust((SSLContext*)TLSInfo->internals, &SecTrustObject); + 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; - CURL *Connection = GetConnectionObject(); - TLSCode = curl_easy_getinfo(Connection, CURLINFO_TLS_SSL_PTR, &TLSInfo); + TLSCode = curl_easy_getinfo(data->ConnectionSessionObject, CURLINFO_TLS_SSL_PTR, &TLSInfo); - if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK){ + if (TLSInfo->internals != nullptr && TLSCode == CURLE_OK) { // Free the previous certificate data. - CertFreeCertificateContext(CertificateData); + //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); @@ -85,13 +121,35 @@ CardDAV2::~CardDAV2(){ 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(){ @@ -109,13 +167,13 @@ SSLCertCollectionString CardDAV2::BuildSSLCollection(){ certptr.certdata = NULL; - curl_easy_getinfo(ConnectionSession, CURLINFO_CERTINFO, &certptr.certinfo); - + 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; @@ -151,13 +209,13 @@ SSLCertCollectionString CardDAV2::BuildSSLCollection(){ } -void CardDAV2::BypassSSLVerification(bool EnableBypass){ +#endif + +void CardDAV2::BypassSSLVerification(bool EnableBypass) { EnableSSLBypass = EnableBypass; SSLSelfSigned = EnableBypass; } -#endif - void CardDAV2::SetupConnectionObject(){ ConnectionSession = curl_easy_init(); } @@ -173,7 +231,7 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){ COConnectResult ConnectResult = COCONNECT_UNITTESTFAIL; string ServerAddressURL = BuildURL("/principals/"); - + curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str()); if (TestMode == true){ @@ -189,6 +247,7 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){ SSLVerified = COSSL_VERIFIED; ConnectResult = COCONNECT_OK; break; + case CURLE_SSL_INVALIDCERTSTATUS: case CURLE_SSL_CACERT: case CURLE_SSL_CONNECT_ERROR: SSLStatus = true; @@ -200,6 +259,26 @@ COConnectResult CardDAV2::Connect(bool DoAuthentication){ 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. @@ -476,7 +555,7 @@ COServerResponse CardDAV2::GetDefaultPrefix(string *ServerPrefix){ ValidResponse = false; } - if (ValidResponse == false && AuthPassed == false){ + if (ValidResponse == false || AuthPassed == false){ ServerResponse.RequestResult = COREQUEST_ERROR_SERVER; ServerResponse.EntityTag = ""; ServerResponse.SessionCode = SessionResult; @@ -809,7 +888,7 @@ COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){ ValidResponse = false; } - if (ValidResponse == false && AuthPassed == false){ + if (ValidResponse == false || AuthPassed == false){ ServerResponse.RequestResult = COREQUEST_ERROR_SERVER; ServerResponse.EntityTag = ""; ServerResponse.SessionCode = SessionResult; @@ -830,162 +909,635 @@ COServerResponse CardDAV2::AddContact(std::string Location, std::string Data){ } COServerResponse CardDAV2::EditContact(std::string Location, std::string Data){ - -} -COServerResponse CardDAV2::DeleteContact(std::string Location, std::string EntityTag){ - -} - -COServerResponse CardDAV2::GetServerEntityTagValue(std::string Location){ - -} + // Check if authentication was successful, otherwise don't do anything. -COServerResponse CardDAV2::GetContact(std::string Location){ + COServerResponse ServerResponse; -} + if (AuthPassed == false){ + ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED; + ServerResponse.EntityTag = ""; + ServerResponse.SessionCode = 0; + ServerResponse.ResultCode = 0; + ServerResponse.ResultMessage = ""; + return ServerResponse; + } -COContactList CardDAV2::GetContactList(std::string SyncToken){ - -} + ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true); + ResetResults(); -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){ + 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())); - std::string ServerAddress = ""; + HeaderList = curl_slist_append(HeaderList, "Content-Type: text/vcard; charset=utf-8"); - string ServerAddressURL = "http://" + ServerAddress + ":" + to_string(ServerPort) + "/"; - string UsernamePassword = ServerUser + ":" + ServerPass; - - curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddress.c_str()); - curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - 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, &PageData); - curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader); - curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET"); - curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr); + curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, HeaderList); - if (DoAuthentication == true){ - curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str()); + if (TestMode == true){ + SessionResult = curl_easy_perform(ConnectionSession); } else { - curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":"); + SessionResult = curl_easy_perform(ConnectionSession); } -} - -void CardDAV2::SetupDefaultParametersSSL(bool DoAuthentication){ - - // Setup the default parameters. + 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; + }; - string ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + "/"; - string UsernamePassword = ServerUser + ":" + ServerPass; + long SessionResponseCode = 0; - curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str()); - curl_easy_setopt(ConnectionSession, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(ConnectionSession, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - 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, &PageData); - curl_easy_setopt(ConnectionSession, CURLOPT_WRITEHEADER, &PageHeader); - curl_easy_setopt(ConnectionSession, CURLOPT_ERRORBUFFER, SessionErrorBuffer); - curl_easy_setopt(ConnectionSession, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(ConnectionSession, CURLOPT_CERTINFO, 1); - curl_easy_setopt(ConnectionSession, CURLOPT_VERBOSE, 1); - curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "GET"); - curl_easy_setopt(ConnectionSession, CURLOPT_HTTPHEADER, nullptr); + curl_easy_getinfo(ConnectionSession, CURLINFO_RESPONSE_CODE, &SessionResponseCode); - if (DoAuthentication == true){ - curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, UsernamePassword.c_str()); + 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 { - curl_easy_setopt(ConnectionSession, CURLOPT_USERPWD, ":"); + AuthPassed = false; + ValidResponse = false; } - if (EnableSSLBypass == true){ - curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 0); - curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 0); - } else { - curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYHOST, 2); - curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYPEER, 1); + if (ValidResponse == false || AuthPassed == false){ + ServerResponse.RequestResult = COREQUEST_ERROR_SERVER; + ServerResponse.EntityTag = ""; + ServerResponse.SessionCode = SessionResult; + ServerResponse.ResultCode = SessionResponseCode; + ServerResponse.ResultMessage = ""; + return ServerResponse; } - 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()); - - } - - } + CanProcess = true; + + ServerResponse.RequestResult = COREQUEST_OK; + ServerResponse.EntityTag = ""; + ServerResponse.SessionCode = SessionResult; + ServerResponse.ResultCode = SessionResponseCode; + ServerResponse.ResultMessage = SessionErrorBuffer; + return ServerResponse; } -string CardDAV2::BuildURL(string URI){ +COServerResponse CardDAV2::DeleteContact(std::string Location){ - string ServerAddressURL; + // Check if authentication was successful, otherwise don't do anything. + + COServerResponse ServerResponse; - if (SSLStatus == true){ - ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI; - } else { - ServerAddressURL = "https://" + ServerAddress + ":" + to_string(ServerPort) + URI; + if (AuthPassed == false){ + ServerResponse.RequestResult = COREQUEST_ERROR_NOTCONNECTED; + ServerResponse.EntityTag = ""; + ServerResponse.SessionCode = 0; + ServerResponse.ResultCode = 0; + ServerResponse.ResultMessage = ""; + return ServerResponse; } - - return ServerAddressURL; - -} -string CardDAV2::GetErrorMessage(){ - - ErrorMessage = SessionErrorBuffer; - return ErrorMessage; + ServerSSL ? SetupDefaultParametersSSL(true) : SetupDefaultParametersNonSSL(true); + ResetResults(); -} - -void CardDAV2::ResetResults(){ + string ServerAddressURL = BuildURL(ServerPrefix + Location); + curl_easy_setopt(ConnectionSession, CURLOPT_URL, ServerAddressURL.c_str()); + curl_easy_setopt(ConnectionSession, CURLOPT_CUSTOMREQUEST, "DELETE"); - SSLStatus = false; - COSSLVerified SSLVerified = COSSL_NORESULT; - ValidResponse = false; + 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; + + 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()); + + // Force CURLOPT_SSL_VERIFYSTATUS to 0. + curl_easy_setopt(ConnectionSession, CURLOPT_SSL_VERIFYSTATUS, 0L); + + } + + } + +#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){ @@ -995,6 +1547,150 @@ void CardDAV2::ResetResults(){ } +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 @@ -1157,4 +1853,163 @@ vector CardDAV2::GetDAVHeader(){ return DAVHeaderList; -} \ No newline at end of file +} + +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; + +}