// carddav-connect.cpp - CardDAV Object - Connect subroutines. // // (c) 2012-2015 Xestia Software Development. // // This file is part of Xestia Address Book. // // Xestia Address Book is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by the // Free Software Foundation, version 3 of the license. // // Xestia Address Book is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with Xestia Address Book. If not, see #include "carddav.h" #include "../version.h" #include #include #include #include #include #include #include #include "../vcard/vcard.h" #include "../common/dirs.h" 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; }