Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Reset the connection status in CalDAV and add GetUserPrincipal
[xestiacalendar/.git] / source / objects / CalDAV / CalDAV.cpp
index 33c81b4..ea578a9 100644 (file)
@@ -1,5 +1,383 @@
+// CalDAV.cpp - CalDAV Connection Object.
+//
+// (c) 2016 Xestia Software Development.
+//
+// This file is part of Xestia Calendar.
+//
+// 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 Calendar. If not, see <http://www.gnu.org/licenses/>
+
 #include "CalDAV.h"
 
+using namespace std;
+
+size_t CalDAVReceive(char *ReceivedBuffer, size_t Size, size_t NewMemoryBytes, string *StringPointer)
+{
+       
+       string ReceivedBufferString = "";
+       ReceivedBufferString.append(ReceivedBuffer, NewMemoryBytes);
+       
+       StringPointer->append(ReceivedBufferString);
+       
+       return Size * NewMemoryBytes;
+       
+}
+
+size_t CalDAVSend(char *SendBuffer, size_t Size, size_t NewMemoryBytes, void *DataStruct){
+
+       struct CalDAVSendData *UploadPtr = (struct CalDAVSendData *)DataStruct;
+       
+       if (UploadPtr->sizeleft){
+
+               UploadPtr->sizeleft--;
+               char CharSend;
+
+               CharSend = (*UploadPtr->readptr)[UploadPtr->seek];
+               
+               *SendBuffer = CharSend;
+               
+               UploadPtr->seek++;
+
+               return 1;
+
+       }
+
+       return 0;
+
+}
+
+CalDAV::CalDAV(){
+
+       // Setup the objects within the CalDAV connection 
+       // object.
+       
+       ConnectionHandle = curl_easy_init();
+       
+}
+
+CalDAV::~CalDAV(){
+       
+       // Destory the objects within the CalDAV connection
+       // object.
+       
+       curl_easy_cleanup(ConnectionHandle);
+       ConnectionHandle = nullptr;
+       
+}
+
+void CalDAV::SetupConnectionData(CalDAVConnectionData *ConnData){
+       
+       // Check if ConnData is a nullptr, return if it is.
+       
+       if (ConnData == nullptr){
+               return;
+       }
+       
+       // Set the connection settings to the values from ConnData.
+
+       ConnectionData = (*ConnData);
+       
+}
+
+CalDAVStatus CalDAV::GetConnectionData(){
+       
+       // Get the current connection settings for the CalDAV
+       // connection object and return a CalDAVStatus object.
+       
+       CalDAVStatus ConnectionStatus;
+       
+       ConnectionStatus.Hostname = ConnectionData.Hostname;
+       ConnectionStatus.Port = ConnectionData.Port;
+       ConnectionStatus.Username = ConnectionData.Username;
+       ConnectionStatus.Prefix = ConnectionData.Prefix;
+       ConnectionStatus.UseSSL = ConnectionData.UseSSL;
+       ConnectionStatus.Timeout = ConnectionData.Timeout;
+       
+       return ConnectionStatus;
+       
+}
+
+CalDAVServerResult CalDAV::Connect(){
+
+       CalDAVServerResult ServerResult;
+
+       string ServerAddress = "";
+       string ServerUserPass = "";
+
+       // Setup the server address.
+       
+       ServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+
+       // Setup the server password.
+       
+       ServerUserPass += ConnectionData.Username;
+       ServerUserPass += ":";
+       ServerUserPass += ConnectionData.Password;
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, ServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_USERPWD, ServerUserPass.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_FAILONERROR, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_TIMEOUT, ConnectionData.Timeout);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEFUNCTION, CalDAVReceive);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEDATA, &ServerData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEHEADER, &ServerHeader);
+       
+       // Connect to the CalDAV server.
+       
+       ServerResult.Code = curl_easy_perform(ConnectionHandle);
+
+       // Process the result received from the server.
+       
+       if (ServerResult.Code != CURLE_OK){
+               
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;
+               
+       } else {
+               
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+               
+       }
+       
+       // Get the HTTP code.
+       
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::GetServerResult(){
+       
+       return ConnectionServerResult;
+       
+}
+
+CalDAVServerSupport CalDAV::GetServerSupport(){
+
+       CalDAVServerSupport ServerStatus;
+       
+       // Setup the server connection.
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       // Set the results.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               return ServerStatus;
+       }
+       
+       // Check that the server header has data in,
+       // otherwise return an "empty" CalDAVServerSupport.
+       
+       if (ServerHeader.size() == 0){
+               return ServerStatus;
+       }
+       
+       // Process each line looking for the first DAV header 
+       // line.
+       
+       bool NewlineMode = true;
+       
+       string DAVLine;
+       
+       for (int CharSeek = 0; CharSeek < ServerHeader.size(); CharSeek++){
+               
+               if (NewlineMode == true){
+                       
+                       // Check if we have reached the end of the string.
+                       
+                       if (CharSeek >= ServerHeader.size()){
+                               
+                               break;
+                               
+                       }
+                       
+                       // Check the first four letters to make sure
+                       // they are 'DAV:'.
+                       
+                       string DAVHeaderCheck = "";
+                       
+                       try {
+                               DAVHeaderCheck = ServerHeader.substr(CharSeek, 4);
+                       }
+                       
+                       catch (out_of_range &oor){
+                               break;
+                       }
+                       
+                       if (DAVHeaderCheck == "DAV:"){
+                               
+                               CharSeek += 5;
+                               
+                               for (; CharSeek < ServerHeader.size(); CharSeek++){
+                                       
+                                       if (ServerHeader[CharSeek] == '\n'){
+                                       
+                                               break;
+                                               
+                                       }
+                                       
+                                       DAVLine.push_back(ServerHeader[CharSeek]);
+                                       
+                               }
+                               
+                               break;
+                               
+                       }
+                       
+                       NewlineMode = false;
+                       
+               }
+               
+               if (ServerHeader[CharSeek] == '\n'){
+                       
+                       NewlineMode = true;
+                       
+               }
+               
+       }
+       
+       // Process the DAV line.
+       
+       vector<string> DAVLineData;
+       string DAVSegmentString;
+       
+       for (int CharSeek = 0; CharSeek < DAVLine.size(); CharSeek++){
+               
+               if (DAVLine[CharSeek] == ' '){
+                       continue;
+               }
+               
+               if (DAVLine[CharSeek] == ','){
+                       
+                       DAVLineData.push_back(DAVSegmentString);
+                       DAVSegmentString.clear();
+                       continue;
+                       
+               }
+               
+               DAVSegmentString += DAVLine[CharSeek];
+               
+       }
+       
+       // Process the DAV values and set each value
+       // to true as required.
+       
+       for (int DAVItemSeek = 0; 
+               DAVItemSeek < DAVLineData.size();
+               DAVItemSeek++){
+                       
+               if (DAVLineData.at(DAVItemSeek) == "calendar-access"){
+                       
+                       ServerStatus.BasicSupport = true;
+               
+               }
+                       
+       }
+       
+       // Reset the connection status.
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);
+       
+       return ServerStatus;
+       
+}
+
+string CalDAV::GetUserPrincipal(){
+       
+       string CurrentUserPrincipal = "";
+       string UserPrincipalRequest = "";
+       CalDAVSendData UserPrincipalSendData;
+       
+       UserPrincipalRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<d:propfind xmlns:d=\"DAV:\">\n"
+       " <d:prop>\n"
+       "  <d:current-user-principal />\n"
+       " </d:prop>\n"
+       "</d:propfind>";
+       
+       UserPrincipalSendData.readptr = &UserPrincipalRequest;
+       UserPrincipalSendData.sizeleft = UserPrincipalRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *UserPrincipalRequestHeader = NULL;
+       
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Depth: 0");
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Prefer: return-minimal");
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, UserPrincipalRequestHeader);
+
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &UserPrincipalSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       // Set the results.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               
+               return CurrentUserPrincipal;
+               
+       }
+       
+       // Process the User Principal from the ServerData.
+
+       CurrentUserPrincipal = ProcessXMLUserPrincipal();
+       
+       // Reset the changed settings.
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+
+       return CurrentUserPrincipal;
+}
+
+CalDAVCalendarList CalDAV::GetCalendars(){
+       
+       CalDAVCalendarList ServerList;
+       
+       return ServerList;
+       
+}
+
 bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
 
        // Check if the passed CalDAV Connection Data is has
@@ -14,7 +392,7 @@ bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
        // Check the server hostname. Return false
        // if no value has been set.
        
-       if (ConnData->Hostname.size() > 0){
+       if (ConnData->Hostname.size() == 0){
        
                return false;
        
@@ -32,16 +410,20 @@ bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
        
        // Check the server username. Return false
        // if no value has been set.
-
-       if (ConnData->Username.size() > 0){
+       
+       if (ConnData->Username.size() == 0){
+               
                return false;
-       }
-
+               
+       }       
+       
        // Check the server password. Return false
        // if no value has been set.
-
-       if (ConnData->Password.size() > 0){
+       
+       if (ConnData->Password.size() == 0){
+               
                return false;
+               
        }
 
        // Cannot check UseSSL: It is either true
@@ -55,4 +437,32 @@ bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
        
        return true;
 
+}
+
+string BuildServerAddress(CalDAVConnectionData *ConnData, string URIAddress){
+       
+       string ServerAddress;
+       
+       // Setup the server address.
+       
+       if (ConnData->UseSSL == true){
+               ServerAddress += "https://";
+       } else {
+               ServerAddress += "http://";
+       }
+       
+       ServerAddress += ConnData->Hostname;
+       
+       // Check if server port is 80, otherwise
+       // specifiy the port number in the address.
+       
+       if (ConnData->Port != 80){
+               ServerAddress += ":";
+               ServerAddress += to_string(ConnData->Port);
+       }
+       
+       ServerAddress += URIAddress;
+       
+       return ServerAddress;
+       
 }
\ No newline at end of file
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