X-Git-Url: http://Server1/repobrowser/?a=blobdiff_plain;f=source%2Fobjects%2FCalDAV%2FCalDAV.cpp;h=ea578a9ae0924608e2cd9bffcfea2505877ac19a;hb=6013b76daf2e9e2cf790584aea18a6f2a5bf1aa8;hp=33c81b4b769df9fe456b0a59880ee59b61e9269c;hpb=71dcf590a74da5c14b465a25f8d91ed7ef5c342d;p=xestiacalendar%2F.git diff --git a/source/objects/CalDAV/CalDAV.cpp b/source/objects/CalDAV/CalDAV.cpp index 33c81b4..ea578a9 100644 --- a/source/objects/CalDAV/CalDAV.cpp +++ b/source/objects/CalDAV/CalDAV.cpp @@ -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 + #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 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 = "\n" + "\n" + " \n" + " \n" + " \n" + ""; + + 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