Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Adde code and unit tests for checking CalDAV support.
[xestiacalendar/.git] / source / objects / CalDAV / CalDAV.cpp
1 // CalDAV.cpp - CalDAV Connection Object.
2 //
3 // (c) 2016 Xestia Software Development.
4 //
5 // This file is part of Xestia Calendar.
6 //
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.
10 //
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.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
19 #include "CalDAV.h"
21 using namespace std;
23 size_t CalDAVOutput(char *ReceivedBuffer, size_t Size, size_t NewMemoryBytes, string *StringPointer)
24 {
25         
26         string ReceivedBufferString = "";
27         ReceivedBufferString.append(ReceivedBuffer, NewMemoryBytes);
28         
29         StringPointer->append(ReceivedBufferString);
30         
31         return Size * NewMemoryBytes;
32         
33 }
35 CalDAV::CalDAV(){
37         // Setup the objects within the CalDAV connection 
38         // object.
39         
40         ConnectionHandle = curl_easy_init();
41         
42 }
44 CalDAV::~CalDAV(){
45         
46         // Destory the objects within the CalDAV connection
47         // object.
48         
49         curl_easy_cleanup(ConnectionHandle);
50         ConnectionHandle = nullptr;
51         
52 }
54 void CalDAV::SetupConnectionData(CalDAVConnectionData *ConnData){
55         
56         // Check if ConnData is a nullptr, return if it is.
57         
58         if (ConnData == nullptr){
59                 return;
60         }
61         
62         // Set the connection settings to the values from ConnData.
64         ConnectionData = (*ConnData);
65         
66 }
68 CalDAVStatus CalDAV::GetConnectionData(){
69         
70         // Get the current connection settings for the CalDAV
71         // connection object and return a CalDAVStatus object.
72         
73         CalDAVStatus ConnectionStatus;
74         
75         ConnectionStatus.Hostname = ConnectionData.Hostname;
76         ConnectionStatus.Port = ConnectionData.Port;
77         ConnectionStatus.Username = ConnectionData.Username;
78         ConnectionStatus.Prefix = ConnectionData.Prefix;
79         ConnectionStatus.UseSSL = ConnectionData.UseSSL;
80         ConnectionStatus.Timeout = ConnectionData.Timeout;
81         
82         return ConnectionStatus;
83         
84 }
86 CalDAVServerResult CalDAV::Connect(){
88         CalDAVServerResult ServerResult;
90         string ServerAddress = "";
91         string ServerUserPass = "";
93         // Setup the server address.
94         
95         ServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
97         // Setup the server password.
98         
99         ServerUserPass += ConnectionData.Username;
100         ServerUserPass += ":";
101         ServerUserPass += ConnectionData.Password;
102         
103         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, ServerAddress.c_str());
104         curl_easy_setopt(ConnectionHandle, CURLOPT_USERPWD, ServerUserPass.c_str());
105         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
106         curl_easy_setopt(ConnectionHandle, CURLOPT_FAILONERROR, 1L);
107         curl_easy_setopt(ConnectionHandle, CURLOPT_TIMEOUT, ConnectionData.Timeout);
108         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEFUNCTION, CalDAVOutput);
109         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEDATA, &ServerData);
110         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEHEADER, &ServerHeader);
111         
112         // Connect to the CalDAV server.
113         
114         ServerResult.Code = curl_easy_perform(ConnectionHandle);
116         // Process the result received from the server.
117         
118         if (ServerResult.Code != CURLE_OK){
119                 
120                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;
121                 
122         } else {
123                 
124                 ServerResult.Result = CALDAVQUERYRESULT_OK;
125                 
126         }
127         
128         // Get the HTTP code.
129         
130         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
131         
132         return ServerResult;
133         
136 CalDAVServerSupport CalDAV::GetServerSupport(){
138         CalDAVServerSupport ServerStatus;
139         
140         // Setup the server connection.
141         
142         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
143         
144         CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
145         
146         if (ServerResult != CURLE_OK){
147                 return ServerStatus;
148         }
149         
150         // Check that the server header has data in,
151         // otherwise return an "empty" CalDAVServerSupport.
152         
153         if (ServerHeader.size() == 0){
154                 return ServerStatus;
155         }
156         
157         // Process each line looking for the first DAV header 
158         // line.
159         
160         bool NewlineMode = true;
161         
162         string DAVLine;
163         
164         for (int CharSeek = 0; CharSeek < ServerHeader.size(); CharSeek++){
165                 
166                 if (NewlineMode == true){
167                         
168                         // Check if we have reached the end of the string.
169                         
170                         if (CharSeek >= ServerHeader.size()){
171                                 
172                                 break;
173                                 
174                         }
175                         
176                         // Check the first four letters to make sure
177                         // they are 'DAV:'.
178                         
179                         string DAVHeaderCheck = "";
180                         
181                         try {
182                                 DAVHeaderCheck = ServerHeader.substr(CharSeek, 4);
183                         }
184                         
185                         catch (out_of_range &oor){
186                                 break;
187                         }
188                         
189                         if (DAVHeaderCheck == "DAV:"){
190                                 
191                                 CharSeek += 5;
192                                 
193                                 for (; CharSeek < ServerHeader.size(); CharSeek++){
194                                         
195                                         if (ServerHeader[CharSeek] == '\n'){
196                                         
197                                                 break;
198                                                 
199                                         }
200                                         
201                                         DAVLine.push_back(ServerHeader[CharSeek]);
202                                         
203                                 }
204                                 
205                                 break;
206                                 
207                         }
208                         
209                         NewlineMode = false;
210                         
211                 }
212                 
213                 if (ServerHeader[CharSeek] == '\n'){
214                         
215                         NewlineMode = true;
216                         
217                 }
218                 
219         }
220         
221         // Process the DAV line.
222         
223         vector<string> DAVLineData;
224         string DAVSegmentString;
225         
226         for (int CharSeek = 0; CharSeek < DAVLine.size(); CharSeek++){
227                 
228                 if (DAVLine[CharSeek] == ' '){
229                         continue;
230                 }
231                 
232                 if (DAVLine[CharSeek] == ','){
233                         
234                         DAVLineData.push_back(DAVSegmentString);
235                         DAVSegmentString.clear();
236                         continue;
237                         
238                 }
239                 
240                 DAVSegmentString += DAVLine[CharSeek];
241                 
242         }
243         
244         // Process the DAV values and set each value
245         // to true as required.
246         
247         for (int DAVItemSeek = 0; 
248                 DAVItemSeek < DAVLineData.size();
249                 DAVItemSeek++){
250                         
251                 if (DAVLineData.at(DAVItemSeek) == "calendar-access"){
252                         
253                         ServerStatus.BasicSupport = true;
254                 
255                 }
256                         
257         }
258         
259         return ServerStatus;
260         
263 bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
265         // Check if the passed CalDAV Connection Data is has
266         // an address set. Return false if nullptr is used.
268         if (ConnData == nullptr){
269         
270                 return false;
271         
272         }
273         
274         // Check the server hostname. Return false
275         // if no value has been set.
276         
277         if (ConnData->Hostname.size() == 0){
278         
279                 return false;
280         
281         }
282         
283         // Check the server port. Return false if
284         // no value has been set or the port number
285         // is less than 1 or higher than 65535.
286         
287         if (ConnData->Port < 1 || ConnData->Port > 65535){
288         
289                 return false;
290         
291         }
292         
293         // Check the server username. Return false
294         // if no value has been set.
295         
296         if (ConnData->Username.size() == 0){
297                 
298                 return false;
299                 
300         }       
301         
302         // Check the server password. Return false
303         // if no value has been set.
304         
305         if (ConnData->Password.size() == 0){
306                 
307                 return false;
308                 
309         }
311         // Cannot check UseSSL: It is either true
312         // or false.
313         
314         // Cannot check Prefix: The prefix may need
315         // to be worked out first.
317         // No errors were found whilst checking so
318         // return true.
319         
320         return true;
324 string BuildServerAddress(CalDAVConnectionData *ConnData, string URIAddress){
325         
326         string ServerAddress;
327         
328         // Setup the server address.
329         
330         if (ConnData->UseSSL == true){
331                 ServerAddress += "https://";
332         } else {
333                 ServerAddress += "http://";
334         }
335         
336         ServerAddress += ConnData->Hostname;
337         
338         // Check if server port is 80, otherwise
339         // specifiy the port number in the address.
340         
341         if (ConnData->Port != 80){
342                 ServerAddress += ":";
343                 ServerAddress += to_string(ConnData->Port);
344         }
345         
346         ServerAddress += URIAddress;
347         
348         return ServerAddress;
349         
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy