Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Added the CalDAVSend subroutine which is used when uploading data.
[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 CalDAVReceive(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 size_t CalDAVSend(char *SendBuffer, size_t Size, size_t NewMemoryBytes, void *DataStruct){
37         struct CalDAVSendData *UploadPtr = (struct CalDAVSendData *)DataStruct;
38         
39         if (UploadPtr->sizeleft){
41                 UploadPtr->sizeleft--;
42                 char CharSend;
44                 CharSend = (*UploadPtr->readptr)[UploadPtr->seek];
45                 
46                 *SendBuffer = CharSend;
47                 
48                 UploadPtr->seek++;
50                 return 1;
52         }
54         return 0;
56 }
58 CalDAV::CalDAV(){
60         // Setup the objects within the CalDAV connection 
61         // object.
62         
63         ConnectionHandle = curl_easy_init();
64         
65 }
67 CalDAV::~CalDAV(){
68         
69         // Destory the objects within the CalDAV connection
70         // object.
71         
72         curl_easy_cleanup(ConnectionHandle);
73         ConnectionHandle = nullptr;
74         
75 }
77 void CalDAV::SetupConnectionData(CalDAVConnectionData *ConnData){
78         
79         // Check if ConnData is a nullptr, return if it is.
80         
81         if (ConnData == nullptr){
82                 return;
83         }
84         
85         // Set the connection settings to the values from ConnData.
87         ConnectionData = (*ConnData);
88         
89 }
91 CalDAVStatus CalDAV::GetConnectionData(){
92         
93         // Get the current connection settings for the CalDAV
94         // connection object and return a CalDAVStatus object.
95         
96         CalDAVStatus ConnectionStatus;
97         
98         ConnectionStatus.Hostname = ConnectionData.Hostname;
99         ConnectionStatus.Port = ConnectionData.Port;
100         ConnectionStatus.Username = ConnectionData.Username;
101         ConnectionStatus.Prefix = ConnectionData.Prefix;
102         ConnectionStatus.UseSSL = ConnectionData.UseSSL;
103         ConnectionStatus.Timeout = ConnectionData.Timeout;
104         
105         return ConnectionStatus;
106         
109 CalDAVServerResult CalDAV::Connect(){
111         CalDAVServerResult ServerResult;
113         string ServerAddress = "";
114         string ServerUserPass = "";
116         // Setup the server address.
117         
118         ServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
120         // Setup the server password.
121         
122         ServerUserPass += ConnectionData.Username;
123         ServerUserPass += ":";
124         ServerUserPass += ConnectionData.Password;
125         
126         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, ServerAddress.c_str());
127         curl_easy_setopt(ConnectionHandle, CURLOPT_USERPWD, ServerUserPass.c_str());
128         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
129         curl_easy_setopt(ConnectionHandle, CURLOPT_FAILONERROR, 1L);
130         curl_easy_setopt(ConnectionHandle, CURLOPT_TIMEOUT, ConnectionData.Timeout);
131         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEFUNCTION, CalDAVOutput);
132         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEDATA, &ServerData);
133         curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEHEADER, &ServerHeader);
134         
135         // Connect to the CalDAV server.
136         
137         ServerResult.Code = curl_easy_perform(ConnectionHandle);
139         // Process the result received from the server.
140         
141         if (ServerResult.Code != CURLE_OK){
142                 
143                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;
144                 
145         } else {
146                 
147                 ServerResult.Result = CALDAVQUERYRESULT_OK;
148                 
149         }
150         
151         // Get the HTTP code.
152         
153         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
154         
155         return ServerResult;
156         
159 CalDAVServerSupport CalDAV::GetServerSupport(){
161         CalDAVServerSupport ServerStatus;
162         
163         // Setup the server connection.
164         
165         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
166         
167         CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
168         
169         if (ServerResult != CURLE_OK){
170                 return ServerStatus;
171         }
172         
173         // Check that the server header has data in,
174         // otherwise return an "empty" CalDAVServerSupport.
175         
176         if (ServerHeader.size() == 0){
177                 return ServerStatus;
178         }
179         
180         // Process each line looking for the first DAV header 
181         // line.
182         
183         bool NewlineMode = true;
184         
185         string DAVLine;
186         
187         for (int CharSeek = 0; CharSeek < ServerHeader.size(); CharSeek++){
188                 
189                 if (NewlineMode == true){
190                         
191                         // Check if we have reached the end of the string.
192                         
193                         if (CharSeek >= ServerHeader.size()){
194                                 
195                                 break;
196                                 
197                         }
198                         
199                         // Check the first four letters to make sure
200                         // they are 'DAV:'.
201                         
202                         string DAVHeaderCheck = "";
203                         
204                         try {
205                                 DAVHeaderCheck = ServerHeader.substr(CharSeek, 4);
206                         }
207                         
208                         catch (out_of_range &oor){
209                                 break;
210                         }
211                         
212                         if (DAVHeaderCheck == "DAV:"){
213                                 
214                                 CharSeek += 5;
215                                 
216                                 for (; CharSeek < ServerHeader.size(); CharSeek++){
217                                         
218                                         if (ServerHeader[CharSeek] == '\n'){
219                                         
220                                                 break;
221                                                 
222                                         }
223                                         
224                                         DAVLine.push_back(ServerHeader[CharSeek]);
225                                         
226                                 }
227                                 
228                                 break;
229                                 
230                         }
231                         
232                         NewlineMode = false;
233                         
234                 }
235                 
236                 if (ServerHeader[CharSeek] == '\n'){
237                         
238                         NewlineMode = true;
239                         
240                 }
241                 
242         }
243         
244         // Process the DAV line.
245         
246         vector<string> DAVLineData;
247         string DAVSegmentString;
248         
249         for (int CharSeek = 0; CharSeek < DAVLine.size(); CharSeek++){
250                 
251                 if (DAVLine[CharSeek] == ' '){
252                         continue;
253                 }
254                 
255                 if (DAVLine[CharSeek] == ','){
256                         
257                         DAVLineData.push_back(DAVSegmentString);
258                         DAVSegmentString.clear();
259                         continue;
260                         
261                 }
262                 
263                 DAVSegmentString += DAVLine[CharSeek];
264                 
265         }
266         
267         // Process the DAV values and set each value
268         // to true as required.
269         
270         for (int DAVItemSeek = 0; 
271                 DAVItemSeek < DAVLineData.size();
272                 DAVItemSeek++){
273                         
274                 if (DAVLineData.at(DAVItemSeek) == "calendar-access"){
275                         
276                         ServerStatus.BasicSupport = true;
277                 
278                 }
279                         
280         }
281         
282         return ServerStatus;
283         
286 bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
288         // Check if the passed CalDAV Connection Data is has
289         // an address set. Return false if nullptr is used.
291         if (ConnData == nullptr){
292         
293                 return false;
294         
295         }
296         
297         // Check the server hostname. Return false
298         // if no value has been set.
299         
300         if (ConnData->Hostname.size() == 0){
301         
302                 return false;
303         
304         }
305         
306         // Check the server port. Return false if
307         // no value has been set or the port number
308         // is less than 1 or higher than 65535.
309         
310         if (ConnData->Port < 1 || ConnData->Port > 65535){
311         
312                 return false;
313         
314         }
315         
316         // Check the server username. Return false
317         // if no value has been set.
318         
319         if (ConnData->Username.size() == 0){
320                 
321                 return false;
322                 
323         }       
324         
325         // Check the server password. Return false
326         // if no value has been set.
327         
328         if (ConnData->Password.size() == 0){
329                 
330                 return false;
331                 
332         }
334         // Cannot check UseSSL: It is either true
335         // or false.
336         
337         // Cannot check Prefix: The prefix may need
338         // to be worked out first.
340         // No errors were found whilst checking so
341         // return true.
342         
343         return true;
347 string BuildServerAddress(CalDAVConnectionData *ConnData, string URIAddress){
348         
349         string ServerAddress;
350         
351         // Setup the server address.
352         
353         if (ConnData->UseSSL == true){
354                 ServerAddress += "https://";
355         } else {
356                 ServerAddress += "http://";
357         }
358         
359         ServerAddress += ConnData->Hostname;
360         
361         // Check if server port is 80, otherwise
362         // specifiy the port number in the address.
363         
364         if (ConnData->Port != 80){
365                 ServerAddress += ":";
366                 ServerAddress += to_string(ConnData->Port);
367         }
368         
369         ServerAddress += URIAddress;
370         
371         return ServerAddress;
372         
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