1 // carddav-connect.cpp - CardDAV Object - Connect subroutines.
3 // (c) 2012-2015 Xestia Software Development.
5 // This file is part of Xestia Address Book.
7 // Xestia Address Book is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
11 // Xestia Address Book is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Address Book. If not, see <http://www.gnu.org/licenses/>
20 #include "../version.h"
22 #include <wx/tokenzr.h>
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
28 #include "../vcard/vcard.h"
29 #include "../common/dirs.h"
31 bool CardDAV::Connect(){
38 AbortConnection = FALSE;
42 wxString ServerAddressURL;
44 wxString ServerAddressSSL;
45 wxString ServerAddressNormal;
47 conn = curl_easy_init();
49 struct CardDAVCURLPasser {
52 bool HeaderMode = TRUE;
54 } CardDAVHeader, CardDAVFooter;
56 CardDAVHeader.Data = this;
57 CardDAVHeader.HeaderMode = TRUE;
59 CardDAVFooter.Data = this;
60 CardDAVFooter.HeaderMode = FALSE;
65 ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
66 ServerAddressSSL = wxT("https://") + ServerAddressURL;
67 ServerAddressNormal = wxT("http://") + ServerAddressURL;
69 ServerAuth = ServerUser + wxT(":") + ServerPass;
75 char *ServerAdrSSLChar = new char[(ServerAddressSSL.Length() - 1)];
76 //memset(ServerAdrSSLChar, 0, ServerAddressSSL.Length());
77 strncpy(ServerAdrSSLChar, (const char*)ServerAddressSSL.mb_str(wxConvUTF8), (ServerAddressSSL.Length() - 1));
79 char *ServerAdrNorChar = new char[(ServerAddressNormal.Length() - 1)];
80 //memset(ServerAdrNorChar, 0, ServerAddressSSL.Length());
81 strncpy(ServerAdrNorChar, (const char*)ServerAddressNormal.mb_str(wxConvUTF8), (ServerAddressNormal.Length() - 1));
83 char *ServerAuthChar = new char[(ServerAuth.Length() - 1)];
84 //memset(ServerAuthChar, 0, ServerAddressSSL.Length());
85 strncpy(ServerAuthChar, (const char*)ServerAuth.mb_str(wxConvUTF8), (ServerAuth.Length() - 1));
92 struct curl_slist *certdata;
93 struct curl_certinfo *certinfo;
98 // Setup two initial connections and attempt to get the certificate data.
100 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
101 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
103 conncode = (curl_easy_perform(conn));
105 // Check if the SSL certificate is valid or self-signed or some other
108 if (conncode == CURLE_OK){
110 // Connection is OK. Do nothing.
112 } else if (conncode == CURLE_SSL_CACERT){
114 // Post message saying SSL certificate is invalid.
116 curl_easy_getinfo(conn, CURLINFO_CERTINFO, &ptr.certdata);
120 fprintf(stderr, "curl_easy_perform() failed: %s\n",
121 curl_easy_strerror(conncode));
123 ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode));
125 *ServerResult = FALSE;
130 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
131 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
132 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
133 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
134 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
135 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
136 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
137 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
138 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
139 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
140 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
141 curl_easy_setopt(conn, CURLOPT_CERTINFO, 1);
143 if (AllowSelfSign == TRUE){
144 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0L);
145 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0L);
148 conncode = (curl_easy_perform(conn));
152 curl_easy_getinfo(conn, CURLINFO_CERTINFO, &ptr.certdata);
154 if (conncode == CURLE_OK){
156 // Process the server header response and look for
157 // 'addressbook' within the DAV header.
159 wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n"));
160 wxString wxSHeaderLine;
161 std::map<int, wxString> DAVHeaderLines;
163 while (wxSHeaderLines.HasMoreTokens()){
165 wxSHeaderLine = wxSHeaderLines.GetNextToken();
167 if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){
169 // Look for address book in the line.
171 if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){
173 HasCalDAVSupport = TRUE;
181 *ServerResult = TRUE;
182 ValidResponse = TRUE;
187 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
189 fprintf(stderr, "curl_easy_perform() failed: %s\n",
190 curl_easy_strerror(conncode));
192 ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode));
194 *ServerResult = TRUE;
195 ValidResponse = FALSE;
202 fprintf(stderr, "curl_easy_perform() failed: %s\n",
203 curl_easy_strerror(conncode));
205 ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode));
207 *ServerResult = FALSE;
216 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
217 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
218 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
219 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
220 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
221 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
222 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
223 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
224 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
225 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
226 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
228 conncode = (curl_easy_perform(conn));
230 if (conncode == CURLE_OK){
232 // Process the server header response and look for
233 // 'addressbook' within the DAV header.
235 wxStringTokenizer wxSHeaderLines(PageHeader, wxT("\r\n"));
236 wxString wxSHeaderLine;
237 std::map<int, wxString> DAVHeaderLines;
239 while (wxSHeaderLines.HasMoreTokens()){
241 wxSHeaderLine = wxSHeaderLines.GetNextToken();
243 if (wxSHeaderLine.Mid(0, 4) == wxT("DAV:")){
245 // Look for address book in the line.
247 if (wxSHeaderLine.Find(wxT("addressbook")) != wxNOT_FOUND){
249 HasCalDAVSupport = TRUE;
257 *ServerResult = TRUE;
258 ValidResponse = TRUE;
263 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
265 fprintf(stderr, "curl_easy_perform() failed: %s\n",
266 curl_easy_strerror(conncode));
268 *ServerResult = TRUE;
269 ValidResponse = FALSE;
276 fprintf(stderr, "curl_easy_perform() failed: %s\n",
277 curl_easy_strerror(conncode));
279 *ServerResult = FALSE;
284 // TODO: Double check and make sure HTTP Authentication is possible.
288 *ServerResult = TRUE;