1 // CalendarDataStorage.cpp - CalendarDataStorage class
3 // (c) 2016-2017 Xestia Software Development.
5 // This file is part of Xestia Calendar.
7 // Xestia Calendar 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 Calendar 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 Calendar. If not, see <http://www.gnu.org/licenses/>
19 #include "CalendarDataStorage.h"
21 #define CDS_RANDOMPOW 24
25 static int callback(void *NotUsed, int argc, char **argv, char **azColName){
29 CalendarDataStorage::CalendarDataStorage(){
31 // Initialise the SQLite database.
33 sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nullptr);
38 CalendarDataStorage::~CalendarDataStorage(){
40 // Destory the SQLite database.
46 void CalendarDataStorage::SetupTables(){
48 // Setup the tables for the Calendar Data Storage.
50 char *setupTablesErrMsg = nullptr;
53 // Setup the accounts table.
55 const char *accountsTableString;
56 accountsTableString = "CREATE TABLE accounts(id INTEGER PRIMARY KEY AUTOINCREMENT"
57 ", preferencesid INTEGER"
61 resultCode = sqlite3_exec(db, accountsTableString, callback, nullptr, &setupTablesErrMsg);
64 DataStorageInitOK = false;
68 // Setup the calendars table.
70 const char *calendarTableString;
71 calendarTableString = "CREATE TABLE calendars(id INTEGER PRIMARY KEY AUTOINCREMENT"
79 resultCode = sqlite3_exec(db, calendarTableString, callback, nullptr, &setupTablesErrMsg);
82 DataStorageInitOK = false;
86 // Setup the calendar entries table.
88 const char *calendarentriesTableString;
89 calendarentriesTableString = "CREATE TABLE calendarentries(id INTEGER PRIMARY KEY AUTOINCREMENT"
90 ", calendarid INTEGER"
92 ", entrydescription TEXT"
93 ", entrystartyear INTEGER"
94 ", entrystartmonth INTEGER"
95 ", entrystartday INTEGER"
96 ", entrystarthour INTEGER"
97 ", entrystartminute INTEGER"
98 ", entrystartsecond INTEGER"
99 ", entryendyear INTEGER"
100 ", entryendmonth INTEGER"
101 ", entryendday INTEGER"
102 ", entryendhour INTEGER"
103 ", entryendminute INTEGER"
104 ", entryendsecond INTEGER"
105 ", entrydurationweek INTEGER"
106 ", entrydurationday INTEGER"
107 ", entrydurationhour INTEGER"
108 ", entrydurationminute INTEGER"
109 ", entrydurationsecond INTEGER"
113 resultCode = sqlite3_exec(db, calendarentriesTableString, callback, nullptr, &setupTablesErrMsg);
115 if (resultCode != 0){
116 DataStorageInitOK = false;
120 // Setup the checksums table.
122 const char *checksumsTableString;
123 checksumsTableString = "CREATE TABLE checksums(checksumname TEXT PRIMARY KEY "
124 ", checksumvalue TEXT);";
126 resultCode = sqlite3_exec(db, checksumsTableString, callback, nullptr, &setupTablesErrMsg);
128 if (resultCode != 0){
129 DataStorageInitOK = false;
133 // Setup internal checksums.
135 CDSChecksumResult addChecksum = AddChecksum("internal_updatedata", "");
137 if (addChecksum != CDSCHECKSUM_OK){
138 DataStorageInitOK = false;
142 DataStorageInitOK = true;
146 bool CalendarDataStorage::DidInitOK()
149 return DataStorageInitOK;
153 CDSAccountResult CalendarDataStorage::AddAccount(string accountName, int accountPreferencesID)
156 CDSAccountResult addResult = CDSACCOUNT_UNITTESTFAIL;
159 sqlite3_stmt *statementHandle;
161 resultCode = sqlite3_prepare_v2(db, "INSERT INTO accounts (name, preferencesid) VALUES(?1, ?2);", -1, &statementHandle, nullptr);
163 if (resultCode != 0){
164 return CDSACCOUNT_FAILED;
167 resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC);
169 if (resultCode != 0){
170 return CDSACCOUNT_FAILED;
173 resultCode = sqlite3_bind_int(statementHandle, 2, accountPreferencesID);
175 if (resultCode != 0){
176 return CDSACCOUNT_FAILED;
179 resultCode = sqlite3_step(statementHandle);
181 if (resultCode != SQLITE_DONE){
182 return CDSACCOUNT_FAILED;
185 // Update the checksum.
187 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
189 addResult = CDSACCOUNT_OK;
195 CDSAccountList CalendarDataStorage::GetAccountList()
198 CDSAccountList accountList;
200 // Check if calendar exists first.
204 sqlite3_stmt *statementHandle;
206 resultCode = sqlite3_prepare_v2(db, "SELECT id, name, preferencesid from accounts;", -1, &statementHandle, nullptr);
208 if (resultCode != 0){
209 accountList.getAccountListResult = CDSACCOUNT_FAILED;
213 if (resultCode != 0){
214 accountList.getAccountListResult = CDSACCOUNT_FAILED;
218 resultCode = sqlite3_step(statementHandle);
220 if (resultCode == SQLITE_ROW){
222 } else if (resultCode == SQLITE_DONE) {
223 accountList.getAccountListResult = CDSACCOUNT_NOACCOUNT;
226 accountList.getAccountListResult = CDSACCOUNT_FAILED;
230 while (resultCode == SQLITE_ROW){
232 CDSGetAccountInfo accountInfo;
234 accountInfo.accountID = sqlite3_column_int(statementHandle, 0);
235 accountInfo.accountPreferencesID = sqlite3_column_int(statementHandle, 2);
237 stringstream calendarStream;
239 calendarStream << sqlite3_column_text(statementHandle, 1);
241 accountInfo.accountName = calendarStream.str();
242 accountInfo.accountInfoResult = CDSACCOUNT_OK;
244 accountList.accountList.push_back(accountInfo);
246 resultCode = sqlite3_step(statementHandle);
250 accountList.getAccountListResult = CDSACCOUNT_OK;
256 CDSGetAccountInfo CalendarDataStorage::GetAccount(string accountName)
259 CDSGetAccountInfo accountInfo;
260 accountInfo.accountInfoResult = CDSACCOUNT_UNITTESTFAIL;
263 sqlite3_stmt *statementHandle;
265 resultCode = sqlite3_prepare_v2(db, "SELECT name, id, preferencesid FROM accounts WHERE name=(?1);", -1, &statementHandle, nullptr);
267 if (resultCode != 0){
268 accountInfo.accountInfoResult = CDSACCOUNT_FAILED;
272 resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC);
274 if (resultCode != 0){
275 accountInfo.accountInfoResult = CDSACCOUNT_FAILED;
279 resultCode = sqlite3_step(statementHandle);
281 if (resultCode == SQLITE_DONE){
283 accountInfo.accountInfoResult = CDSACCOUNT_NOACCOUNT;
286 } else if (resultCode == SQLITE_ROW){
288 // Get the result data.
290 stringstream accountNameStream;
292 accountNameStream << sqlite3_column_text(statementHandle, 0);
294 accountInfo.accountName = accountNameStream.str();
295 accountInfo.accountID = sqlite3_column_int(statementHandle, 1);
296 accountInfo.accountPreferencesID = sqlite3_column_int(statementHandle, 2);
298 accountInfo.accountInfoResult = CDSACCOUNT_OK;
303 accountInfo.accountInfoResult = CDSACCOUNT_FAILED;
312 CDSAccountResult CalendarDataStorage::UpdateAccount(int accountID, string accountName)
315 CDSAccountResult updateResult = CDSACCOUNT_UNITTESTFAIL;
318 sqlite3_stmt *findHandle;
319 sqlite3_stmt *statementHandle;
321 // Check if account exists first.
323 resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr);
325 if (resultCode != 0){
326 return CDSACCOUNT_FAILED;
329 resultCode = sqlite3_bind_int(findHandle, 1, accountID);
331 if (resultCode != 0){
332 return CDSACCOUNT_FAILED;
335 resultCode = sqlite3_step(findHandle);
337 if (resultCode == SQLITE_ROW){
339 } else if (resultCode == SQLITE_DONE) {
340 return CDSACCOUNT_NOACCOUNT;
342 return CDSACCOUNT_FAILED;
345 // Update the account.
347 resultCode = sqlite3_prepare_v2(db, "UPDATE accounts SET name=(?1) WHERE id=(?2);", -1, &statementHandle, nullptr);
349 if (resultCode != 0){
350 return CDSACCOUNT_FAILED;
353 resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC);
355 if (resultCode != 0){
356 return CDSACCOUNT_FAILED;
359 resultCode = sqlite3_bind_int(statementHandle, 2, accountID);
361 if (resultCode != 0){
362 return CDSACCOUNT_FAILED;
365 resultCode = sqlite3_step(statementHandle);
367 if (resultCode != SQLITE_DONE){
368 return CDSACCOUNT_FAILED;
371 // Update the checksum.
373 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
375 updateResult = CDSACCOUNT_OK;
381 CDSAccountResult CalendarDataStorage::DeleteAccount(int accountID)
384 CDSAccountResult deleteResult = CDSACCOUNT_UNITTESTFAIL;
386 // Check if account exists first.
388 sqlite3_stmt *findHandle;
389 sqlite3_stmt *statementHandle;
390 sqlite3_stmt *calendarHandle;
393 resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr);
395 if (resultCode != 0){
396 return CDSACCOUNT_FAILED;
399 resultCode = sqlite3_bind_int(findHandle, 1, accountID);
401 if (resultCode != 0){
402 return CDSACCOUNT_FAILED;
405 resultCode = sqlite3_step(findHandle);
407 if (resultCode == SQLITE_ROW){
409 } else if (resultCode == SQLITE_DONE) {
410 return CDSACCOUNT_NOACCOUNT;
412 return CDSACCOUNT_FAILED;
415 // Delete the account.
417 resultCode = sqlite3_prepare_v2(db, "DELETE FROM accounts WHERE id=(?1);", -1, &statementHandle, nullptr);
419 if (resultCode != 0){
420 return CDSACCOUNT_FAILED;
423 resultCode = sqlite3_bind_int(statementHandle, 1, accountID);
425 if (resultCode != 0){
426 return CDSACCOUNT_FAILED;
429 resultCode = sqlite3_step(statementHandle);
431 if (resultCode == SQLITE_DONE){
432 //deleteResult = CDSACCOUNT_OK;
434 return CDSACCOUNT_FAILED;
437 // Get the calendar IDs and delete each calendar (and associated entries).
439 resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendars WHERE accountid=(?1);", -1, &calendarHandle, nullptr);
441 if (resultCode != 0){
442 return CDSACCOUNT_FAILED;
445 resultCode = sqlite3_bind_int(calendarHandle, 1, accountID);
447 if (resultCode != 0){
448 return CDSACCOUNT_FAILED;
451 resultCode = sqlite3_step(calendarHandle);
453 if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){
454 deleteResult = CDSACCOUNT_OK;
456 return CDSACCOUNT_FAILED;
459 while (resultCode == SQLITE_ROW){
461 int calendarDeleteID = sqlite3_column_int(calendarHandle, 0);
463 DeleteCalendar(calendarDeleteID);
465 resultCode = sqlite3_step(calendarHandle);
469 // Update the checksum.
471 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
473 deleteResult = CDSACCOUNT_OK;
480 CDSCalendarResult CalendarDataStorage::AddCalendar(int accountID, string calendarName, string calendarID, Colour calendarColour, string calendarDescription)
483 CDSCalendarResult addResult = CDSCALENDAR_UNITTESTFAIL;
486 sqlite3_stmt *statementHandle;
488 resultCode = sqlite3_prepare_v2(db, "INSERT INTO calendars (name, calendarid, accountid, colour, description) VALUES(?1, ?2, ?3, ?4, ?5);", -1, &statementHandle, nullptr);
490 if (resultCode != 0){
491 return CDSCALENDAR_FAILED;
494 resultCode = sqlite3_bind_text(statementHandle, 1, calendarName.c_str(), -1, SQLITE_STATIC);
496 if (resultCode != 0){
497 return CDSCALENDAR_FAILED;
500 resultCode = sqlite3_bind_text(statementHandle, 2, calendarID.c_str(), -1, SQLITE_STATIC);
502 if (resultCode != 0){
503 return CDSCALENDAR_FAILED;
506 resultCode = sqlite3_bind_int(statementHandle, 3, accountID);
508 if (resultCode != 0){
509 return CDSCALENDAR_FAILED;
512 resultCode = sqlite3_bind_text(statementHandle, 4, ((string)calendarColour).c_str(), -1, SQLITE_STATIC);
514 if (resultCode != 0){
515 return CDSCALENDAR_FAILED;
518 resultCode = sqlite3_bind_text(statementHandle, 5, calendarDescription.c_str(), -1, SQLITE_STATIC);
520 if (resultCode != 0){
521 return CDSCALENDAR_FAILED;
524 resultCode = sqlite3_step(statementHandle);
526 if (resultCode != SQLITE_DONE){
527 return CDSCALENDAR_FAILED;
530 // Update the checksum.
532 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
534 addResult = CDSCALENDAR_OK;
540 CDSGetCalendarInfo CalendarDataStorage::GetCalendar(std::string accountName, std::string calendarTextID)
543 CDSGetAccountInfo accountResult;
544 CDSGetCalendarInfo calendarResult;
545 sqlite3_stmt *statementHandle;
548 // Check if the account exists.
550 accountResult = GetAccount(accountName);
552 switch (accountResult.accountInfoResult){
555 calendarResult.accountName = accountResult.accountName;
556 calendarResult.accountInfoResult = CDSACCOUNT_OK;
558 case CDSACCOUNT_FAILED:
559 calendarResult.accountInfoResult = CDSACCOUNT_FAILED;
560 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
561 return calendarResult;
562 case CDSACCOUNT_NOACCOUNT:
563 calendarResult.accountInfoResult = CDSACCOUNT_NOACCOUNT;
564 calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR;
565 return calendarResult;
569 // Check if the calendar exists.
571 resultCode = sqlite3_prepare_v2(db, "SELECT id, accountid, name, calendarid, colour, description FROM calendars WHERE accountid=(?1) AND calendarid=(?2);", -1, &statementHandle, nullptr);
573 if (resultCode != 0){
574 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
575 return calendarResult;
578 resultCode = sqlite3_bind_int(statementHandle, 1, accountResult.accountID);
580 if (resultCode != 0){
581 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
582 return calendarResult;
585 resultCode = sqlite3_bind_text(statementHandle, 2, calendarTextID.c_str(), -1, SQLITE_STATIC);
587 if (resultCode != 0){
588 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
589 return calendarResult;
592 resultCode = sqlite3_step(statementHandle);
594 if (resultCode == SQLITE_DONE){
596 calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR;
597 return calendarResult;
599 } else if (resultCode == SQLITE_ROW){
601 // Get the calendar name.
603 stringstream calendarStream;
605 calendarStream << sqlite3_column_text(statementHandle, 2);
606 calendarResult.calendarName = calendarStream.str();
608 calendarStream.str("");
609 calendarStream << sqlite3_column_text(statementHandle, 3);
610 calendarResult.calendarTextID = calendarStream.str();
612 calendarStream.str("");
613 calendarStream << sqlite3_column_text(statementHandle, 4);
614 calendarResult.calendarColour = calendarStream.str();
616 calendarStream.str("");
617 calendarStream << sqlite3_column_text(statementHandle, 5);
618 calendarResult.calendarDescription = calendarStream.str();
620 calendarResult.calendarID = sqlite3_column_int(statementHandle, 0);
621 calendarResult.accountID = sqlite3_column_int(statementHandle, 1);
622 calendarResult.calendarInfoResult = CDSCALENDAR_OK;
623 return calendarResult;
627 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
628 return calendarResult;
632 return calendarResult;
636 CDSGetCalendarInfo CalendarDataStorage::GetCalendar(int calendarID)
639 CDSGetCalendarInfo calendarResult;
640 sqlite3_stmt *statementHandle;
641 sqlite3_stmt *accountHandle;
644 // Check if the calendar exists.
646 resultCode = sqlite3_prepare_v2(db, "SELECT id, accountid, name, calendarid, colour, description FROM calendars WHERE id=(?1);", -1, &statementHandle, nullptr);
648 if (resultCode != 0){
649 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
650 return calendarResult;
653 resultCode = sqlite3_bind_int(statementHandle, 1, calendarID);
655 if (resultCode != 0){
656 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
657 return calendarResult;
660 resultCode = sqlite3_step(statementHandle);
662 if (resultCode == SQLITE_DONE){
664 calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR;
665 return calendarResult;
667 } else if (resultCode == SQLITE_ROW){
669 // Get the calendar data.
671 stringstream calendarStream;
673 calendarStream << sqlite3_column_text(statementHandle, 2);
674 calendarResult.calendarName = calendarStream.str();
676 calendarStream.str("");
677 calendarStream << sqlite3_column_text(statementHandle, 3);
678 calendarResult.calendarTextID = calendarStream.str();
680 calendarStream.str("");
681 calendarStream << sqlite3_column_text(statementHandle, 4);
682 calendarResult.calendarColour = calendarStream.str();
684 calendarStream.str("");
685 calendarStream << sqlite3_column_text(statementHandle, 5);
686 calendarResult.calendarDescription = calendarStream.str();
688 calendarResult.calendarID = sqlite3_column_int(statementHandle, 0);
689 calendarResult.accountID = sqlite3_column_int(statementHandle, 1);
691 // Get the account name.
693 resultCode = sqlite3_prepare_v2(db, "SELECT name FROM accounts WHERE id=(?1);", -1, &accountHandle, nullptr);
695 if (resultCode != 0){
696 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
697 return calendarResult;
700 resultCode = sqlite3_bind_int(accountHandle, 1, calendarResult.accountID);
702 if (resultCode != 0){
703 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
704 return calendarResult;
707 resultCode = sqlite3_step(accountHandle);
709 if (resultCode == SQLITE_ROW){
711 stringstream accountStream;
712 accountStream << sqlite3_column_text(accountHandle, 0);
713 calendarResult.accountName = accountStream.str();
714 calendarResult.accountInfoResult = CDSACCOUNT_OK;
718 calendarResult.accountInfoResult = CDSACCOUNT_FAILED;
722 calendarResult.calendarInfoResult = CDSCALENDAR_OK;
723 return calendarResult;
727 calendarResult.calendarInfoResult = CDSCALENDAR_FAILED;
728 return calendarResult;
732 return calendarResult;
737 CDSCalendarResult CalendarDataStorage::UpdateCalendar(int calendarID, string calendarName, Colour calendarColour, std::string calendarDescription)
740 CDSCalendarResult updateResult = CDSCALENDAR_UNITTESTFAIL;
743 sqlite3_stmt *findHandle;
744 sqlite3_stmt *statementHandle;
746 // Check if calendar exists first.
748 resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr);
750 if (resultCode != 0){
751 return CDSCALENDAR_FAILED;
754 resultCode = sqlite3_bind_int(findHandle, 1, calendarID);
756 if (resultCode != 0){
757 return CDSCALENDAR_FAILED;
760 resultCode = sqlite3_step(findHandle);
762 if (resultCode == SQLITE_ROW){
764 } else if (resultCode == SQLITE_DONE) {
765 return CDSCALENDAR_NOCALENDAR;
767 return CDSCALENDAR_FAILED;
770 // Update the account.
772 resultCode = sqlite3_prepare_v2(db, "UPDATE calendars SET name=(?1), colour=(?2), description=(?3) WHERE id=(?4);", -1, &statementHandle, nullptr);
774 if (resultCode != 0){
775 return CDSCALENDAR_FAILED;
778 resultCode = sqlite3_bind_text(statementHandle, 1, calendarName.c_str(), -1, SQLITE_STATIC);
780 if (resultCode != 0){
781 return CDSCALENDAR_FAILED;
784 resultCode = sqlite3_bind_text(statementHandle, 2, string(calendarColour).c_str(), -1, SQLITE_STATIC);
786 if (resultCode != 0){
787 return CDSCALENDAR_FAILED;
790 resultCode = sqlite3_bind_text(statementHandle, 3, calendarDescription.c_str(), -1, SQLITE_STATIC);
792 if (resultCode != 0){
793 return CDSCALENDAR_FAILED;
796 resultCode = sqlite3_bind_int(statementHandle, 4, calendarID);
798 if (resultCode != 0){
799 return CDSCALENDAR_FAILED;
802 resultCode = sqlite3_step(statementHandle);
804 if (resultCode != SQLITE_DONE){
805 return CDSCALENDAR_FAILED;
808 // Update the checksum.
810 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
812 updateResult = CDSCALENDAR_OK;
818 CDSCalendarResult CalendarDataStorage::DeleteCalendar(int calendarID)
821 CDSCalendarResult deleteResult = CDSCALENDAR_UNITTESTFAIL;
823 // Check if account exists first.
825 sqlite3_stmt *findHandle;
826 sqlite3_stmt *statementHandle;
827 sqlite3_stmt *entriesHandle;
830 resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr);
832 if (resultCode != 0){
833 return CDSCALENDAR_FAILED;
836 resultCode = sqlite3_bind_int(findHandle, 1, calendarID);
838 if (resultCode != 0){
839 return CDSCALENDAR_FAILED;
842 resultCode = sqlite3_step(findHandle);
844 if (resultCode == SQLITE_ROW){
846 } else if (resultCode == SQLITE_DONE) {
847 return CDSCALENDAR_NOCALENDAR;
849 return CDSCALENDAR_FAILED;
852 // Delete the calendar.
854 resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendars WHERE id=(?1);", -1, &statementHandle, nullptr);
856 if (resultCode != 0){
857 return CDSCALENDAR_FAILED;
860 resultCode = sqlite3_bind_int(statementHandle, 1, calendarID);
862 if (resultCode != 0){
863 return CDSCALENDAR_FAILED;
866 resultCode = sqlite3_step(statementHandle);
868 if (resultCode != SQLITE_DONE){
869 return CDSCALENDAR_FAILED;
872 // Delete the calendar entries.
874 resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendarentries WHERE calendarid=(?1);", -1, &entriesHandle, nullptr);
876 if (resultCode != 0){
877 return CDSCALENDAR_FAILED;
880 resultCode = sqlite3_bind_int(entriesHandle, 1, calendarID);
882 if (resultCode != 0){
883 return CDSCALENDAR_FAILED;
886 resultCode = sqlite3_step(entriesHandle);
888 if (resultCode == SQLITE_DONE){
889 deleteResult = CDSCALENDAR_OK;
891 return CDSCALENDAR_FAILED;
894 // Update the checksum.
896 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
902 CDSAddEntryResult CalendarDataStorage::AddEvent(int calendarID, std::string filename)
905 CDSAddEntryResult addResult;
906 addResult.addEventResult = CDSENTRY_UNITTESTFAIL;
908 // Load the event file.
910 CalendarEventObject eventData;
911 CalendarObjectLoadResult eventLoadResult = eventData.LoadFile(filename);
913 // Check the result of the event file load.
915 switch (eventLoadResult){
917 case CALENDAROBJECTLOAD_OK:
919 case CALENDAROBJECTLOAD_MISSING:
920 addResult.addEventResult = CDSENTRY_MISSINGFILE;
922 case CALENDAROBJECTLOAD_INVALIDFORMAT:
923 addResult.addEventResult = CDSENTRY_INVALIDFILE;
925 case CALENDAROBJECTLOAD_CANNOTOPEN:
926 addResult.addEventResult = CDSENTRY_CANNOTOPENFILE;
931 // Check if calendar exists first.
935 sqlite3_stmt *findHandle;
936 sqlite3_stmt *statementHandle;
938 resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr);
940 if (resultCode != 0){
941 addResult.addEventResult = CDSENTRY_FAILED;
945 resultCode = sqlite3_bind_int(findHandle, 1, calendarID);
947 if (resultCode != 0){
948 addResult.addEventResult = CDSENTRY_FAILED;
952 resultCode = sqlite3_step(findHandle);
954 if (resultCode == SQLITE_ROW){
956 } else if (resultCode == SQLITE_DONE) {
957 addResult.addEventResult = CDSENTRY_NOCALENDAR;
960 addResult.addEventResult = CDSENTRY_FAILED;
964 // Get the required values from the event object.
966 int eventStartYear = 0;
967 int eventStartMonth = 0;
968 int eventStartDay = 0;
969 int eventStartHour = 0;
970 int eventStartMinute = 0;
971 int eventStartSecond = 0;
972 int eventStartDuration = 0;
973 std::string eventString = "";
977 if (eventData.DateTimeStartData.size() < 16){
979 addResult.addEventResult = CDSENTRY_INVALIDFILE;
984 eventString = eventData.DateTimeStartData.substr(0,4);
986 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
988 eventStartYear = atoi(eventString.c_str());
992 addResult.addEventResult = CDSENTRY_INVALIDFILE;
997 eventString = eventData.DateTimeStartData.substr(4,2);
999 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1001 eventStartMonth = atoi(eventString.c_str());
1005 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1010 eventString = eventData.DateTimeStartData.substr(6,2);
1012 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1014 eventStartDay = atoi(eventString.c_str());
1018 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1023 eventString = eventData.DateTimeStartData.substr(9,2);
1025 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1027 eventStartHour = atoi(eventString.c_str());
1031 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1036 eventString = eventData.DateTimeStartData.substr(11,2);
1038 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1040 eventStartMinute = atoi(eventString.c_str());
1044 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1049 eventString = eventData.DateTimeStartData.substr(13,2);
1051 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1053 eventStartSecond = atoi(eventString.c_str());
1057 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1062 //eventYear = eventStartDate.substr(0, 4);
1066 int eventEndYear = 0;
1067 int eventEndMonth = 0;
1068 int eventEndDay = 0;
1069 int eventEndHour = 0;
1070 int eventEndMinute = 0;
1071 int eventEndSecond = 0;
1072 int eventEndDuration = 0;
1074 if (eventData.DateTimeEndData != ""){
1076 if (eventData.DateTimeEndData.size() < 16){
1078 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1083 eventString = eventData.DateTimeEndData.substr(0,4);
1085 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1087 eventEndYear = atoi(eventString.c_str());
1091 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1096 eventString = eventData.DateTimeEndData.substr(4,2);
1098 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1100 eventEndMonth = atoi(eventString.c_str());
1104 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1109 eventString = eventData.DateTimeEndData.substr(6,2);
1111 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1113 eventEndDay = atoi(eventString.c_str());
1117 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1122 eventString = eventData.DateTimeEndData.substr(9,2);
1124 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1126 eventEndHour = atoi(eventString.c_str());
1130 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1135 eventString = eventData.DateTimeEndData.substr(11,2);
1137 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1139 eventEndMinute = atoi(eventString.c_str());
1143 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1148 eventString = eventData.DateTimeEndData.substr(13,2);
1150 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1152 eventEndSecond = atoi(eventString.c_str());
1156 addResult.addEventResult = CDSENTRY_INVALIDFILE;
1163 eventString = eventData.DurationData;
1165 // Process the duration data.
1167 int eventDurationWeeks = 0;
1168 int eventDurationDays = 0;
1169 int eventDurationHours = 0;
1170 int eventDurationMinutes = 0;
1171 int eventDurationSeconds = 0;
1173 // Get the duration (if DTEND hasn't been specified).
1175 if (eventData.DurationData.size() > 0){
1177 bool FoundP = false;
1178 bool FoundW = false;
1179 bool DateTimeMode = false;
1181 std::string::iterator eventDataChar = eventData.DurationData.begin();
1182 std::string currentValue = "";
1184 if (*eventDataChar != 'P'){
1186 eventDataChar = eventData.DurationData.end();
1190 for(eventDataChar; eventDataChar != eventData.DurationData.end(); eventDataChar++){
1192 // Check if value is a digit.
1194 if (isdigit(*eventDataChar)){
1196 currentValue += *eventDataChar;
1200 // Check that the value matches one of the letters.
1202 if (*eventDataChar == 'W' && DateTimeMode == false){
1204 eventDurationWeeks = atoi(currentValue.c_str());
1206 } else if (*eventDataChar == 'D' && DateTimeMode == false){
1208 eventDurationDays = atoi(currentValue.c_str());
1210 } else if (*eventDataChar == 'T' && DateTimeMode == false){
1212 DateTimeMode = true;
1214 } else if (*eventDataChar == 'H'){
1216 eventDurationHours = atoi(currentValue.c_str());
1218 } else if (*eventDataChar == 'M'){
1220 eventDurationMinutes = atoi(currentValue.c_str());
1222 } else if (*eventDataChar == 'S'){
1224 eventDurationSeconds = atoi(currentValue.c_str());
1228 // Reset the current value.
1238 // Add the calendar entry.
1240 std::string sqlParameter = "INSERT INTO calendarentries (calendarid, entryname, entrydescription,"
1241 " entrystartyear, entrystartmonth, entrystartday, entrystarthour, entrystartminute, entrystartsecond,"
1242 " entryendyear, entryendmonth, entryendday, entryendhour, entryendminute, entryendsecond, "
1243 " entrydurationweek, entrydurationday, entrydurationhour, entrydurationminute, entrydurationsecond, "
1245 " VALUES ((?1), (?2), (?3), (?4), (?5), (?6), (?7), (?8), (?9), (?10), "
1246 " (?11), (?12), (?13), (?14), (?15), (?16), (?17), (?18), (?19), (?20), (?21))";
1248 resultCode = sqlite3_prepare_v2(db, sqlParameter.c_str(), -1, &statementHandle, nullptr);
1250 resultCode = sqlite3_bind_int(statementHandle, 1, calendarID);
1252 if (resultCode != 0){
1253 addResult.addEventResult = CDSENTRY_FAILED;
1257 // Process Entry Name.
1259 resultCode = sqlite3_bind_text(statementHandle, 2, eventData.SummaryData.c_str(), -1, SQLITE_STATIC);
1261 if (resultCode != 0){
1262 addResult.addEventResult = CDSENTRY_FAILED;
1266 // Process Entry Description.
1268 string eventDescription;
1271 eventDescription = eventData.DescriptionList.at(0);
1274 catch (out_of_range &err){
1275 eventDescription = "";
1278 resultCode = sqlite3_bind_text(statementHandle, 3, eventDescription.c_str(), -1, SQLITE_STATIC);
1280 if (resultCode != 0){
1281 addResult.addEventResult = CDSENTRY_FAILED;
1285 // Process Entry Start Date information.
1287 resultCode = sqlite3_bind_int(statementHandle, 4, eventStartYear);
1289 if (resultCode != 0){
1290 addResult.addEventResult = CDSENTRY_FAILED;
1294 resultCode = sqlite3_bind_int(statementHandle, 5, eventStartMonth);
1296 if (resultCode != 0){
1297 addResult.addEventResult = CDSENTRY_FAILED;
1301 resultCode = sqlite3_bind_int(statementHandle, 6, eventStartDay);
1303 if (resultCode != 0){
1304 addResult.addEventResult = CDSENTRY_FAILED;
1308 resultCode = sqlite3_bind_int(statementHandle, 7, eventStartHour);
1310 if (resultCode != 0){
1311 addResult.addEventResult = CDSENTRY_FAILED;
1315 resultCode = sqlite3_bind_int(statementHandle, 8, eventStartMinute);
1317 if (resultCode != 0){
1318 addResult.addEventResult = CDSENTRY_FAILED;
1322 resultCode = sqlite3_bind_int(statementHandle, 9, eventStartSecond);
1324 if (resultCode != 0){
1325 addResult.addEventResult = CDSENTRY_FAILED;
1329 // Process Entry Start End information.
1331 resultCode = sqlite3_bind_int(statementHandle, 10, eventEndYear);
1333 if (resultCode != 0){
1334 addResult.addEventResult = CDSENTRY_FAILED;
1338 resultCode = sqlite3_bind_int(statementHandle, 11, eventEndMonth);
1340 if (resultCode != 0){
1341 addResult.addEventResult = CDSENTRY_FAILED;
1345 resultCode = sqlite3_bind_int(statementHandle, 12, eventEndDay);
1347 if (resultCode != 0){
1348 addResult.addEventResult = CDSENTRY_FAILED;
1352 resultCode = sqlite3_bind_int(statementHandle, 13, eventEndHour);
1354 if (resultCode != 0){
1355 addResult.addEventResult = CDSENTRY_FAILED;
1359 resultCode = sqlite3_bind_int(statementHandle, 14, eventEndMinute);
1361 if (resultCode != 0){
1362 addResult.addEventResult = CDSENTRY_FAILED;
1366 resultCode = sqlite3_bind_int(statementHandle, 15, eventEndSecond);
1368 if (resultCode != 0){
1369 addResult.addEventResult = CDSENTRY_FAILED;
1373 resultCode = sqlite3_bind_int(statementHandle, 16, eventDurationWeeks);
1375 if (resultCode != 0){
1376 addResult.addEventResult = CDSENTRY_FAILED;
1380 resultCode = sqlite3_bind_int(statementHandle, 17, eventDurationDays);
1382 if (resultCode != 0){
1383 addResult.addEventResult = CDSENTRY_FAILED;
1387 resultCode = sqlite3_bind_int(statementHandle, 18, eventDurationHours);
1389 if (resultCode != 0){
1390 addResult.addEventResult = CDSENTRY_FAILED;
1394 resultCode = sqlite3_bind_int(statementHandle, 19, eventDurationMinutes);
1396 if (resultCode != 0){
1397 addResult.addEventResult = CDSENTRY_FAILED;
1401 resultCode = sqlite3_bind_int(statementHandle, 20, eventDurationSeconds);
1403 if (resultCode != 0){
1404 addResult.addEventResult = CDSENTRY_FAILED;
1408 resultCode = sqlite3_bind_text(statementHandle, 21, filename.c_str(), -1, SQLITE_STATIC);
1410 if (resultCode != 0){
1411 addResult.addEventResult = CDSENTRY_FAILED;
1415 resultCode = sqlite3_step(statementHandle);
1417 if (resultCode != SQLITE_DONE){
1418 addResult.addEventResult = CDSENTRY_FAILED;
1422 addResult.calendarEntryID = sqlite3_last_insert_rowid(db);
1423 addResult.addEventResult = CDSENTRY_OK;
1425 // Update the checksum.
1427 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
1433 CDSEditEntryResult CalendarDataStorage::UpdateEvent(int eventID, std::string filename)
1436 CDSEditEntryResult editResult;
1437 editResult.editEventResult = CDSENTRY_UNITTESTFAIL;
1439 // Load the event file.
1441 CalendarEventObject eventData;
1442 CalendarObjectLoadResult eventLoadResult = eventData.LoadFile(filename);
1444 // Check the result of the event file load.
1446 switch (eventLoadResult){
1448 case CALENDAROBJECTLOAD_OK:
1450 case CALENDAROBJECTLOAD_MISSING:
1451 editResult.editEventResult = CDSENTRY_MISSINGFILE;
1453 case CALENDAROBJECTLOAD_INVALIDFORMAT:
1454 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1456 case CALENDAROBJECTLOAD_CANNOTOPEN:
1457 editResult.editEventResult = CDSENTRY_CANNOTOPENFILE;
1462 // Check if event exists first.
1466 sqlite3_stmt *findHandle;
1467 sqlite3_stmt *statementHandle;
1469 resultCode = sqlite3_prepare_v2(db, "SELECT id from calendarentries WHERE id=(?1);", -1, &findHandle, nullptr);
1471 if (resultCode != 0){
1472 editResult.editEventResult = CDSENTRY_FAILED;
1476 resultCode = sqlite3_bind_int(findHandle, 1, eventID);
1478 if (resultCode != 0){
1479 editResult.editEventResult = CDSENTRY_FAILED;
1483 resultCode = sqlite3_step(findHandle);
1485 if (resultCode == SQLITE_ROW){
1487 } else if (resultCode == SQLITE_DONE) {
1488 editResult.editEventResult = CDSENTRY_NOENTRY;
1491 editResult.editEventResult = CDSENTRY_FAILED;
1495 // Get the required values from the event object.
1497 int eventStartYear = 0;
1498 int eventStartMonth = 0;
1499 int eventStartDay = 0;
1500 int eventStartHour = 0;
1501 int eventStartMinute = 0;
1502 int eventStartSecond = 0;
1503 int eventStartDuration = 0;
1504 std::string eventString = "";
1508 if (eventData.DateTimeStartData.size() < 16){
1510 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1515 eventString = eventData.DateTimeStartData.substr(0,4);
1517 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1519 eventStartYear = atoi(eventString.c_str());
1523 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1528 eventString = eventData.DateTimeStartData.substr(4,2);
1530 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1532 eventStartMonth = atoi(eventString.c_str());
1536 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1541 eventString = eventData.DateTimeStartData.substr(6,2);
1543 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1545 eventStartDay = atoi(eventString.c_str());
1549 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1554 eventString = eventData.DateTimeStartData.substr(9,2);
1556 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1558 eventStartHour = atoi(eventString.c_str());
1562 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1567 eventString = eventData.DateTimeStartData.substr(11,2);
1569 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1571 eventStartMinute = atoi(eventString.c_str());
1575 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1580 eventString = eventData.DateTimeStartData.substr(13,2);
1582 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1584 eventStartSecond = atoi(eventString.c_str());
1588 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1593 //eventYear = eventStartDate.substr(0, 4);
1597 int eventEndYear = 0;
1598 int eventEndMonth = 0;
1599 int eventEndDay = 0;
1600 int eventEndHour = 0;
1601 int eventEndMinute = 0;
1602 int eventEndSecond = 0;
1603 int eventEndDuration = 0;
1605 if (eventData.DateTimeEndData != ""){
1607 if (eventData.DateTimeEndData.size() < 16){
1609 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1614 eventString = eventData.DateTimeEndData.substr(0,4);
1616 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1618 eventEndYear = atoi(eventString.c_str());
1622 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1627 eventString = eventData.DateTimeEndData.substr(4,2);
1629 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1631 eventEndMonth = atoi(eventString.c_str());
1635 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1640 eventString = eventData.DateTimeEndData.substr(6,2);
1642 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1644 eventEndDay = atoi(eventString.c_str());
1648 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1653 eventString = eventData.DateTimeEndData.substr(9,2);
1655 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1657 eventEndHour = atoi(eventString.c_str());
1661 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1666 eventString = eventData.DateTimeEndData.substr(11,2);
1668 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1670 eventEndMinute = atoi(eventString.c_str());
1674 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1679 eventString = eventData.DateTimeEndData.substr(13,2);
1681 if (all_of(eventString.begin(), eventString.end(), ::isdigit)){
1683 eventEndSecond = atoi(eventString.c_str());
1687 editResult.editEventResult = CDSENTRY_INVALIDFILE;
1694 eventString = eventData.DurationData;
1696 // Process the duration data.
1698 int eventDurationWeeks = 0;
1699 int eventDurationDays = 0;
1700 int eventDurationHours = 0;
1701 int eventDurationMinutes = 0;
1702 int eventDurationSeconds = 0;
1704 // Get the duration (if DTEND hasn't been specified).
1706 if (eventData.DurationData.size() > 0){
1708 bool FoundP = false;
1709 bool FoundW = false;
1710 bool DateTimeMode = false;
1712 std::string::iterator eventDataChar = eventData.DurationData.begin();
1713 std::string currentValue = "";
1715 if (*eventDataChar != 'P'){
1717 eventDataChar = eventData.DurationData.end();
1721 for(eventDataChar; eventDataChar != eventData.DurationData.end(); eventDataChar++){
1723 // Check if value is a digit.
1725 if (isdigit(*eventDataChar)){
1727 currentValue += *eventDataChar;
1731 // Check that the value matches one of the letters.
1733 if (*eventDataChar == 'W' && DateTimeMode == false){
1735 eventDurationWeeks = atoi(currentValue.c_str());
1737 } else if (*eventDataChar == 'D' && DateTimeMode == false){
1739 eventDurationDays = atoi(currentValue.c_str());
1741 } else if (*eventDataChar == 'T' && DateTimeMode == false){
1743 DateTimeMode = true;
1745 } else if (*eventDataChar == 'H'){
1747 eventDurationHours = atoi(currentValue.c_str());
1749 } else if (*eventDataChar == 'M'){
1751 eventDurationMinutes = atoi(currentValue.c_str());
1753 } else if (*eventDataChar == 'S'){
1755 eventDurationSeconds = atoi(currentValue.c_str());
1759 // Reset the current value.
1769 // Add the calendar entry.
1771 std::string sqlParameter = "UPDATE calendarentries SET entryname=(?2), entrydescription=(?3),"
1772 " entrystartyear=(?4), entrystartmonth=(?5), entrystartday=(?6), entrystarthour=(?7), entrystartminute=(?8), entrystartsecond=(?9),"
1773 " entryendyear=(?10), entryendmonth=(?11), entryendday=(?12), entryendhour=(?13), entryendminute=(?14), entryendsecond=(?15), "
1774 " entrydurationweek=(?16), entrydurationday=(?17), entrydurationhour=(?18), entrydurationminute=(?19), entrydurationsecond=(?20), "
1777 resultCode = sqlite3_prepare_v2(db, sqlParameter.c_str(), -1, &statementHandle, nullptr);
1779 resultCode = sqlite3_bind_int(statementHandle, 1, eventID);
1781 if (resultCode != 0){
1782 editResult.editEventResult = CDSENTRY_FAILED;
1786 // Process Entry Name.
1788 resultCode = sqlite3_bind_text(statementHandle, 2, eventData.SummaryData.c_str(), -1, SQLITE_STATIC);
1790 if (resultCode != 0){
1791 editResult.editEventResult = CDSENTRY_FAILED;
1795 // Process Entry Description.
1797 string eventDescription;
1800 eventDescription = eventData.DescriptionList.at(0);
1803 catch (out_of_range &err){
1804 eventDescription = "";
1807 resultCode = sqlite3_bind_text(statementHandle, 3, eventDescription.c_str(), -1, SQLITE_STATIC);
1809 if (resultCode != 0){
1810 editResult.editEventResult = CDSENTRY_FAILED;
1814 // Process Entry Start Date information.
1816 resultCode = sqlite3_bind_int(statementHandle, 4, eventStartYear);
1818 if (resultCode != 0){
1819 editResult.editEventResult = CDSENTRY_FAILED;
1823 resultCode = sqlite3_bind_int(statementHandle, 5, eventStartMonth);
1825 if (resultCode != 0){
1826 editResult.editEventResult = CDSENTRY_FAILED;
1830 resultCode = sqlite3_bind_int(statementHandle, 6, eventStartDay);
1832 if (resultCode != 0){
1833 editResult.editEventResult = CDSENTRY_FAILED;
1837 resultCode = sqlite3_bind_int(statementHandle, 7, eventStartHour);
1839 if (resultCode != 0){
1840 editResult.editEventResult = CDSENTRY_FAILED;
1844 resultCode = sqlite3_bind_int(statementHandle, 8, eventStartMinute);
1846 if (resultCode != 0){
1847 editResult.editEventResult = CDSENTRY_FAILED;
1851 resultCode = sqlite3_bind_int(statementHandle, 9, eventStartSecond);
1853 if (resultCode != 0){
1854 editResult.editEventResult = CDSENTRY_FAILED;
1858 // Process Entry Start End information.
1860 resultCode = sqlite3_bind_int(statementHandle, 10, eventEndYear);
1862 if (resultCode != 0){
1863 editResult.editEventResult = CDSENTRY_FAILED;
1867 resultCode = sqlite3_bind_int(statementHandle, 11, eventEndMonth);
1869 if (resultCode != 0){
1870 editResult.editEventResult = CDSENTRY_FAILED;
1874 resultCode = sqlite3_bind_int(statementHandle, 12, eventEndDay);
1876 if (resultCode != 0){
1877 editResult.editEventResult = CDSENTRY_FAILED;
1881 resultCode = sqlite3_bind_int(statementHandle, 13, eventEndHour);
1883 if (resultCode != 0){
1884 editResult.editEventResult = CDSENTRY_FAILED;
1888 resultCode = sqlite3_bind_int(statementHandle, 14, eventEndMinute);
1890 if (resultCode != 0){
1891 editResult.editEventResult = CDSENTRY_FAILED;
1895 resultCode = sqlite3_bind_int(statementHandle, 15, eventEndSecond);
1897 if (resultCode != 0){
1898 editResult.editEventResult = CDSENTRY_FAILED;
1902 resultCode = sqlite3_bind_int(statementHandle, 16, eventDurationWeeks);
1904 if (resultCode != 0){
1905 editResult.editEventResult = CDSENTRY_FAILED;
1909 resultCode = sqlite3_bind_int(statementHandle, 17, eventDurationDays);
1911 if (resultCode != 0){
1912 editResult.editEventResult = CDSENTRY_FAILED;
1916 resultCode = sqlite3_bind_int(statementHandle, 18, eventDurationHours);
1918 if (resultCode != 0){
1919 editResult.editEventResult = CDSENTRY_FAILED;
1923 resultCode = sqlite3_bind_int(statementHandle, 19, eventDurationMinutes);
1925 if (resultCode != 0){
1926 editResult.editEventResult = CDSENTRY_FAILED;
1930 resultCode = sqlite3_bind_int(statementHandle, 20, eventDurationSeconds);
1932 if (resultCode != 0){
1933 editResult.editEventResult = CDSENTRY_FAILED;
1937 resultCode = sqlite3_step(statementHandle);
1939 if (resultCode != SQLITE_DONE){
1940 editResult.editEventResult = CDSENTRY_FAILED;
1944 editResult.calendarEntryID = sqlite3_last_insert_rowid(db);
1945 editResult.editEventResult = CDSENTRY_OK;
1947 // Update the checksum.
1949 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
1955 CDSGetCalendarEntryInfo CalendarDataStorage::GetEvent(int calendarEntryID)
1958 CDSGetCalendarEntryInfo entryResult;
1960 // Check if the calendar entry exists.
1964 sqlite3_stmt *findHandle;
1965 sqlite3_stmt *statementHandle;
1967 resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE id=(?1);", -1, &findHandle, nullptr);
1969 if (resultCode != 0){
1970 entryResult.getEventResult = CDSENTRY_FAILED;
1974 resultCode = sqlite3_bind_int(findHandle, 1, calendarEntryID);
1976 if (resultCode != 0){
1977 entryResult.getEventResult = CDSENTRY_FAILED;
1981 resultCode = sqlite3_step(findHandle);
1983 if (resultCode == SQLITE_ROW){
1985 } else if (resultCode == SQLITE_DONE) {
1986 entryResult.getEventResult = CDSENTRY_NOENTRY;
1989 entryResult.getEventResult = CDSENTRY_FAILED;
1993 // Get the calendar entry data.
1995 std::string sqlParameter = "SELECT entryname, entrydescription,"
1996 " entrystartyear, entrystartmonth, entrystartday, entrystarthour, entrystartminute, entrystartsecond,"
1997 " entryendyear, entryendmonth, entryendday, entryendhour, entryendminute, entryendsecond, "
1998 " entrydurationweek, entrydurationday, entrydurationhour, entrydurationminute, entrydurationsecond, "
1999 " calendarid, id, filename"
2000 " FROM calendarentries WHERE id=(?1)";
2002 resultCode = sqlite3_prepare_v2(db, sqlParameter.c_str(), -1, &statementHandle, nullptr);
2004 if (resultCode != 0){
2005 entryResult.getEventResult = CDSENTRY_FAILED;
2009 resultCode = sqlite3_bind_int(statementHandle, 1, calendarEntryID);
2011 if (resultCode != 0){
2012 entryResult.getEventResult = CDSENTRY_FAILED;
2016 resultCode = sqlite3_step(statementHandle);
2018 if (resultCode == SQLITE_ROW){
2020 // Get the calendar entry name,
2022 stringstream entryStream;
2024 entryStream << sqlite3_column_text(statementHandle, 0);
2025 entryResult.entryName = entryStream.str();
2027 entryStream.str("");
2029 // Get the calendar entry description.
2031 entryStream << sqlite3_column_text(statementHandle, 1);
2032 entryResult.entryDescription = entryStream.str();
2034 entryStream.str("");
2036 // Get the calendar entry filename.
2038 entryStream << sqlite3_column_text(statementHandle, 21);
2039 entryResult.entryFilename = entryStream.str();
2041 entryStream.str("");
2043 entryResult.entryStartYear = sqlite3_column_int(statementHandle, 2);
2044 entryResult.entryStartMonth = sqlite3_column_int(statementHandle, 3);
2045 entryResult.entryStartDay = sqlite3_column_int(statementHandle, 4);
2046 entryResult.entryStartHour = sqlite3_column_int(statementHandle, 5);
2047 entryResult.entryStartMinute = sqlite3_column_int(statementHandle, 6);
2048 entryResult.entryStartSecond = sqlite3_column_int(statementHandle, 7);
2049 entryResult.entryEndYear = sqlite3_column_int(statementHandle, 8);
2050 entryResult.entryEndMonth = sqlite3_column_int(statementHandle, 9);
2051 entryResult.entryEndDay = sqlite3_column_int(statementHandle, 10);
2052 entryResult.entryEndHour = sqlite3_column_int(statementHandle, 11);
2053 entryResult.entryEndMinute = sqlite3_column_int(statementHandle, 12);
2054 entryResult.entryEndSecond = sqlite3_column_int(statementHandle, 13);
2055 entryResult.entryDurationWeeks = sqlite3_column_int(statementHandle, 14);
2056 entryResult.entryDurationDays = sqlite3_column_int(statementHandle, 15);
2057 entryResult.entryDurationHours = sqlite3_column_int(statementHandle, 16);
2058 entryResult.entryDurationMinutes = sqlite3_column_int(statementHandle, 17);
2059 entryResult.entryDurationSeconds = sqlite3_column_int(statementHandle, 18);
2060 entryResult.calendarID = sqlite3_column_int(statementHandle, 19);
2061 entryResult.calendarEntryID = sqlite3_column_int(statementHandle, 20);
2063 } else if (resultCode == SQLITE_DONE) {
2064 entryResult.getEventResult = CDSENTRY_NOCALENDAR;
2067 entryResult.getEventResult = CDSENTRY_FAILED;
2071 entryResult.getEventResult = CDSENTRY_OK;
2077 CDSEntryResult CalendarDataStorage::DeleteEvent(int calendarEntryID)
2080 CDSEntryResult deleteResult = CDSENTRY_UNITTESTFAIL;
2082 // Check if the calendar entry exists.
2086 sqlite3_stmt *findHandle;
2087 sqlite3_stmt *statementHandle;
2089 resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE id=(?1);", -1, &findHandle, nullptr);
2091 if (resultCode != 0){
2092 return CDSENTRY_FAILED;
2095 resultCode = sqlite3_bind_int(findHandle, 1, calendarEntryID);
2097 if (resultCode != 0){
2098 return CDSENTRY_FAILED;
2101 resultCode = sqlite3_step(findHandle);
2103 if (resultCode == SQLITE_ROW){
2105 } else if (resultCode == SQLITE_DONE) {
2106 return CDSENTRY_NOENTRY;
2108 return CDSENTRY_FAILED;
2111 // Delete the account.
2113 resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendarentries WHERE id=(?1);", -1, &statementHandle, nullptr);
2115 if (resultCode != 0){
2116 return CDSENTRY_FAILED;
2119 resultCode = sqlite3_bind_int(statementHandle, 1, calendarEntryID);
2121 if (resultCode != 0){
2122 return CDSENTRY_FAILED;
2125 resultCode = sqlite3_step(statementHandle);
2127 if (resultCode == SQLITE_DONE){
2128 deleteResult = CDSENTRY_OK;
2130 return CDSENTRY_FAILED;
2133 // Update the checksum.
2135 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
2137 return deleteResult;
2141 CDSEntryList CalendarDataStorage::GetEventList(int calendarID){
2143 CDSEntryList entryList;
2144 entryList.getEventListResult = CDSENTRY_UNITTESTFAIL;
2146 // Check if calendar exists first.
2150 sqlite3_stmt *findHandle;
2151 sqlite3_stmt *calendarHandle;
2153 resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr);
2155 if (resultCode != 0){
2156 entryList.getEventListResult = CDSENTRY_FAILED;
2160 resultCode = sqlite3_bind_int(findHandle, 1, calendarID);
2162 if (resultCode != 0){
2163 entryList.getEventListResult = CDSENTRY_FAILED;
2167 resultCode = sqlite3_step(findHandle);
2169 if (resultCode == SQLITE_ROW){
2171 } else if (resultCode == SQLITE_DONE) {
2172 entryList.getEventListResult = CDSENTRY_NOCALENDAR;
2175 entryList.getEventListResult = CDSENTRY_FAILED;
2179 // Get the list of entry IDs.
2181 resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE calendarid=(?1);", -1, &calendarHandle, nullptr);
2183 if (resultCode != 0){
2184 entryList.getEventListResult = CDSENTRY_FAILED;
2188 resultCode = sqlite3_bind_int(calendarHandle, 1, calendarID);
2190 if (resultCode != 0){
2191 entryList.getEventListResult = CDSENTRY_FAILED;
2195 resultCode = sqlite3_step(calendarHandle);
2197 if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){
2199 entryList.getEventListResult = CDSENTRY_FAILED;
2203 while (resultCode == SQLITE_ROW){
2205 int calendarID = sqlite3_column_int(calendarHandle, 0);
2207 entryList.entryList.push_back(calendarID);
2209 resultCode = sqlite3_step(calendarHandle);
2213 entryList.getEventListResult = CDSENTRY_OK;
2219 CDSEntryList CalendarDataStorage::GetEventListByDate(int calendarYear, int calendarMonth, int calendarDay){
2221 CDSEntryList entryList;
2222 entryList.getEventListResult = CDSENTRY_UNITTESTFAIL;
2224 // Check if calendar exists first.
2228 sqlite3_stmt *calendarHandle;
2230 // Get the list of entry IDs.
2232 resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE entrystartyear=(?1) AND entrystartmonth=(?2) AND entrystartday=(?3);", -1, &calendarHandle, nullptr);
2234 if (resultCode != 0){
2235 entryList.getEventListResult = CDSENTRY_FAILED;
2239 resultCode = sqlite3_bind_int(calendarHandle, 1, calendarYear);
2241 if (resultCode != 0){
2242 entryList.getEventListResult = CDSENTRY_FAILED;
2246 resultCode = sqlite3_bind_int(calendarHandle, 2, calendarMonth);
2248 if (resultCode != 0){
2249 entryList.getEventListResult = CDSENTRY_FAILED;
2253 resultCode = sqlite3_bind_int(calendarHandle, 3, calendarDay);
2255 if (resultCode != 0){
2256 entryList.getEventListResult = CDSENTRY_FAILED;
2260 resultCode = sqlite3_step(calendarHandle);
2262 if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){
2264 entryList.getEventListResult = CDSENTRY_FAILED;
2268 while (resultCode == SQLITE_ROW){
2270 int calendarID = sqlite3_column_int(calendarHandle, 0);
2272 entryList.entryList.push_back(calendarID);
2274 resultCode = sqlite3_step(calendarHandle);
2278 entryList.getEventListResult = CDSENTRY_OK;
2284 CDSCalendarList CalendarDataStorage::GetCalendarList(int accountID){
2286 CDSCalendarList calendarList;
2287 calendarList.getCalendarListResult = CDSCALENDAR_UNITTESTFAIL;
2289 // Check if calendar exists first.
2293 sqlite3_stmt *findHandle;
2294 sqlite3_stmt *calendarHandle;
2296 resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr);
2298 if (resultCode != 0){
2299 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2300 return calendarList;
2303 resultCode = sqlite3_bind_int(findHandle, 1, accountID);
2305 if (resultCode != 0){
2306 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2307 return calendarList;
2310 resultCode = sqlite3_step(findHandle);
2312 if (resultCode == SQLITE_ROW){
2314 } else if (resultCode == SQLITE_DONE) {
2315 calendarList.getCalendarListResult = CDSCALENDAR_NOCALENDAR;
2316 return calendarList;
2318 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2319 return calendarList;
2322 // Get the list of entry IDs.
2324 resultCode = sqlite3_prepare_v2(db, "SELECT id, calendarid FROM calendars WHERE accountid=(?1);", -1, &calendarHandle, nullptr);
2326 if (resultCode != 0){
2327 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2328 return calendarList;
2331 resultCode = sqlite3_bind_int(calendarHandle, 1, accountID);
2333 if (resultCode != 0){
2334 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2335 return calendarList;
2338 resultCode = sqlite3_step(calendarHandle);
2340 if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){
2342 calendarList.getCalendarListResult = CDSCALENDAR_FAILED;
2343 return calendarList;
2346 while (resultCode == SQLITE_ROW){
2348 int calendarID = sqlite3_column_int(calendarHandle, 0);
2350 stringstream calendarStream;
2352 calendarStream << sqlite3_column_text(calendarHandle, 1);
2354 calendarList.calendarList.push_back(calendarID);
2355 calendarList.calendarListTextID.push_back(calendarStream.str());
2357 calendarStream.str("");
2359 resultCode = sqlite3_step(calendarHandle);
2363 calendarList.getCalendarListResult = CDSCALENDAR_OK;
2365 return calendarList;
2369 CDSChecksumResult CalendarDataStorage::AddChecksum(string checksumName, string checksumValue){
2373 // Check if the checksum already exists.
2375 sqlite3_stmt *findHandle;
2376 sqlite3_stmt *checksumHandle;
2378 resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &findHandle, nullptr);
2380 if (resultCode != 0){
2381 return CDSCHECKSUM_FAILED;
2384 resultCode = sqlite3_bind_text(findHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC);
2386 if (resultCode != 0){
2387 return CDSCHECKSUM_FAILED;
2390 resultCode = sqlite3_step(findHandle);
2392 if (resultCode == SQLITE_ROW){
2393 return CDSCHECKSUM_CHECKSUMALREADYEXISTS;
2394 } else if (resultCode == SQLITE_DONE) {
2397 return CDSCHECKSUM_FAILED;
2400 // Add the checksum to the checksum table.
2402 resultCode = sqlite3_prepare_v2(db, "INSERT INTO checksums (checksumname, checksumvalue) VALUES(?1, ?2);", -1, &checksumHandle, nullptr);
2404 if (resultCode != 0){
2405 return CDSCHECKSUM_FAILED;
2408 resultCode = sqlite3_bind_text(checksumHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC);
2410 if (resultCode != 0){
2411 return CDSCHECKSUM_FAILED;
2414 resultCode = sqlite3_bind_text(checksumHandle, 2, checksumValue.c_str(), -1, SQLITE_STATIC);
2416 if (resultCode != 0){
2417 return CDSCHECKSUM_FAILED;
2420 resultCode = sqlite3_step(checksumHandle);
2422 if (resultCode != SQLITE_DONE){
2423 return CDSCHECKSUM_FAILED;
2426 return CDSCHECKSUM_OK;
2430 CDSGetChecksumResult CalendarDataStorage::GetChecksum(string checksumName){
2432 CDSGetChecksumResult getChecksumResult;
2436 // Check if the checksum already exists.
2438 sqlite3_stmt *getHandle;
2440 resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &getHandle, nullptr);
2442 if (resultCode != 0){
2443 getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED;
2444 return getChecksumResult;
2447 resultCode = sqlite3_bind_text(getHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC);
2449 if (resultCode != 0){
2450 getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED;
2451 return getChecksumResult;
2454 resultCode = sqlite3_step(getHandle);
2456 if (resultCode == SQLITE_ROW){
2457 } else if (resultCode == SQLITE_DONE) {
2458 getChecksumResult.getChecksumResult = CDSCHECKSUM_NOHASH;
2459 return getChecksumResult;
2461 getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED;
2462 return getChecksumResult;
2465 stringstream checksumStream;
2467 checksumStream << sqlite3_column_text(getHandle, 0);
2469 getChecksumResult.checksumValue = checksumStream.str();
2471 getChecksumResult.getChecksumResult = CDSCHECKSUM_OK;
2473 return getChecksumResult;
2477 CDSChecksumResult CalendarDataStorage::UpdateChecksum(std::string checksumName, std::string checksumValue){
2481 // Check if the checksum already exists.
2483 sqlite3_stmt *getHandle;
2484 sqlite3_stmt *statementHandle;
2486 resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &getHandle, nullptr);
2488 if (resultCode != 0){
2489 return CDSCHECKSUM_FAILED;
2492 resultCode = sqlite3_bind_text(getHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC);
2494 if (resultCode != 0){
2495 return CDSCHECKSUM_FAILED;
2498 resultCode = sqlite3_step(getHandle);
2500 if (resultCode == SQLITE_ROW){
2501 } else if (resultCode == SQLITE_DONE) {
2502 return CDSCHECKSUM_NOHASH;
2504 return CDSCHECKSUM_FAILED;
2507 // Update the checksum.
2509 resultCode = sqlite3_prepare_v2(db, "UPDATE checksums SET checksumvalue=(?1) WHERE checksumname=(?2);", -1, &statementHandle, nullptr);
2511 if (resultCode != 0){
2512 return CDSCHECKSUM_FAILED;
2515 resultCode = sqlite3_bind_text(statementHandle, 1, checksumValue.c_str(), -1, SQLITE_STATIC);
2517 if (resultCode != 0){
2518 return CDSCHECKSUM_FAILED;
2521 resultCode = sqlite3_bind_text(statementHandle, 2, checksumName.c_str(), -1, SQLITE_STATIC);
2523 if (resultCode != 0){
2524 return CDSCHECKSUM_FAILED;
2527 resultCode = sqlite3_step(statementHandle);
2529 if (resultCode != SQLITE_DONE){
2530 return CDSCHECKSUM_FAILED;
2533 return CDSCHECKSUM_OK;
2537 CDSCleanupResult CalendarDataStorage::Clear(){
2539 // Remove all data from the tables and reset the sequence numbers.
2542 sqlite3_stmt *statementHandle;
2544 resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendarentries", - 1, &statementHandle, nullptr);
2546 if (resultCode != 0){
2547 cout << "Fail 1" << endl;
2548 return CDSCLEANUP_FAILED;
2551 resultCode = sqlite3_step(statementHandle);
2553 if (resultCode != SQLITE_DONE){
2554 cout << "Fail 2" << endl;
2555 return CDSCLEANUP_FAILED;
2558 resultCode = sqlite3_prepare_v2(db, "DELETE FROM sqlite_sequence WHERE name='calendarentries';", -1, &statementHandle, nullptr);
2560 if (resultCode != 0){
2561 cout << "Fail 3" << endl;
2562 cout << sqlite3_errmsg(db) << endl;
2563 return CDSCLEANUP_FAILED;
2566 resultCode = sqlite3_step(statementHandle);
2568 if (resultCode != SQLITE_DONE){
2569 cout << "Fail 4" << endl;
2570 return CDSCLEANUP_FAILED;
2573 resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendars", -1, &statementHandle, nullptr);
2575 if (resultCode != 0){
2576 cout << "Fail 5" << endl;
2577 return CDSCLEANUP_FAILED;
2580 resultCode = sqlite3_step(statementHandle);
2582 if (resultCode != SQLITE_DONE){
2583 cout << "Fail 6" << endl;
2584 return CDSCLEANUP_FAILED;
2587 resultCode = sqlite3_prepare_v2(db, "DELETE FROM sqlite_sequence WHERE name='calendars';", -1, &statementHandle, nullptr);
2589 if (resultCode != 0){
2590 cout << "Fail 7" << endl;
2591 return CDSCLEANUP_FAILED;
2594 resultCode = sqlite3_step(statementHandle);
2596 if (resultCode != SQLITE_DONE){
2597 cout << "Fail 8" << endl;
2598 return CDSCLEANUP_FAILED;
2601 resultCode = sqlite3_prepare_v2(db, "DELETE FROM accounts", -1, &statementHandle, nullptr);
2603 if (resultCode != 0){
2604 cout << "Fail 9" << endl;
2605 return CDSCLEANUP_FAILED;
2608 resultCode = sqlite3_step(statementHandle);
2610 if (resultCode != SQLITE_DONE){
2611 cout << "Fail 10" << endl;
2612 return CDSCLEANUP_FAILED;
2615 resultCode = sqlite3_prepare_v2(db, "DELETE FROM sqlite_sequence WHERE name='accounts'", -1, &statementHandle, nullptr);
2617 if (resultCode != 0){
2618 cout << "Fail 11" << endl;
2619 return CDSCLEANUP_FAILED;
2622 resultCode = sqlite3_step(statementHandle);
2624 if (resultCode != SQLITE_DONE){
2625 cout << "Fail 12" << endl;
2626 return CDSCLEANUP_FAILED;
2629 // Update the checksum.
2631 UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW)));
2633 return CDSCLEANUP_OK;