#include "carddav.h" #include "../version.h" #include #include #include #include #include #include #include #include "../vcard/vcard.h" #include "../common/dirs.h" size_t WritebackFunc(char *ptr, size_t size, size_t nmemb, wxString *stream){ wxString Data; Data = wxString::FromUTF8((char *)ptr); stream->Append(Data); return size * nmemb; } struct UploadDataStruc{ wxString *readptr; long sizeleft; int seek = 0; }; int ProgressFunc(void *clientdata, double TTDown, double NDown, double TTUp, double NUp){ int ProgressRet; CardDAV *IncCardDAV = static_cast(clientdata); ProgressRet = IncCardDAV->ProgressFuncProc(clientdata, TTDown, NDown, TTUp, NUp); if (ProgressRet != 0){ return 1; } return 0; } wxString CardDAV::ServerAddress; int CardDAV::ServerPort; wxString CardDAV::ServerUser; wxString CardDAV::ServerPass; wxString CardDAV::ServerPrefix; wxString CardDAV::ServerAccount; bool CardDAV::ServerSSL; bool *CardDAV::ServerResult; bool *CardDAV::ServerMonitor; bool CardDAV::SSLStatus; bool CardDAV::SSLVerified; bool CardDAV::ValidResponse; bool CardDAV::AuthPassed; bool CardDAV::HasCalDAVSupport; bool CardDAV::AbortConnection; wxString CardDAV::ServerResponse; wxString CardDAV::ServerMethod; wxString CardDAV::ServerFilenameLocation; wxString CardDAV::ServerUploadData; wxString CardDAV::ETagData; wxString CardDAV::ETagResult; bool CardDAV::UploadMode; bool CardDAV::EditMode; long CardDAV::ItemIndex; std::map *CardDAV::ActivityListPtr; char CardDAV::curlerrbuffer[CURL_ERROR_SIZE]; SSLCertCollection CardDAV::SSLCertCol; int CardDAV::SSLErrorCode; int CardDAV::ConnectionErrorCode; wxString CardDAV::PageHeader; wxString CardDAV::PageData; CURLcode CardDAV::claconncode; int CardDAV::HTTPErrorCode; wxString CardDAV::ErrorMessage; SSLCertCollection CardDAV::VerifyCertCollection; bool CardDAV::AllowSelfSign; CardDAV::CardDAV(){ ServerPort = 8080; SSLStatus = FALSE; SSLVerified = FALSE; AuthPassed = FALSE; ValidResponse = FALSE; HasCalDAVSupport = FALSE; SSLCertCol.SuccessCode = 0; AllowSelfSign = FALSE; AbortConnection = FALSE; UploadMode = FALSE; EditMode = FALSE; HTTPErrorCode = 0; } CardDAV::~CardDAV(){ } size_t UploadReadFunc(void *ptr, size_t size, size_t nmemb, void *userdata){ struct UploadDataStruc *UploadPtr = (struct UploadDataStruc *)userdata; if (UploadPtr->sizeleft){ //MeepMoop->sizeleft--; //return 1; UploadPtr->sizeleft--; wxString wxSChar; wxSChar = UploadPtr->readptr->Mid(UploadPtr->seek,1); //*(char *)ptr = (char)wxSChar.mb_str(); strncpy((char *)ptr, (const char*)wxSChar.mb_str(wxConvUTF8), 1); UploadPtr->seek++; return 1; } return 0; } bool CardDAV::SetupConnection(wxString SvrAddress, int SvrPort, wxString SvrUser, wxString SvrPass, bool SvrSSL){ ServerAddress = SvrAddress; ServerPort = SvrPort; ServerUser = SvrUser; ServerPass = SvrPass; ServerSSL = SvrSSL; return TRUE; } bool CardDAV::SetupConnection(wxString SvrAddress, int SvrPort, wxString SvrUser, wxString SvrPass, bool SvrSSL, wxString SvrPrefix, wxString SvrAccount){ ServerAddress = SvrAddress; ServerPort = SvrPort; ServerUser = SvrUser; ServerPass = SvrPass; ServerSSL = SvrSSL; ServerPrefix = SvrPrefix; ServerAccount = SvrAccount; return TRUE; } bool CardDAV::SetupResultBools(bool *SvrResult, bool *SvrMonitor){ ServerResult = SvrResult; ServerMonitor = SvrMonitor; return TRUE; } bool CardDAV::HasValidResponse(){ return ValidResponse; } bool CardDAV::CanDoCardDAV(){ return HasCalDAVSupport; } bool CardDAV::CanDoSSL(){ return SSLStatus; } bool CardDAV::SSLVerify(){ return SSLVerified; } bool CardDAV::AbleToLogin(){ return AuthPassed; } bool CardDAV::IsSelfSigned(){ return AllowSelfSign; } /* size_t CardDAV::WritebackFunc(char *ptr, size_t size, size_t nmemb, FILE *stream){ wxString Data; Data = wxString::FromUTF8((char *)ptr); if ((bool)stream == TRUE){ PageHeader.Append(Data); } else { PageData.Append(Data); } return size * nmemb; } */ int CardDAV::ProgressFuncProc(void *clientdata, double TTUp, double NUp, double TTDown, double NDown){ if (AbortConnection == TRUE){ return -1; } else { return 0; } } void CardDAV::Abort(){ AbortConnection = TRUE; } CURLcode CardDAV::SSLVerifyTest(){ PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; CURL *connssldata; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); /*struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE;*/ wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); ServerAddressSSL = wxT("https://") + ServerAddressURL; if (ServerSSL){ union { struct curl_slist *certdata; struct curl_certinfo *certinfo; } ptr; ptr.certdata = NULL; // Setup two initial connections and attempt to get the certificate data. curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); curl_easy_setopt(conn, CURLOPT_VERBOSE, 1L); //curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, FALSE); //curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, FALSE); curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, curlerrbuffer); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); conncode = (curl_easy_perform(conn)); // Check if the SSL certificate is valid or self-signed or some other // error occured. if (conncode == CURLE_OK){ // Connection is OK. Do nothing. *ServerResult = TRUE; } else if (conncode == CURLE_SSL_CACERT || conncode == CURLE_SSL_CONNECT_ERROR){ connssldata = curl_easy_init(); // Retry but get the certificates without peer/host verification. curl_easy_setopt(connssldata, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(connssldata, CURLOPT_CERTINFO, 1); curl_easy_setopt(connssldata, CURLOPT_VERBOSE, 1L); curl_easy_setopt(connssldata, CURLOPT_ERRORBUFFER, curlerrbuffer); curl_easy_setopt(connssldata, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(connssldata, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(connssldata, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(connssldata, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(connssldata, CURLOPT_SSL_VERIFYHOST, 0L); CURLcode certfetchcode; certfetchcode = (curl_easy_perform(connssldata)); VerifyCertCollection = BuildSSLCollection(connssldata); if (certfetchcode == CURLE_OK){ curl_easy_getinfo(connssldata, CURLINFO_CERTINFO, &ptr.certdata); VerifyCertCollection = BuildSSLCollection(connssldata); } else { conncode = certfetchcode; } *ServerResult = FALSE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode)); *ServerResult = FALSE; } } curl_easy_cleanup(conn); return conncode; } SSLCertCollection CardDAV::GetSSLVerifyResults(){ return VerifyCertCollection; } void CardDAV::AllowSelfSignTest(bool AllowSelfSignIn){ AllowSelfSign = AllowSelfSignIn; } bool CardDAV::Connect(){ PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; // Try SSL first. /* char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)]; //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1)); char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)]; //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1)); char *ServerAuthChar = new char[(ServerAuth.Length() - 1)]; //memset(ServerAuthChar, 0, ServerAddressSSL.Length()); strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1)); */ if (ServerSSL){ union { struct curl_slist *certdata; struct curl_certinfo *certinfo; } ptr; ptr.certdata = NULL; // Setup two initial connections and attempt to get the certificate data. curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); conncode = (curl_easy_perform(conn)); // Check if the SSL certificate is valid or self-signed or some other // error occured. if (conncode == CURLE_OK){ // Connection is OK. Do nothing. } else if (conncode == CURLE_SSL_CACERT){ // Post message saying SSL certificate is invalid. curl_easy_getinfo(conn, CURLINFO_CERTINFO, &ptr.certdata); } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode)); *ServerResult = FALSE; return FALSE; } curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); if (AllowSelfSign == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0L); } conncode = (curl_easy_perform(conn)); ptr.certdata = NULL; curl_easy_getinfo(conn, CURLINFO_CERTINFO, &ptr.certdata); if (conncode == CURLE_OK){ // Process the server header response and look for // 'addressbook' within the DAV header. wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n")); wxString wxSHeaderLine; std::map DAVHeaderLines; while (wxSHeaderLines.HasMoreTokens()){ wxSHeaderLine = wxSHeaderLines.GetNextToken(); if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){ // Look for address book in the line. if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){ HasCalDAVSupport = TRUE; } } } *ServerResult = TRUE; ValidResponse = TRUE; AuthPassed = TRUE; SSLStatus = TRUE; return TRUE; } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode)); *ServerResult = TRUE; ValidResponse = FALSE; AuthPassed = FALSE; SSLStatus = TRUE; return TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode)); *ServerResult = FALSE; return FALSE; } } else { // No SSL. curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ // Process the server header response and look for // 'addressbook' within the DAV header. wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n")); wxString wxSHeaderLine; std::map DAVHeaderLines; while (wxSHeaderLines.HasMoreTokens()){ wxSHeaderLine = wxSHeaderLines.GetNextToken(); if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){ // Look for address book in the line. if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){ HasCalDAVSupport = TRUE; } } } *ServerResult = TRUE; ValidResponse = TRUE; AuthPassed = TRUE; SSLStatus = FALSE; return TRUE; } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = TRUE; ValidResponse = FALSE; AuthPassed = FALSE; SSLStatus = FALSE; return TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = FALSE; return FALSE; } // TODO: Double check and make sure HTTP Authentication is possible. } *ServerResult = TRUE; return TRUE; } void CardDAV::GetSSLResults(){ } void CardDAV::ProcessDataThread(){ PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; wxString ETag; wxString ETagOriginal; wxString ETagServer; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation; ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; // Try SSL first. /* char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)]; //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1)); char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)]; //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1)); char *ServerAuthChar = new char[(ServerAuth.Length() - 1)]; //memset(ServerAuthChar, 0, ServerAddressSSL.Length()); strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1)); */ //std::string WriteDataString = std::string(ServerUploadData.mb_str()); std::map::iterator ActIter; struct UploadDataStruc UploadData; ActIter = ActivityListPtr->find((int)ItemIndex); // Update result flag. ActIter->second = 1; // Setup the request mode if it is not empty. if (!ServerMethod.IsEmpty()){ curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, (const char*)ServerMethod.mb_str(wxConvUTF8)); } if (ServerSSL){ wxString ServerCertFilename; bool MatchingCert = FALSE; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); if (UploadMode == TRUE){ UploadData.readptr = &ServerUploadData; UploadData.sizeleft = ServerUploadData.Len(); curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); } ServerCertFilename = GetAccountDir(ServerAccount, TRUE); if (wxFile::Exists(ServerCertFilename) == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); } //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); claconncode = (curl_easy_perform(conn)); // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without // the local certificate in use. if (claconncode == CURLE_PEER_FAILED_VERIFICATION){ curl_easy_cleanup(conn); conn = curl_easy_init(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); if (UploadMode == TRUE){ UploadData.readptr = &ServerUploadData; UploadData.sizeleft = ServerUploadData.Len(); curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); } claconncode = (curl_easy_perform(conn)); // If claconncode is CURLE_OK then delete the certificate file as that // is no longer needed. if (claconncode == CURLE_OK){ // Delete the certificate file. wxRemoveFile(ServerCertFilename); } } // Check if it fails with a CURLE_SSL_CACERT then compare // the certificates as PEM files. if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){ //curl_easy_cleanup(conn); //conn = curl_easy_init(); CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; //claconncode = (curl_easy_perform(conn)); wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); wxString SSLLocalData; wxString SSLServerData; sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); std::map::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0); std::multimap::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert")); wxFFile SSLLocalFile; #if wxABI_VERSION < 20900 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r")); #else SSLLocalFile.Open(ServerCertFilename, wxT("r")); #endif // Load the recovery database for tasks not done. if (SSLLocalFile.IsOpened() == TRUE){ // Check if we are using wxWidgets version 2.8 or less and // execute the required command accordingly. SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto()); } SSLServerData = SSLDataIter->second; if (SSLLocalData == SSLServerData){ // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER // and CURLOPT_SSL_VERIFYHOST off. curl_easy_cleanup(conn); conn = curl_easy_init(); PageData.clear(); PageHeader.clear(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); if (UploadMode == TRUE){ UploadData.readptr = &ServerUploadData; UploadData.sizeleft = ServerUploadData.Len(); curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); } curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0); claconncode = (curl_easy_perform(conn)); MatchingCert = TRUE; } if (MatchingCert == FALSE){ claconncode = CURLE_SSL_CACERT; return; } curl_easy_cleanup(sslerrconn); } // Sort out SSL error. // When SSL cert error occurs, connect again and fetch certificates. // Display a message to the user explaining that an invalid // certificate has been given and let the user decide what // to do next. if (claconncode == CURLE_OK){ } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){ CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); // Replace conn with sslerrconn! curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); SSLCertCol.SuccessCode = 1; return; } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return; } } else { // No SSL. curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); if (UploadMode == TRUE){ UploadData.readptr = &ServerUploadData; UploadData.sizeleft = ServerUploadData.Len(); curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); } conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ // Process the server header response and look for // 'addressbook' within the DAV header. wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n")); wxString wxSHeaderLine; std::map DAVHeaderLines; while (wxSHeaderLines.HasMoreTokens()){ wxSHeaderLine = wxSHeaderLines.GetNextToken(); if (wxSHeaderLine.Mid(0, 5) == wxT("ETag:")){ ETagData = wxSHeaderLine.Mid(5); ETagData.Trim(); ETagData.Trim(FALSE); // Check for commas. if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){ ETagData.Remove(0, 1); ETagData.RemoveLast(); } } if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){ // Look for address book in the line. if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){ HasCalDAVSupport = TRUE; } } } // Get the ETag from the header. if (UploadMode == TRUE){ wxString PageHeaderLine; wxStringTokenizer PageHeaderSplit(PageHeader, wxT("\r\n")); if (PageHeaderSplit.HasMoreTokens()){ PageHeaderLine = PageHeaderSplit.GetNextToken(); } } ActIter->second = 4; return; } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n", GetHTTPCode()); ActIter->second = 2; return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ActIter->second = 2; return; } } /* } */ // Connection was successful /* if (conn){ wxString ServerAddressURL; // Try secure connection first. ServerAddressURL = wxT("http://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); ServerAddressURL.Trim(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressURL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(conn, CURLOPT_WRITEDATA, NULL); conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ *ServerResult = TRUE; return TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = FALSE; return FALSE; } // Failed. So use unsecure connection. UseSSL = FALSE; ServerAddress = wxT("http://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort); curl_easy_setopt(conn, CURLOPT_URL, ServerAddress.c_str()); conncode = (curl_easy_perform(conn)); if (conncode != CURLE_OK){ *ServerResult = FALSE; return FALSE; } else { *ServerResult = TRUE; return TRUE; } } else { *ServerResult = FALSE; return FALSE; } */ // Catch all. //ActIter->second = 1; *ServerResult = TRUE; return; } void CardDAV::ProcessData(){ std::thread ConnectThread(&CardDAV::ProcessDataThread, this); ConnectThread.detach(); } void CardDAV::SetServerFilename(wxString Filename){ ServerFilenameLocation = Filename; } void CardDAV::GetServerContactData() { PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; wxString ServerCertFilename; bool MatchingCert = FALSE; CURL *conn; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation; ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; // Try SSL first. /* char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)]; //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1)); char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)]; //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1)); char *ServerAuthChar = new char[(ServerAuth.Length() - 1)]; //memset(ServerAuthChar, 0, ServerAddressSSL.Length()); strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1)); */ //std::string WriteDataString = std::string(ServerUploadData.mb_str()); std::map::iterator ActIter; struct UploadDataStruc UploadData; ActIter = ActivityListPtr->find((int)ItemIndex); //ActIter->second = 1; /*wxString CardDAVDataQuery = wxT("\r\n"); CardDAVDataQuery.Append(wxT("\r\n")); CardDAVDataQuery.Append(wxT("\r\n")); CardDAVDataQuery.Append(wxT("\r\n")); CardDAVDataQuery.Append(wxT(" \r\n")); CardDAVDataQuery.Append(wxT("\r\n")); CardDAVDataQuery.Append(wxT(""));*/ if (ServerSSL){ curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); ServerCertFilename = GetAccountDir(ServerAccount, TRUE); if (wxFile::Exists(ServerCertFilename) == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); } claconncode = (curl_easy_perform(conn)); // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without // the local certificate in use. if (claconncode == CURLE_PEER_FAILED_VERIFICATION){ curl_easy_cleanup(conn); conn = curl_easy_init(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); claconncode = (curl_easy_perform(conn)); // If claconncode is CURLE_OK then delete the certificate file as that // is no longer needed. if (claconncode == CURLE_OK){ // Delete the certificate file. wxRemoveFile(ServerCertFilename); } } // Check if it fails with a CURLE_SSL_CACERT then compare // the certificates as PEM files. if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){ //curl_easy_cleanup(conn); //conn = curl_easy_init(); CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; //claconncode = (curl_easy_perform(conn)); wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); wxString SSLLocalData; wxString SSLServerData; sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); std::map::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0); std::multimap::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert")); wxFFile SSLLocalFile; #if wxABI_VERSION < 20900 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r")); #else SSLLocalFile.Open(ServerCertFilename, wxT("r")); #endif // Load the recovery database for tasks not done. if (SSLLocalFile.IsOpened() == TRUE){ SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto()); } SSLServerData = SSLDataIter->second; if (SSLLocalData == SSLServerData){ // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER // and CURLOPT_SSL_VERIFYHOST off. curl_easy_cleanup(conn); conn = curl_easy_init(); PageData.clear(); PageHeader.clear(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0); claconncode = (curl_easy_perform(conn)); MatchingCert = TRUE; } if (MatchingCert == FALSE){ claconncode = CURLE_SSL_CACERT; return; } curl_easy_cleanup(sslerrconn); } // Sort out SSL error. // When SSL cert error occurs, connect again and fetch certificates. // Display a message to the user explaining that an invalid // certificate has been given and let the user decide what // to do next. if (claconncode == CURLE_OK){ } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){ CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); // Replace conn with sslerrconn! curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); SSLCertCol.SuccessCode = 1; return; } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return; } } else { // No SSL. wxString EmptyString; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); PageData.Clear(); PageHeader.Clear(); conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n", GetHTTPCode()); return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); return; } } return; } wxString CardDAV::GetPageData() { return PageData; } void CardDAV::GetServerETagValueThread() { PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; bool FilenameIsDirectory = FALSE; CURL *conn; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation; ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; // Workout if path is directory or filename. /*if (ServerAddress){ FilenameIsDirectory = TRUE; } else { FilenameIsDirectory = FALSE; }*/ // Try SSL first. /* char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)]; //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1)); char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)]; //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length()); strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1)); char *ServerAuthChar = new char[(ServerAuth.Length() - 1)]; //memset(ServerAuthChar, 0, ServerAddressSSL.Length()); strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1)); */ //std::string WriteDataString = std::string(ServerUploadData.mb_str()); std::map::iterator ActIter; struct UploadDataStruc UploadData; ActIter = ActivityListPtr->find((int)ItemIndex); static const char* query = "" "" "" //"" //" " //"" "" "" ""; if (ServerSSL){ wxString ServerCertFilename; bool MatchingCert = FALSE; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); ServerCertFilename = GetAccountDir(ServerAccount, TRUE); if (wxFile::Exists(ServerCertFilename) == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); } claconncode = (curl_easy_perform(conn)); // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without // the local certificate in use. if (claconncode == CURLE_PEER_FAILED_VERIFICATION){ curl_easy_cleanup(conn); conn = curl_easy_init(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); claconncode = (curl_easy_perform(conn)); // If claconncode is CURLE_OK then delete the certificate file as that // is no longer needed. if (claconncode == CURLE_OK){ // Delete the certificate file. wxRemoveFile(ServerCertFilename); } } // Check if it fails with a CURLE_SSL_CACERT then compare // the certificates as PEM files. if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){ //curl_easy_cleanup(conn); //conn = curl_easy_init(); CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; //claconncode = (curl_easy_perform(conn)); wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); PageData.clear(); PageHeader.clear(); curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(sslerrconn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); wxString SSLLocalData; wxString SSLServerData; sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); std::map::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0); std::multimap::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert")); wxFFile SSLLocalFile; #if wxABI_VERSION < 20900 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r")); #else SSLLocalFile.Open(ServerCertFilename, wxT("r")); #endif // Load the recovery database for tasks not done. if (SSLLocalFile.IsOpened() == TRUE){ // Check if we are using wxWidgets version 2.8 or less and // execute the required command accordingly. SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto()); } SSLServerData = SSLDataIter->second; if (SSLLocalData == SSLServerData){ // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER // and CURLOPT_SSL_VERIFYHOST off. curl_easy_cleanup(conn); conn = curl_easy_init(); PageData.clear(); PageHeader.clear(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0); claconncode = (curl_easy_perform(conn)); MatchingCert = TRUE; } if (MatchingCert == FALSE){ claconncode = CURLE_SSL_CACERT; return; } curl_easy_cleanup(sslerrconn); } // Sort out SSL error. // When SSL cert error occurs, connect again and fetch certificates. // Display a message to the user explaining that an invalid // certificate has been given and let the user decide what // to do next. if (claconncode == CURLE_OK){ } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){ CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); // Replace conn with sslerrconn! curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); SSLCertCol.SuccessCode = 1; curl_easy_cleanup(conn); curl_easy_cleanup(sslerrconn); return; } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); curl_easy_cleanup(conn); return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); curl_easy_cleanup(conn); return; } } else { // No SSL. wxString EmptyString; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); PageData.Clear(); PageHeader.Clear(); conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); return; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); return; } } xmlDocPtr xmlCardDAVDoc; xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0); xmlNodePtr nodeLevel1; xmlNodePtr nodeLevel2; xmlNodePtr nodeLevel3; xmlNodePtr nodeLevel4; xmlNodePtr nodeLevel5; xmlNodePtr nodeLevel6; std::map xmlDataMap; wxString DataFilename; wxString ETagData; std::string xmlStringSafe; // 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(); } 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 = wxString::FromUTF8((const char*)nodeLevel6->content); if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){ ETagData.Remove(0, 1); ETagData.RemoveLast(); } ETagFound = TRUE; } } } } } } } if (HREFFound == TRUE && ETagFound == TRUE){ // Add to the map data. xmlDataMap.insert(std::make_pair(DataFilename, ETagData)); HREFFound = FALSE; ETagFound = FALSE; } } xmlFreeDoc(xmlCardDAVDoc); // Get the first result. for (std::map::iterator iter = xmlDataMap.begin(); iter != xmlDataMap.end(); ++iter){ ETagResult = iter->second; break; } if (ETagResult.IsEmpty()){ return; } return; } wxString CardDAV::ETagValueResult(){ return ETagResult; } void CardDAV::GetServerETagValue(){ std::thread ConnectThread(&CardDAV::GetServerETagValueThread, this); ConnectThread.detach(); } void CardDAV::SetupData(wxString Method, wxString FilenameLocation, wxString UploadData){ ServerMethod = Method; ServerFilenameLocation = FilenameLocation; ServerUploadData = UploadData; // Check if ServerFilenameLocation has a / at // the start and if not then append it. if (ServerFilenameLocation.Left(1) != wxT("/")){ // Not there so insert. ServerFilenameLocation = wxT("/") + ServerFilenameLocation; } } void CardDAV::SetupVariables(std::map *actlist, int actindex){ ActivityListPtr = actlist; ItemIndex = actindex; } wxString CardDAV::GetETagData(){ return ETagData; } void CardDAV::SetUploadMode(bool IncMode){ UploadMode = IncMode; } void CardDAV::SetEditMode(bool EditModeInc){ EditMode = EditModeInc; } ContactListData CardDAV::GetContactList(wxString SyncTokenInc){ ContactListData ContactListFinal; std::map ContactList; PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + wxT("/"); ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; // Load the sync token file (if it exists). wxCharBuffer SyncDataBuffer; wxString SyncData; SyncData.Clear(); SyncTokenInc.Trim(); if (!SyncTokenInc.IsEmpty()){ SyncData = wxT("\n"); SyncData.Append(wxT("\n")); SyncData.Append(wxT("")); //SyncData.Trim(); //SyncData.Append(wxT("data:,00378c55-1f44-44a2-a255-84f6560b5cac_580")); SyncData.Append(SyncTokenInc); //SyncData.Trim(); SyncData.Append(wxT("\n")); SyncData.Append(wxT("1\n")); SyncData.Append(wxT("\n")); SyncData.Append(wxT(" \n")); SyncData.Append(wxT("\n")); SyncData.Append(wxT("")); SyncDataBuffer = SyncData.ToUTF8(); } else { SyncData = wxT("\n"); SyncData.Append(wxT("\n")); SyncData.Append(wxT("\n")); SyncData.Append(wxT("1\n")); SyncData.Append(wxT("\n")); SyncData.Append(wxT(" \n")); SyncData.Append(wxT("\n")); SyncData.Append(wxT("\n")); SyncDataBuffer = SyncData.ToUTF8(); } //static const char* query = SyncData.mb_str(); /*char *query = "\n\ \n\ data:,00378c55-1f44-44a2-a255-84f6560b5cac_580\n\ 1\n\ \n\ \n\ \n\ \n";*/ const char* query = SyncDataBuffer.data(); // Try SSL first. std::map::iterator ActIter; struct UploadDataStruc UploadData; ActIter = ActivityListPtr->find((int)ItemIndex); curl_slist *slist = NULL; slist = curl_slist_append(slist, "Depth: 1"); if (ServerSSL){ wxString ServerCertFilename; bool MatchingCert = FALSE; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); ServerCertFilename = GetAccountDir(ServerAccount, TRUE); if (wxFile::Exists(ServerCertFilename) == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); } //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); claconncode = (curl_easy_perform(conn)); // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without // the local certificate in use. if (claconncode == CURLE_PEER_FAILED_VERIFICATION){ curl_easy_cleanup(conn); conn = curl_easy_init(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); claconncode = (curl_easy_perform(conn)); // If claconncode is CURLE_OK then delete the certificate file as that // is no longer needed. if (claconncode == CURLE_OK){ // Delete the certificate file. wxRemoveFile(ServerCertFilename); } } // Check if it fails with a CURLE_SSL_CACERT then compare // the certificates as PEM files. if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){ //curl_easy_cleanup(conn); //conn = curl_easy_init(); CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; //claconncode = (curl_easy_perform(conn)); wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); wxString SSLLocalData; wxString SSLServerData; sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); std::map::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0); std::multimap::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert")); wxFFile SSLLocalFile; #if wxABI_VERSION < 20900 SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r")); #else SSLLocalFile.Open(ServerCertFilename, wxT("r")); #endif // Load the recovery database for tasks not done. if (SSLLocalFile.IsOpened() == TRUE){ // Check if we are using wxWidgets version 2.8 or less and // execute the required command accordingly. SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto()); } SSLServerData = SSLDataIter->second; if (SSLLocalData == SSLServerData){ // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER // and CURLOPT_SSL_VERIFYHOST off. curl_easy_cleanup(conn); conn = curl_easy_init(); PageHeader.clear(); PageData.clear(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0); claconncode = (curl_easy_perform(conn)); MatchingCert = TRUE; } if (MatchingCert == FALSE){ claconncode = CURLE_SSL_CACERT; return ContactListFinal; } curl_easy_cleanup(sslerrconn); } // Sort out SSL error. // When SSL cert error occurs, connect again and fetch certificates. // Display a message to the user explaining that an invalid // certificate has been given and let the user decide what // to do next. if (claconncode == CURLE_OK){ } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){ CURL *sslerrconn; sslerrconn = curl_easy_init(); CURLcode sslerrconncode; wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); // Replace conn with sslerrconn! curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8)); curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1); sslerrconncode = (curl_easy_perform(sslerrconn)); SSLCertCol = BuildSSLCollection(sslerrconn); SSLCertCol.SuccessCode = 1; return ContactListFinal; } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return ContactListFinal; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %d\n", http_code); return ContactListFinal; } SSLCertCol = BuildSSLCollection(conn); } else { // No SSL. wxString EmptyString; curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "REPORT"); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, slist); //UploadData.readptr = &CardDAVDataQuery; //UploadData.sizeleft = CardDAVDataQuery.Len(); //curl_easy_setopt(conn, CURLOPT_UPLOAD, 1); //curl_easy_setopt(conn, CURLOPT_READDATA, &UploadData); //curl_easy_setopt(conn, CURLOPT_READFUNCTION, UploadReadFunc); //curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); PageData.Clear(); PageHeader.Clear(); claconncode = (curl_easy_perform(conn)); if (claconncode == CURLE_OK){ } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %i\n", http_code); return ContactListFinal; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(claconncode)); int http_code = 0; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code); fprintf(stderr, "Error code was: %i\n", http_code); return ContactListFinal; } } xmlDocPtr xmlCardDAVDoc; xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0); xmlNodePtr nodeLevel1; xmlNodePtr nodeLevel2; xmlNodePtr nodeLevel3; xmlNodePtr nodeLevel4; xmlNodePtr nodeLevel5; xmlNodePtr nodeLevel6; xmlNodePtr nodeStatusLv1; xmlNodePtr nodeStatusLv2; std::map xmlDataMap; std::map ServerETagData; wxString DataFilename; wxString DataSyncToken; int DataFileStatus; wxString ETagData; bool SyncTokenFound = FALSE; std::string xmlStringSafe; // Tranverse through the catacombs of the response to get our ETag for the file and // the server syncronisation token. // Start by getting all the server ETag data. 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) { DataFileStatus = 0; bool HREFFound = FALSE; bool ETagFound = FALSE; bool HTTPStatus = FALSE; 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(); } HREFFound = TRUE; } } } else { for (nodeLevel4 = nodeLevel3->children; nodeLevel4 != NULL; nodeLevel4 = nodeLevel4->next) { for (nodeStatusLv1 = nodeLevel3->children; nodeStatusLv1 != NULL; nodeStatusLv1 = nodeStatusLv1->next) { if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){ DataFileStatus = 2; HTTPStatus = TRUE; } if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") || !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") || !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE) { // Get the filename. for (nodeStatusLv2 = nodeStatusLv1->children; nodeStatusLv2 != NULL; nodeStatusLv2 = nodeStatusLv2->next) { if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") || !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") || !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text") ){ if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){ DataFileStatus = 1; HTTPStatus = TRUE; // This is currently in a WebDAV draft and may hopefully be enabled when this changes. //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){ // DataFileStatus = 0; } } } } } 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 = wxString::FromUTF8((const char*)nodeLevel6->content); if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){ ETagData.Remove(0, 1); ETagData.RemoveLast(); } ETagFound = TRUE; } } } } } if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){ // Add to the map data. FileSyncData SData; SData.ETagData = ETagData; SData.DataFlag = DataFileStatus; ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData)); } // Reset the values. HREFFound = FALSE; ETagFound = FALSE; HTTPStatus = FALSE; } if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") || !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") || !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) && SyncTokenFound == FALSE ){ for (nodeLevel3 = nodeLevel2->children; nodeLevel3 != NULL; nodeLevel3 = nodeLevel3->next) { if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") || !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") || !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text") ){ DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content); SyncTokenFound = TRUE; } } } } } for (nodeLevel1 = xmlCardDAVDoc->children; nodeLevel1 != NULL; nodeLevel1 = nodeLevel1->next) { for (nodeLevel2 = nodeLevel1->children; nodeLevel2 != NULL; nodeLevel2 = nodeLevel2->next) { DataFileStatus = 0; bool HREFFound = FALSE; bool ETagFound = FALSE; bool HTTPStatus = FALSE; 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(); } HREFFound = TRUE; } } } else { for (nodeLevel4 = nodeLevel3->children; nodeLevel4 != NULL; nodeLevel4 = nodeLevel4->next) { for (nodeStatusLv1 = nodeLevel3->children; nodeStatusLv1 != NULL; nodeStatusLv1 = nodeStatusLv1->next) { if (wxString::FromUTF8((const char*)nodeStatusLv1->content) == wxT("HTTP/1.1 404 Not Found")){ DataFileStatus = 2; HTTPStatus = TRUE; } if ((!xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"status") || !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"d:status") || !xmlStrcmp(nodeStatusLv1->name, (const xmlChar *)"D:status")) && HTTPStatus == FALSE) { // Get the filename. for (nodeStatusLv2 = nodeStatusLv1->children; nodeStatusLv2 != NULL; nodeStatusLv2 = nodeStatusLv2->next) { if (!xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"text") || !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"d:text") || !xmlStrcmp(nodeStatusLv2->name, (const xmlChar *)"D:text") ){ if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 200 OK")){ DataFileStatus = 1; HTTPStatus = TRUE; // This is currently in a WebDAV draft and may hopefully be enabled when this changes. //} else if (wxString::FromUTF8((const char*)nodeStatusLv2->content) == wxT("HTTP/1.1 201 Created")){ // DataFileStatus = 0; } } } } } 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 = wxString::FromUTF8((const char*)nodeLevel6->content); if (ETagData.Mid(0, 1) == wxT("\"") && ETagData.Mid((ETagData.Len() - 1), 1) == wxT("\"")){ ETagData.Remove(0, 1); ETagData.RemoveLast(); } ETagFound = TRUE; } } } } } } if (HREFFound == TRUE && HTTPStatus == TRUE && DataFileStatus == 2){ FileSyncData SData; SData.ETagData = wxT(""); SData.DataFlag = DataFileStatus; ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData)); } if (HREFFound == TRUE && ETagFound == TRUE && HTTPStatus == TRUE){ // Add to the map data. FileSyncData SData; SData.ETagData = ETagData; SData.DataFlag = DataFileStatus; ContactListFinal.ListData.insert(std::make_pair(DataFilename, SData)); } // Reset the values. HREFFound = FALSE; ETagFound = FALSE; HTTPStatus = FALSE; DataFilename.Clear(); if ((!xmlStrcmp(nodeLevel2->name, (const xmlChar *)"sync-token") || !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"d:sync-token") || !xmlStrcmp(nodeLevel2->name, (const xmlChar *)"D:sync-token")) && SyncTokenFound == FALSE ){ for (nodeLevel3 = nodeLevel2->children; nodeLevel3 != NULL; nodeLevel3 = nodeLevel3->next) { if (!xmlStrcmp(nodeLevel3->name, (const xmlChar *)"text") || !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"d:text") || !xmlStrcmp(nodeLevel3->name, (const xmlChar *)"D:text") ){ DataSyncToken = wxString::FromUTF8((const char*)nodeLevel3->content); SyncTokenFound = TRUE; } } } } } // Get the sync token. if (SyncTokenFound == TRUE){ ContactListFinal.SyncToken = DataSyncToken; } else { } SleepFor(2000000000); /*timespec n1, n2; n1.tv_sec = 0; n1.tv_nsec = 2000000000L; nanosleep(&n1, &n2);*/ xmlFreeDoc(xmlCardDAVDoc); curl_easy_cleanup(conn); SyncDataBuffer.reset(); // Get the first result. return ContactListFinal; } int CardDAV::GetResultCode(){ return (int)claconncode; } int CardDAV::GetHTTPCode(){ return HTTPErrorCode; } wxString CardDAV::GetErrorBuffer(){ wxString ErrorBuffer = wxString::FromUTF8(curlerrbuffer); return ErrorBuffer; } wxString CardDAV::GetDefaultAddressBookURL(){ // First: Get the principal UID address. PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; CURLcode conncode; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); struct curl_slist *connhd = NULL; struct curl_slist *connhd2 = NULL; struct curl_slist *connhd3 = NULL; connhd = curl_slist_append(connhd, "Depth: 0"); connhd = curl_slist_append(connhd, "Prefer: return-minimal"); connhd = curl_slist_append(connhd, "Content-Type: application/xml; charset=utf-8"); connhd2 = curl_slist_append(connhd2, "Depth: 0"); connhd2 = curl_slist_append(connhd2, "Prefer: return-minimal"); connhd2 = curl_slist_append(connhd2, "Content-Type: application/xml; charset=utf-8"); connhd3 = curl_slist_append(connhd3, "Depth: 1"); connhd3 = curl_slist_append(connhd3, "Prefer: return-minimal"); connhd3 = curl_slist_append(connhd3, "Content-Type: application/xml; charset=utf-8"); struct CardDAVCURLPasser { CardDAV *Data; bool HeaderMode = TRUE; } CardDAVHeader, CardDAVFooter; CardDAVHeader.Data = this; CardDAVHeader.HeaderMode = TRUE; CardDAVFooter.Data = this; CardDAVFooter.HeaderMode = FALSE; wxString Data1; wxString Data2; wxString ETag; wxString ETagOriginal; wxString ETagServer; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); ServerAddressSSL = wxT("https://") + ServerAddressURL; ServerAddressNormal = wxT("http://") + ServerAddressURL; ServerAuth = ServerUser + wxT(":") + ServerPass; wxString SAURLPrincipals; wxString SAURLPrincipalURL; wxString SAURLAddressURL; if (ServerSSL){ SAURLPrincipals = ServerAddressSSL + wxT("principals/"); SAURLPrincipalURL = ServerAddressSSL; SAURLAddressURL = ServerAddressSSL; } else { SAURLPrincipals = ServerAddressNormal + wxT("principals/"); SAURLPrincipalURL = ServerAddressNormal; SAURLAddressURL = ServerAddressNormal; } wxString FinalPrefix; struct UploadDataStruc UploadData; // Setup the first query finding out where the principal URL is. const char* query = "\n" "\n" " " " \n" " " ""; // Setup the second query finding out where the address book home URL is. const char* query2 = "\n" "\n" " \n" " \n" " \n" ""; // Setup the third query finding out where the default address book URL is. const char* query3 = "\n" "\n" " \n" " \n" " \n" ""; if (ServerSSL){ curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLPrincipals.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd); if (AllowSelfSign == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0L); } conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ *ServerResult = TRUE; AuthPassed = TRUE; ValidResponse = TRUE; SSLStatus = TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = FALSE; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); return wxT(""); } } else { // No SSL. // Do an initial connection (incase of Digest authentication). PageData.Clear(); PageHeader.Clear(); curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLPrincipals.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, FALSE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd); conncode = (curl_easy_perform(conn)); // If the ETag is different to the non-matching X-XAB-ETAG and X-XAB-ETAG-ORIG, // then bring up the conflict resolution form. if (EditMode == TRUE){ } if (conncode == CURLE_OK){ } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n", GetHTTPCode()); return wxT(""); } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); return wxT(""); } } // Process the XML data from the application. xmlDocPtr xmlCardDAVDoc; xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0); 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) { SAURLPrincipalURL.Append(wxString::FromUTF8((const char*)nodeLevel7->content)); } } } } } } } } xmlFreeDoc(xmlCardDAVDoc); PageData.Clear(); PageHeader.Clear(); // Second: Get the addressbook-home-set curl_easy_reset(conn); if (ServerSSL){ curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLPrincipalURL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, FALSE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query2); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query2)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd2); if (AllowSelfSign == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0L); } conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ *ServerResult = TRUE; AuthPassed = TRUE; SSLStatus = TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = FALSE; ValidResponse = FALSE; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); return wxT(""); } } else { // No SSL. curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLPrincipalURL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, FALSE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query2); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query2)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd2); conncode = (curl_easy_perform(conn)); // If the ETag is different to the non-matching X-XAB-ETAG and X-XAB-ETAG-ORIG, // then bring up the conflict resolution form. if (EditMode == TRUE){ } if (conncode == CURLE_OK){ } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n", GetHTTPCode()); ValidResponse = FALSE; return wxT(""); } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ValidResponse = FALSE; return wxT(""); } } xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0); 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) { SAURLAddressURL.Append(wxString::FromUTF8((const char*)nodeLevel7->content)); } } } } } } } } xmlFreeDoc(xmlCardDAVDoc); PageData.Clear(); PageHeader.Clear(); // Finally: Get the default-addressbook-URL from the addressbook-home-set address. curl_easy_reset(conn); if (ServerSSL){ curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLAddressURL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, FALSE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query3); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query3)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd3); if (AllowSelfSign == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0L); } conncode = (curl_easy_perform(conn)); if (conncode == CURLE_OK){ *ServerResult = TRUE; AuthPassed = TRUE; SSLStatus = TRUE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); *ServerResult = FALSE; ValidResponse = FALSE; curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); return wxT(""); } } else { // No SSL. curl_easy_setopt(conn, CURLOPT_URL, (const char*)SAURLAddressURL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60); curl_easy_setopt(conn, CURLOPT_FAILONERROR, FALSE); curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT); curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(conn, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(conn, CURLOPT_PROGRESSFUNCTION, ProgressFunc); curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(conn, CURLOPT_CUSTOMREQUEST, "PROPFIND"); curl_easy_setopt(conn, CURLOPT_POSTFIELDS, query3); curl_easy_setopt(conn, CURLOPT_POSTFIELDSIZE, strlen(query3)); curl_easy_setopt(conn, CURLOPT_HTTPHEADER, connhd3); conncode = (curl_easy_perform(conn)); // If the ETag is different to the non-matching X-XAB-ETAG and X-XAB-ETAG-ORIG, // then bring up the conflict resolution form. if (EditMode == TRUE){ } if (conncode == CURLE_OK){ } else if (conncode == CURLE_HTTP_RETURNED_ERROR){ curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &HTTPErrorCode); fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n", GetHTTPCode()); ValidResponse = FALSE; return wxT(""); } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ValidResponse = FALSE; return wxT(""); } } xmlCardDAVDoc = xmlReadMemory(PageData.mb_str(wxConvUTF8), (int)PageData.Len(), "noname.xml", NULL, 0); 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) { FinalPrefix = wxString::FromUTF8((const char*)nodeLevel7->content); } } } } } } } } xmlFreeDoc(xmlCardDAVDoc); PageData.Clear(); PageHeader.Clear(); return FinalPrefix; } SSLCertCollection CardDAV::BuildSSLCollection(CURL *conn){ SSLCertCollection SSLCertInfo; // Grab the certificate data. union { struct curl_slist *certdata; struct curl_certinfo *certinfo; } certptr; certptr.certdata = NULL; curl_easy_getinfo(conn, CURLINFO_CERTINFO, &certptr.certinfo); wxString CertPropName; wxString CertPropValue; for (int i = 0; i < certptr.certinfo->num_of_certs; i++){ struct curl_slist *slist; SSLCertData SSLCertDataInc; for (slist = certptr.certinfo->certinfo[i]; slist; slist = slist->next){ wxStringTokenizer CertDataInc(wxString::FromUTF8(slist->data), ":"); // Get first token as the property name. CertPropName = CertDataInc.GetNextToken(); // 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; } SSLCertCollection CardDAV::GetCertificateData(){ // Pass on the collected certificate data. return SSLCertCol; } wxString CardDAV::GetErrorMessage(){ return ErrorMessage; }