#include "CalendarDataStorage.h" #define CDS_RANDOMPOW 24 #include using namespace std; static int callback(void *NotUsed, int argc, char **argv, char **azColName){ return 0; } CalendarDataStorage::CalendarDataStorage(){ // Initialise the SQLite database. sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nullptr); SetupTables(); } CalendarDataStorage::~CalendarDataStorage(){ // Destory the SQLite database. sqlite3_close(db); } void CalendarDataStorage::SetupTables(){ // Setup the tables for the Calendar Data Storage. char *setupTablesErrMsg = nullptr; int resultCode; // Setup the accounts table. const char *accountsTableString; accountsTableString = "CREATE TABLE accounts(id INTEGER PRIMARY KEY " ", name TEXT" ");"; resultCode = sqlite3_exec(db, accountsTableString, callback, nullptr, &setupTablesErrMsg); if (resultCode != 0){ DataStorageInitOK = false; return; } // Setup the calendars table. const char *calendarTableString; calendarTableString = "CREATE TABLE calendars(id INTEGER PRIMARY KEY " ", accountid INTEGER" ", name TEXT" ", calendarid TEXT" ", colour TEXT" ");"; resultCode = sqlite3_exec(db, calendarTableString, callback, nullptr, &setupTablesErrMsg); if (resultCode != 0){ DataStorageInitOK = false; return; } // Setup the calendar entries table. const char *calendarentriesTableString; calendarentriesTableString = "CREATE TABLE calendarentries(id INTEGER PRIMARY KEY " ", calendarid INTEGER" ", entryname TEXT" ", entrydescription TEXT" ", entrystartyear INTEGER" ", entrystartmonth INTEGER" ", entrystartday INTEGER" ", entrystarthour INTEGER" ", entrystartminute INTEGER" ", entrystartsecond INTEGER" ", entryendyear INTEGER" ", entryendmonth INTEGER" ", entryendday INTEGER" ", entryendhour INTEGER" ", entryendminute INTEGER" ", entryendsecond INTEGER" ", entrydurationweek INTEGER" ", entrydurationday INTEGER" ", entrydurationhour INTEGER" ", entrydurationminute INTEGER" ", entrydurationsecond INTEGER" ");"; resultCode = sqlite3_exec(db, calendarentriesTableString, callback, nullptr, &setupTablesErrMsg); if (resultCode != 0){ DataStorageInitOK = false; return; } // Setup the checksums table. const char *checksumsTableString; checksumsTableString = "CREATE TABLE checksums(checksumname TEXT PRIMARY KEY " ", checksumvalue TEXT);"; resultCode = sqlite3_exec(db, checksumsTableString, callback, nullptr, &setupTablesErrMsg); if (resultCode != 0){ DataStorageInitOK = false; return; } // Setup internal checksums. CDSChecksumResult addChecksum = AddChecksum("internal_updatedata", ""); if (addChecksum != CDSCHECKSUM_OK){ DataStorageInitOK = false; return; } DataStorageInitOK = true; } bool CalendarDataStorage::DidInitOK() { return DataStorageInitOK; } CDSAccountResult CalendarDataStorage::AddAccount(string accountName) { CDSAccountResult addResult = CDSACCOUNT_UNITTESTFAIL; int resultCode; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "INSERT INTO accounts (name) VALUES(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSACCOUNT_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); addResult = CDSACCOUNT_OK; return addResult; } CDSAccountList CalendarDataStorage::GetAccountList() { CDSAccountList accountList; // Check if calendar exists first. int resultCode = 0; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id, name from accounts;", -1, &statementHandle, nullptr); if (resultCode != 0){ accountList.getAccountListResult = CDSACCOUNT_FAILED; return accountList; } if (resultCode != 0){ accountList.getAccountListResult = CDSACCOUNT_FAILED; return accountList; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { accountList.getAccountListResult = CDSACCOUNT_NOACCOUNT; return accountList; } else { accountList.getAccountListResult = CDSACCOUNT_FAILED; return accountList; } while (resultCode == SQLITE_ROW){ CDSGetAccountInfo accountInfo; accountInfo.accountID = sqlite3_column_int(statementHandle, 0); stringstream calendarStream; calendarStream << sqlite3_column_text(statementHandle, 1); accountInfo.accountName = calendarStream.str(); accountInfo.accountInfoResult = CDSACCOUNT_OK; accountList.accountList.push_back(accountInfo); resultCode = sqlite3_step(statementHandle); } accountList.getAccountListResult = CDSACCOUNT_OK; return accountList; } CDSGetAccountInfo CalendarDataStorage::GetAccount(string accountName) { CDSGetAccountInfo accountInfo; accountInfo.accountInfoResult = CDSACCOUNT_UNITTESTFAIL; int resultCode; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT name, id FROM accounts WHERE name=(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ accountInfo.accountInfoResult = CDSACCOUNT_FAILED; return accountInfo; } resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ accountInfo.accountInfoResult = CDSACCOUNT_FAILED; return accountInfo; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_DONE){ accountInfo.accountInfoResult = CDSACCOUNT_NOACCOUNT; return accountInfo; } else if (resultCode == SQLITE_ROW){ // Get the result data. stringstream accountNameStream; accountNameStream << sqlite3_column_text(statementHandle, 0); accountInfo.accountName = accountNameStream.str(); accountInfo.accountID = sqlite3_column_int(statementHandle, 1); accountInfo.accountInfoResult = CDSACCOUNT_OK; return accountInfo; } else { accountInfo.accountInfoResult = CDSACCOUNT_FAILED; return accountInfo; } return accountInfo; } CDSAccountResult CalendarDataStorage::UpdateAccount(int accountID, string accountName) { CDSAccountResult updateResult = CDSACCOUNT_UNITTESTFAIL; int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; // Check if account exists first. resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_int(findHandle, 1, accountID); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSACCOUNT_NOACCOUNT; } else { return CDSACCOUNT_FAILED; } // Update the account. resultCode = sqlite3_prepare_v2(db, "UPDATE accounts SET name=(?1) WHERE id=(?2);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 1, accountName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 2, accountID); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSACCOUNT_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); updateResult = CDSACCOUNT_OK; return updateResult; } CDSAccountResult CalendarDataStorage::DeleteAccount(int accountID) { CDSAccountResult deleteResult = CDSACCOUNT_UNITTESTFAIL; // Check if account exists first. sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; sqlite3_stmt *calendarHandle; int resultCode; resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_int(findHandle, 1, accountID); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSACCOUNT_NOACCOUNT; } else { return CDSACCOUNT_FAILED; } // Delete the account. resultCode = sqlite3_prepare_v2(db, "DELETE FROM accounts WHERE id=(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 1, accountID); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_DONE){ //deleteResult = CDSACCOUNT_OK; } else { return CDSACCOUNT_FAILED; } // Get the calendar IDs and delete each calendar (and associated entries). resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendars WHERE accountid=(?1);", -1, &calendarHandle, nullptr); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_bind_int(calendarHandle, 1, accountID); if (resultCode != 0){ return CDSACCOUNT_FAILED; } resultCode = sqlite3_step(calendarHandle); if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){ deleteResult = CDSACCOUNT_OK; } else { return CDSACCOUNT_FAILED; } while (resultCode == SQLITE_ROW){ int calendarDeleteID = sqlite3_column_int(calendarHandle, 0); DeleteCalendar(calendarDeleteID); resultCode = sqlite3_step(calendarHandle); } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); deleteResult = CDSACCOUNT_OK; return deleteResult; } CDSCalendarResult CalendarDataStorage::AddCalendar(int accountID, string calendarName, string calendarID, Colour calendarColour) { CDSCalendarResult addResult = CDSCALENDAR_UNITTESTFAIL; int resultCode; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "INSERT INTO calendars (name, calendarid, accountid, colour) VALUES(?1, ?2, ?3, ?4);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 1, calendarName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 2, calendarID.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 3, accountID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 4, ((string)calendarColour).c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSCALENDAR_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); addResult = CDSCALENDAR_OK; return addResult; } CDSGetCalendarInfo CalendarDataStorage::GetCalendar(std::string accountName, std::string calendarTextID) { CDSGetAccountInfo accountResult; CDSGetCalendarInfo calendarResult; sqlite3_stmt *statementHandle; int resultCode; // Check if the account exists. accountResult = GetAccount(accountName); switch (accountResult.accountInfoResult){ case CDSACCOUNT_OK: calendarResult.accountName = accountResult.accountName; calendarResult.accountInfoResult = CDSACCOUNT_OK; break; case CDSACCOUNT_FAILED: calendarResult.accountInfoResult = CDSACCOUNT_FAILED; calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; case CDSACCOUNT_NOACCOUNT: calendarResult.accountInfoResult = CDSACCOUNT_NOACCOUNT; calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR; return calendarResult; } // Check if the calendar exists. resultCode = sqlite3_prepare_v2(db, "SELECT id, accountid, name, calendarid, colour FROM calendars WHERE accountid=(?1) AND calendarid=(?2);", -1, &statementHandle, nullptr); if (resultCode != 0){ calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } resultCode = sqlite3_bind_int(statementHandle, 1, accountResult.accountID); if (resultCode != 0){ calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } resultCode = sqlite3_bind_text(statementHandle, 2, calendarTextID.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_DONE){ calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR; return calendarResult; } else if (resultCode == SQLITE_ROW){ // Get the calendar name. stringstream calendarStream; calendarStream << sqlite3_column_text(statementHandle, 2); calendarResult.calendarName = calendarStream.str(); calendarStream.str(""); calendarStream << sqlite3_column_text(statementHandle, 3); calendarResult.calendarTextID = calendarStream.str(); calendarStream.str(""); calendarStream << sqlite3_column_text(statementHandle, 4); calendarResult.calendarColour = calendarStream.str(); calendarResult.calendarID = sqlite3_column_int(statementHandle, 0); calendarResult.accountID = sqlite3_column_int(statementHandle, 1); calendarResult.calendarInfoResult = CDSCALENDAR_OK; return calendarResult; } else { calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } return calendarResult; } CDSGetCalendarInfo CalendarDataStorage::GetCalendar(int calendarID) { CDSGetCalendarInfo calendarResult; sqlite3_stmt *statementHandle; int resultCode; // Check if the calendar exists. resultCode = sqlite3_prepare_v2(db, "SELECT id, accountid, name, calendarid, colour FROM calendars WHERE id=(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } resultCode = sqlite3_bind_int(statementHandle, 1, calendarID); if (resultCode != 0){ calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_DONE){ calendarResult.calendarInfoResult = CDSCALENDAR_NOCALENDAR; return calendarResult; } else if (resultCode == SQLITE_ROW){ // Get the calendar data. stringstream calendarStream; calendarStream << sqlite3_column_text(statementHandle, 2); calendarResult.calendarName = calendarStream.str(); calendarStream.str(""); calendarStream << sqlite3_column_text(statementHandle, 3); calendarResult.calendarTextID = calendarStream.str(); calendarStream.str(""); calendarStream << sqlite3_column_text(statementHandle, 4); calendarResult.calendarColour = calendarStream.str(); calendarResult.calendarID = sqlite3_column_int(statementHandle, 0); calendarResult.accountID = sqlite3_column_int(statementHandle, 1); calendarResult.calendarInfoResult = CDSCALENDAR_OK; return calendarResult; } else { calendarResult.calendarInfoResult = CDSCALENDAR_FAILED; return calendarResult; } return calendarResult; } CDSCalendarResult CalendarDataStorage::UpdateCalendar(int calendarID, string calendarName) { CDSCalendarResult updateResult = CDSCALENDAR_UNITTESTFAIL; int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; // Check if calendar exists first. resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(findHandle, 1, calendarID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSCALENDAR_NOCALENDAR; } else { return CDSCALENDAR_FAILED; } // Update the account. resultCode = sqlite3_prepare_v2(db, "UPDATE calendars SET name=(?1) WHERE id=(?2);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 1, calendarName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 2, calendarID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSCALENDAR_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); updateResult = CDSCALENDAR_OK; return updateResult; } CDSCalendarResult CalendarDataStorage::DeleteCalendar(int calendarID) { CDSCalendarResult deleteResult = CDSCALENDAR_UNITTESTFAIL; // Check if account exists first. sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; sqlite3_stmt *entriesHandle; int resultCode; resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(findHandle, 1, calendarID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSCALENDAR_NOCALENDAR; } else { return CDSCALENDAR_FAILED; } // Delete the calendar. resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendars WHERE id=(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 1, calendarID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSCALENDAR_FAILED; } // Delete the calendar entries. resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendarentries WHERE calendarid=(?1);", -1, &entriesHandle, nullptr); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_bind_int(entriesHandle, 1, calendarID); if (resultCode != 0){ return CDSCALENDAR_FAILED; } resultCode = sqlite3_step(entriesHandle); if (resultCode == SQLITE_DONE){ deleteResult = CDSCALENDAR_OK; } else { return CDSCALENDAR_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); return deleteResult; } CDSAddEntryResult CalendarDataStorage::AddEvent(int calendarID, std::string filename) { CDSAddEntryResult addResult; addResult.addEventResult = CDSENTRY_UNITTESTFAIL; // Load the event file. CalendarEventObject eventData; CalendarObjectLoadResult eventLoadResult = eventData.LoadFile(filename); // Check the result of the event file load. switch (eventLoadResult){ case CALENDAROBJECTLOAD_OK: break; case CALENDAROBJECTLOAD_MISSING: addResult.addEventResult = CDSENTRY_MISSINGFILE; return addResult; case CALENDAROBJECTLOAD_INVALIDFORMAT: addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; case CALENDAROBJECTLOAD_CANNOTOPEN: addResult.addEventResult = CDSENTRY_CANNOTOPENFILE; return addResult; } // Check if calendar exists first. int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(findHandle, 1, calendarID); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { addResult.addEventResult = CDSENTRY_NOCALENDAR; return addResult; } else { addResult.addEventResult = CDSENTRY_FAILED; return addResult; } // Get the required values from the event object. int eventStartYear = 0; int eventStartMonth = 0; int eventStartDay = 0; int eventStartHour = 0; int eventStartMinute = 0; int eventStartSecond = 0; int eventStartDuration = 0; std::string eventString = ""; // Start Date. if (eventData.DateTimeStartData.size() < 16){ addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(0,4); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartYear = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(4,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartMonth = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(6,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartDay = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(9,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartHour = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(11,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartMinute = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeStartData.substr(13,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventStartSecond = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } //eventYear = eventStartDate.substr(0, 4); // End Date. int eventEndYear = 0; int eventEndMonth = 0; int eventEndDay = 0; int eventEndHour = 0; int eventEndMinute = 0; int eventEndSecond = 0; int eventEndDuration = 0; if (eventData.DateTimeEndData != ""){ if (eventData.DateTimeEndData.size() < 16){ addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(0,4); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndYear = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(4,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndMonth = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(6,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndDay = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(9,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndHour = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(11,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndMinute = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } eventString = eventData.DateTimeEndData.substr(13,2); if (all_of(eventString.begin(), eventString.end(), ::isdigit)){ eventEndSecond = atoi(eventString.c_str()); } else { addResult.addEventResult = CDSENTRY_INVALIDFILE; return addResult; } } eventString = eventData.DurationData; // Process the duration data. int eventDurationWeeks = 0; int eventDurationDays = 0; int eventDurationHours = 0; int eventDurationMinutes = 0; int eventDurationSeconds = 0; // Get the duration (if DTEND hasn't been specified). if (eventData.DurationData.size() > 0){ bool FoundP = false; bool FoundW = false; bool DateTimeMode = false; std::string::iterator eventDataChar = eventData.DurationData.begin(); std::string currentValue = ""; if (*eventDataChar != 'P'){ eventDataChar = eventData.DurationData.end(); } for(eventDataChar; eventDataChar != eventData.DurationData.end(); eventDataChar++){ // Check if value is a digit. if (isdigit(*eventDataChar)){ currentValue += *eventDataChar; } else { // Check that the value matches one of the letters. if (*eventDataChar == 'W' && DateTimeMode == false){ eventDurationWeeks = atoi(currentValue.c_str()); } else if (*eventDataChar == 'D' && DateTimeMode == false){ eventDurationDays = atoi(currentValue.c_str()); } else if (*eventDataChar == 'T' && DateTimeMode == false){ DateTimeMode = true; } else if (*eventDataChar == 'H'){ eventDurationHours = atoi(currentValue.c_str()); } else if (*eventDataChar == 'M'){ eventDurationMinutes = atoi(currentValue.c_str()); } else if (*eventDataChar == 'S'){ eventDurationSeconds = atoi(currentValue.c_str()); } // Reset the current value. currentValue = ""; } } } // Add the calendar entry. std::string sqlParameter = "INSERT INTO calendarentries (calendarid, entryname, entrydescription," " entrystartyear, entrystartmonth, entrystartday, entrystarthour, entrystartminute, entrystartsecond," " entryendyear, entryendmonth, entryendday, entryendhour, entryendminute, entryendsecond, " " entrydurationweek, entrydurationday, entrydurationhour, entrydurationminute, entrydurationsecond)" " VALUES ((?1), (?2), (?3), (?4), (?5), (?6), (?7), (?8), (?9), (?10), " " (?11), (?12), (?13), (?14), (?15), (?16), (?17), (?18), (?19), (?20))"; resultCode = sqlite3_prepare_v2(db, sqlParameter.c_str(), -1, &statementHandle, nullptr); resultCode = sqlite3_bind_int(statementHandle, 1, calendarID); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } // Process Entry Name. resultCode = sqlite3_bind_text(statementHandle, 2, eventData.SummaryData.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } // Process Entry Description. string eventDescription; try { eventDescription = eventData.DescriptionList.at(0); } catch (out_of_range &err){ eventDescription = ""; } resultCode = sqlite3_bind_text(statementHandle, 3, eventDescription.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } // Process Entry Start Date information. resultCode = sqlite3_bind_int(statementHandle, 4, eventStartYear); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 5, eventStartMonth); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 6, eventStartDay); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 7, eventStartHour); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 8, eventStartMinute); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 9, eventStartSecond); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } // Process Entry Start End information. resultCode = sqlite3_bind_int(statementHandle, 10, eventEndYear); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 11, eventEndMonth); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 12, eventEndDay); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 13, eventEndHour); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 14, eventEndMinute); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 15, eventEndSecond); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 16, eventDurationWeeks); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 17, eventDurationDays); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 18, eventDurationHours); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 19, eventDurationMinutes); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_bind_int(statementHandle, 20, eventDurationSeconds); if (resultCode != 0){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ addResult.addEventResult = CDSENTRY_FAILED; return addResult; } addResult.calendarEntryID = sqlite3_last_insert_rowid(db); addResult.addEventResult = CDSENTRY_OK; // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); return addResult; } CDSGetCalendarEntryInfo CalendarDataStorage::GetEvent(int calendarEntryID) { CDSGetCalendarEntryInfo entryResult; // Check if the calendar entry exists. int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } resultCode = sqlite3_bind_int(findHandle, 1, calendarEntryID); if (resultCode != 0){ entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { entryResult.getEventResult = CDSENTRY_NOENTRY; return entryResult; } else { entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } // Get the calendar entry data. std::string sqlParameter = "SELECT entryname, entrydescription," " entrystartyear, entrystartmonth, entrystartday, entrystarthour, entrystartminute, entrystartsecond," " entryendyear, entryendmonth, entryendday, entryendhour, entryendminute, entryendsecond, " " entrydurationweek, entrydurationday, entrydurationhour, entrydurationminute, entrydurationsecond, " " calendarid" " FROM calendarentries WHERE id=(?1)"; resultCode = sqlite3_prepare_v2(db, sqlParameter.c_str(), -1, &statementHandle, nullptr); if (resultCode != 0){ entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } resultCode = sqlite3_bind_int(statementHandle, 1, calendarEntryID); if (resultCode != 0){ entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_ROW){ // Get the calendar entry name, stringstream entryStream; entryStream << sqlite3_column_text(statementHandle, 0); entryResult.entryName = entryStream.str(); entryStream.str(""); // Get the calendar entry description. entryStream << sqlite3_column_text(statementHandle, 1); entryResult.entryDescription = entryStream.str(); entryStream.str(""); entryResult.entryStartYear = sqlite3_column_int(statementHandle, 2); entryResult.entryStartMonth = sqlite3_column_int(statementHandle, 3); entryResult.entryStartDay = sqlite3_column_int(statementHandle, 4); entryResult.entryStartHour = sqlite3_column_int(statementHandle, 5); entryResult.entryStartMinute = sqlite3_column_int(statementHandle, 6); entryResult.entryStartSecond = sqlite3_column_int(statementHandle, 7); entryResult.entryEndYear = sqlite3_column_int(statementHandle, 8); entryResult.entryEndMonth = sqlite3_column_int(statementHandle, 9); entryResult.entryEndDay = sqlite3_column_int(statementHandle, 10); entryResult.entryEndHour = sqlite3_column_int(statementHandle, 11); entryResult.entryEndMinute = sqlite3_column_int(statementHandle, 12); entryResult.entryEndSecond = sqlite3_column_int(statementHandle, 13); entryResult.entryDurationWeeks = sqlite3_column_int(statementHandle, 14); entryResult.entryDurationDays = sqlite3_column_int(statementHandle, 15); entryResult.entryDurationHours = sqlite3_column_int(statementHandle, 16); entryResult.entryDurationMinutes = sqlite3_column_int(statementHandle, 17); entryResult.entryDurationSeconds = sqlite3_column_int(statementHandle, 18); entryResult.calendarID = sqlite3_column_int(statementHandle, 19); } else if (resultCode == SQLITE_DONE) { entryResult.getEventResult = CDSENTRY_NOCALENDAR; return entryResult; } else { entryResult.getEventResult = CDSENTRY_FAILED; return entryResult; } entryResult.getEventResult = CDSENTRY_OK; return entryResult; } CDSEntryResult CalendarDataStorage::DeleteEvent(int calendarEntryID) { CDSEntryResult deleteResult = CDSENTRY_UNITTESTFAIL; // Check if the calendar entry exists. int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSENTRY_FAILED; } resultCode = sqlite3_bind_int(findHandle, 1, calendarEntryID); if (resultCode != 0){ return CDSENTRY_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSENTRY_NOENTRY; } else { return CDSENTRY_FAILED; } // Delete the account. resultCode = sqlite3_prepare_v2(db, "DELETE FROM calendarentries WHERE id=(?1);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSENTRY_FAILED; } resultCode = sqlite3_bind_int(statementHandle, 1, calendarEntryID); if (resultCode != 0){ return CDSENTRY_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode == SQLITE_DONE){ deleteResult = CDSENTRY_OK; } else { return CDSENTRY_FAILED; } // Update the checksum. UpdateChecksum("internal_updatedata", to_string(GenerateRandomNumber(CDS_RANDOMPOW))); return deleteResult; } CDSEntryList CalendarDataStorage::GetEventList(int calendarID){ CDSEntryList entryList; entryList.getEventListResult = CDSENTRY_UNITTESTFAIL; // Check if calendar exists first. int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *calendarHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id from calendars WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_bind_int(findHandle, 1, calendarID); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { entryList.getEventListResult = CDSENTRY_NOCALENDAR; return entryList; } else { entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } // Get the list of entry IDs. resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE calendarid=(?1);", -1, &calendarHandle, nullptr); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_bind_int(calendarHandle, 1, calendarID); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_step(calendarHandle); if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){ } else { entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } while (resultCode == SQLITE_ROW){ int calendarID = sqlite3_column_int(calendarHandle, 0); entryList.entryList.push_back(calendarID); resultCode = sqlite3_step(calendarHandle); } entryList.getEventListResult = CDSENTRY_OK; return entryList; } CDSEntryList CalendarDataStorage::GetEventListByDate(int calendarYear, int calendarMonth, int calendarDay){ CDSEntryList entryList; entryList.getEventListResult = CDSENTRY_UNITTESTFAIL; // Check if calendar exists first. int resultCode; sqlite3_stmt *calendarHandle; // Get the list of entry IDs. resultCode = sqlite3_prepare_v2(db, "SELECT id FROM calendarentries WHERE entrystartyear=(?1) AND entrystartmonth=(?2) AND entrystartday=(?3);", -1, &calendarHandle, nullptr); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_bind_int(calendarHandle, 1, calendarYear); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_bind_int(calendarHandle, 2, calendarMonth); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_bind_int(calendarHandle, 3, calendarDay); if (resultCode != 0){ entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } resultCode = sqlite3_step(calendarHandle); if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){ } else { entryList.getEventListResult = CDSENTRY_FAILED; return entryList; } while (resultCode == SQLITE_ROW){ int calendarID = sqlite3_column_int(calendarHandle, 0); entryList.entryList.push_back(calendarID); resultCode = sqlite3_step(calendarHandle); } entryList.getEventListResult = CDSENTRY_OK; return entryList; } CDSCalendarList CalendarDataStorage::GetCalendarList(int accountID){ CDSCalendarList calendarList; calendarList.getCalendarListResult = CDSCALENDAR_UNITTESTFAIL; // Check if calendar exists first. int resultCode; sqlite3_stmt *findHandle; sqlite3_stmt *calendarHandle; resultCode = sqlite3_prepare_v2(db, "SELECT id from accounts WHERE id=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } resultCode = sqlite3_bind_int(findHandle, 1, accountID); if (resultCode != 0){ calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { calendarList.getCalendarListResult = CDSCALENDAR_NOCALENDAR; return calendarList; } else { calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } // Get the list of entry IDs. resultCode = sqlite3_prepare_v2(db, "SELECT id, calendarid FROM calendars WHERE accountid=(?1);", -1, &calendarHandle, nullptr); if (resultCode != 0){ calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } resultCode = sqlite3_bind_int(calendarHandle, 1, accountID); if (resultCode != 0){ calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } resultCode = sqlite3_step(calendarHandle); if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW){ } else { calendarList.getCalendarListResult = CDSCALENDAR_FAILED; return calendarList; } while (resultCode == SQLITE_ROW){ int calendarID = sqlite3_column_int(calendarHandle, 0); stringstream calendarStream; calendarStream << sqlite3_column_text(calendarHandle, 1); calendarList.calendarList.push_back(calendarID); calendarList.calendarListTextID.push_back(calendarStream.str()); calendarStream.str(""); resultCode = sqlite3_step(calendarHandle); } calendarList.getCalendarListResult = CDSCALENDAR_OK; return calendarList; } CDSChecksumResult CalendarDataStorage::AddChecksum(string checksumName, string checksumValue){ int resultCode; // Check if the checksum already exists. sqlite3_stmt *findHandle; sqlite3_stmt *checksumHandle; resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &findHandle, nullptr); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(findHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_step(findHandle); if (resultCode == SQLITE_ROW){ return CDSCHECKSUM_CHECKSUMALREADYEXISTS; } else if (resultCode == SQLITE_DONE) { } else { return CDSCHECKSUM_FAILED; } // Add the checksum to the checksum table. resultCode = sqlite3_prepare_v2(db, "INSERT INTO checksums (checksumname, checksumvalue) VALUES(?1, ?2);", -1, &checksumHandle, nullptr); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(checksumHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(checksumHandle, 2, checksumValue.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_step(checksumHandle); if (resultCode != SQLITE_DONE){ return CDSCHECKSUM_FAILED; } return CDSCHECKSUM_OK; } CDSGetChecksumResult CalendarDataStorage::GetChecksum(string checksumName){ CDSGetChecksumResult getChecksumResult; int resultCode; // Check if the checksum already exists. sqlite3_stmt *getHandle; resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &getHandle, nullptr); if (resultCode != 0){ getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED; return getChecksumResult; } resultCode = sqlite3_bind_text(getHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED; return getChecksumResult; } resultCode = sqlite3_step(getHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { getChecksumResult.getChecksumResult = CDSCHECKSUM_NOHASH; return getChecksumResult; } else { getChecksumResult.getChecksumResult = CDSCHECKSUM_FAILED; return getChecksumResult; } stringstream checksumStream; checksumStream << sqlite3_column_text(getHandle, 0); getChecksumResult.checksumValue = checksumStream.str(); getChecksumResult.getChecksumResult = CDSCHECKSUM_OK; return getChecksumResult; } CDSChecksumResult CalendarDataStorage::UpdateChecksum(std::string checksumName, std::string checksumValue){ int resultCode; // Check if the checksum already exists. sqlite3_stmt *getHandle; sqlite3_stmt *statementHandle; resultCode = sqlite3_prepare_v2(db, "SELECT checksumvalue from checksums WHERE checksumname=(?1);", -1, &getHandle, nullptr); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(getHandle, 1, checksumName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_step(getHandle); if (resultCode == SQLITE_ROW){ } else if (resultCode == SQLITE_DONE) { return CDSCHECKSUM_NOHASH; } else { return CDSCHECKSUM_FAILED; } // Update the checksum. resultCode = sqlite3_prepare_v2(db, "UPDATE checksums SET checksumvalue=(?1) WHERE checksumname=(?2);", -1, &statementHandle, nullptr); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 1, checksumValue.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_bind_text(statementHandle, 2, checksumName.c_str(), -1, SQLITE_STATIC); if (resultCode != 0){ return CDSCHECKSUM_FAILED; } resultCode = sqlite3_step(statementHandle); if (resultCode != SQLITE_DONE){ return CDSCHECKSUM_FAILED; } return CDSCHECKSUM_OK; }