Browse Source

initial commit with some parsing already working

main
Stefan Pranger 4 years ago
commit
f6e133c2c6
  1. 19
      CMakeLists.txt
  2. 108
      calendar-daemon.cpp
  3. 44
      ical/Alarm.cpp
  4. 32
      ical/Alarm.h
  5. 38
      ical/Event.cpp
  6. 23
      ical/Event.h
  7. 15
      ical/IcalObject.h
  8. 7
      io/debug.cpp
  9. 30
      io/debug.h
  10. 244
      util/calendar_parsing.cpp
  11. 28
      util/calendar_parsing.h
  12. BIN
      util/calendar_parsing.o
  13. 2
      util/calendar_parsing.o.d
  14. 12
      util/notifications.h

19
CMakeLists.txt

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(notification-daemon CXX)
# get all *.cpp files recursively
#file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
#file(GLOB_RECURSE HEADER_FILES ${PROJECT_SOURCE_DIR}/*.h)
include_directories(${PROJECT_SOURCE_DIR})
#add_executable(notification-daemon ${SRC_FILES} ${HEADER_FILES})
add_executable(notification-daemon
calendar-daemon
util/calendar_parsing.cpp
util/notifications.h
ical/Alarm.cpp
ical/Event.cpp
ical/IcalObject.h
io/debug.cpp
)
add_definitions(-DLOG_DEBUG)
target_link_libraries(notification-daemon ical boost_system boost_filesystem)
target_compile_options(notification-daemon PRIVATE -g)

108
calendar-daemon.cpp

@ -0,0 +1,108 @@
#include <dirent.h>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
#include <vector>
#include <sqlite3.h>
#include <util/notifications.h>
#include <util/calendar_parsing.h>
#include <io/debug.h>
const int MINUTE = 1000000;
void update_database() {
std::vector<ical::ical_object*> objects = util::parse_cal_dir();
}
void do_heartbeat()
{
util::notify("Testing", "");
update_database();
}
// For security purposes, we don't allow any arguments to be passed into the daemon
int main(void)
{
// Define variables
//pid_t pid, sid;
//// Fork the current process
//pid = fork();
//// The parent process continues with a process ID greater than 0
//if(pid > 0)
//{
// exit(EXIT_SUCCESS);
//}
//// A process ID lower than 0 indicates a failure in either process
//else if(pid < 0)
//{
// exit(EXIT_FAILURE);
//}
//// The parent process has now terminated, and the forked child process will continue
//// (the pid of the child process was 0)
//// Since the child process is a daemon, the umask needs to be set so files and logs can be written
//umask(0);
//// Open system logs for the child process
//openlog("daemon-named", LOG_NOWAIT | LOG_PID, LOG_USER);
//syslog(LOG_NOTICE, "Successfully started daemon-name");
//// Generate a session ID for the child process
//sid = setsid();
//// Ensure a valid SID for the child process
//if(sid < 0)
//{
// // Log failure and exit
// syslog(LOG_ERR, "Could not generate session ID for child process");
// // If a new session ID could not be generated, we must terminate the child process
// // or it will be orphaned
// exit(EXIT_FAILURE);
//}
//// Change the current working directory to a directory guaranteed to exist
//if((chdir("/")) < 0)
//{
// // Log failure and exit
// syslog(LOG_ERR, "Could not change working directory to /");
// // If our guaranteed directory does not exist, terminate the child process to ensure
// // the daemon has not been hijacked
// exit(EXIT_FAILURE);
//}
//// A daemon cannot use the terminal, so close standard file descriptors for security reasons
//close(STDIN_FILENO);
//close(STDOUT_FILENO);
//close(STDERR_FILENO);
// Daemon-specific intialization should go here
const int SLEEP_INTERVAL = 5 * MINUTE;
// Enter daemon loop
while(1)
{
// Execute daemon heartbeat, where your recurring activity occurs
do_heartbeat();
exit(0);
// Sleep for a period of time
sleep(SLEEP_INTERVAL);
}
// Close system logs for the child process
//syslog(LOG_NOTICE, "Stopping daemon-name");
//closelog();
// Terminate the child process when the daemon completes
exit(EXIT_SUCCESS);
}

44
ical/Alarm.cpp

@ -0,0 +1,44 @@
#include <ical/Alarm.h>
#include <libical/icalproperty_cxx.h>
namespace ical {
Alarm::Alarm(icalcomponent* alarm_component) {
parse(alarm_component);
}
void Alarm::parse(icalcomponent* alarm_component) {
parse_action(alarm_component);
parse_description(alarm_component);
parse_trigger(alarm_component);
DEBUG << "\n" << print();
}
void Alarm::parse_action(icalcomponent* alarm_component) {
DEBUG << icalproperty_get_value_as_string(icalcomponent_get_first_property(alarm_component, ICAL_ACTION_PROPERTY));
}
void Alarm::parse_description(icalcomponent* alarm_component) {
// TODO Error Handling
description = icalproperty_get_value_as_string(icalcomponent_get_first_property(alarm_component, ICAL_DESCRIPTION_PROPERTY));
}
void Alarm::parse_trigger(icalcomponent* alarm_component) {
icalproperty* trigger_property = icalcomponent_get_first_property(alarm_component, ICAL_TRIGGER_PROPERTY);
struct icaltriggertype tr;
if(trigger_property != 0) {
tr = icalproperty_get_trigger(trigger_property);
if (!icaltime_is_null_time(tr.time)) {
trigger = ical::trigger_type::ABSOLUTE;
} else {
trigger = ical::trigger_type::RELATIVE;
}
}
}
std::string Alarm::print() {
std::string s = "";
s += "DESCRIPTION: " + description + "\n";
s += trigger == ical::trigger_type::ABSOLUTE ? "ABSOLUTE: " : "RELATIVE: ";
return s;
}
}

32
ical/Alarm.h

@ -0,0 +1,32 @@
#pragma once
#include <string>
#include <memory>
#include <ical/IcalObject.h>
namespace ical {
enum class action {
DISPLAY, AUDIO, EMAIL, PROC
};
enum class trigger_type {
ABSOLUTE, RELATIVE
};
class Alarm {
public:
Alarm(icalcomponent* alarm_component);
void parse(icalcomponent* alarm_component);
void parse_action(icalcomponent* alarm_component);
void parse_description(icalcomponent* alarm_component);
void parse_trigger(icalcomponent* alarm_component);
std::string print();
private:
action a;
trigger_type trigger;
std::string description;
};
}

38
ical/Event.cpp

@ -0,0 +1,38 @@
#include <ical/Event.h>
#include <ical/Alarm.h>
namespace ical {
Event::Event(ical::ical_object* object, icalcomponent* event_component) {
parse(object, event_component);
}
void Event::parse(ical::ical_object* object, icalcomponent* event_component) {
dtstart = icalcomponent_get_dtstart(event_component);
dtend = icalcomponent_get_dtstart(event_component);
summary = std::string(icalcomponent_get_summary(event_component));
parse_alarms(event_component);
DEBUG << "\n" << print();
for(auto& a : alarms) {
DEBUG << "\n" << a.print();
}
object->events.push_back(this);
}
void Event::parse_alarms(icalcomponent* event_component) {
icalcomponent* c;
for(c = icalcomponent_get_first_component(event_component, ICAL_VALARM_COMPONENT);
c != 0;
c = icalcomponent_get_next_component(event_component, ICAL_VALARM_COMPONENT))
{
alarms.push_back(Alarm(c));
}
}
std::string Event::print() {
std::string s = "";
s += "DTSTART: " + std::string(icaltime_as_ical_string(dtstart)) + "\n";
s += "DTEND: " + std::string(icaltime_as_ical_string(dtend)) + "\n";
s += "SUMMARY: " + summary + "\n";
return s;
}
}

23
ical/Event.h

@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <ical/IcalObject.h>
namespace ical {
class Event {
public:
Event(ical::ical_object* object, icalcomponent* event_component);
void parse(ical::ical_object* object, icalcomponent* event);
void parse_alarms(icalcomponent* event_component);
std::string print();
private:
std::string summary;
icaltimetype dtstart;
icaltimetype dtend;
std::vector<Alarm> alarms;
};
}

15
ical/IcalObject.h

@ -0,0 +1,15 @@
#pragma once
#include <libical/ical.h>
#include <vector>
#include <io/debug.h>
namespace ical {
class Alarm;
class Event;
struct ical_object {
std::vector<ical::Event*> events;
};
}

7
io/debug.cpp

@ -0,0 +1,7 @@
#include <io/debug.h>
namespace io {
void debug(std::string msg) {
std::cout << "DEBUG: " << msg << std::endl;;
}
}

30
io/debug.h

@ -0,0 +1,30 @@
#pragma once
#include <iostream>
#include <string>
struct X {
#ifdef LOG_DEBUG
X() { if(false) std::cout.setstate(std::ios_base::failbit); }
~X() { if(false) { std::cout.clear(); } else { std::cout << std::endl << std::flush; } }
#else
X() { std::cout.setstate(std::ios_base::failbit); }
~X() { std::cout.clear(); }
#endif
};
#define DEBUG (X(), std::cout << "DEBUG[" << __FILE__ << ":" << __LINE__ << " in " << __func__ << "()]: ")
#define WARN (X(), std::cout << "WARN [" << __FILE__ << ":" << __LINE__ << " in " << __func__ << "()]: ")
#ifdef LOG_DEBUG
#define STEP \
do { DEBUG << "Stepping through, Hit Enter..."; \
std::cin.get(); \
} while (0)
#else
#define STEP (void)(0)
#endif
namespace io {
void debug(std::string msg);
}

244
util/calendar_parsing.cpp

@ -0,0 +1,244 @@
#include <util/calendar_parsing.h>
#include <memory>
namespace util {
std::vector<ical::ical_object*> parse_cal_dir() {
std::vector<ical::ical_object*> objects;
std::vector<icalcomponent*> components;
for (boost::filesystem::directory_entry& entry : boost::filesystem::directory_iterator(cal_dir)) {
DEBUG << "Parsing: " + entry.path().generic_string();
ical::ical_object* object = new ical::ical_object();
parse_main_component(object, parse_ics_file(entry.path().generic_string()));
}
return objects;
}
icalcomponent* parse_main_component(ical::ical_object* object, icalcomponent* component) {
icalcomponent* c = icalcomponent_get_first_component(component, ICAL_ANY_COMPONENT);
while(c != 0) {
if(c != 0) {
parse_component(object, c);
}
c = parse_main_component(object, c);
if(c == 0) {
c = icalcomponent_get_next_component(component, ICAL_ANY_COMPONENT);
}
}
return c;
}
void parse_component(ical::ical_object* object, icalcomponent* component) {
switch(icalcomponent_isa(component)) {
case ICAL_VALARM_COMPONENT: break;
case ICAL_NO_COMPONENT:
{
DEBUG << "parsed component: ICAL_NO_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_ANY_COMPONENT:
{
DEBUG << "parsed component: ICAL_ANY_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XROOT_COMPONENT:
{
DEBUG << "parsed component: ICAL_XROOT_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XATTACH_COMPONENT:
{
DEBUG << "parsed component: ICAL_XATTACH_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VEVENT_COMPONENT:
{
DEBUG << "parsed component: ICAL_VEVENT_COMPONENT";
//DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
ical::Event(object, component);
break;
}
case ICAL_VTODO_COMPONENT:
{
DEBUG << "parsed component: ICAL_VTODO_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VJOURNAL_COMPONENT:
{
DEBUG << "parsed component: ICAL_VJOURNAL_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VCALENDAR_COMPONENT:
{
DEBUG << "parsed component: ICAL_VCALENDAR_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VAGENDA_COMPONENT:
{
DEBUG << "parsed component: ICAL_VAGENDA_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VFREEBUSY_COMPONENT:
{
DEBUG << "parsed component: ICAL_VFREEBUSY_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XAUDIOALARM_COMPONENT:
{
DEBUG << "parsed component: ICAL_XAUDIOALARM_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XDISPLAYALARM_COMPONENT:
{
DEBUG << "parsed component: ICAL_XDISPLAYALARM_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XEMAILALARM_COMPONENT:
{
DEBUG << "parsed component: ICAL_XEMAILALARM_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XPROCEDUREALARM_COMPONENT:
{
DEBUG << "parsed component: ICAL_XPROCEDUREALARM_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VTIMEZONE_COMPONENT:
{
DEBUG << "parsed component: ICAL_VTIMEZONE_COMPONENT";
break;
}
case ICAL_XSTANDARD_COMPONENT:
{
DEBUG << "parsed component: ICAL_XSTANDARD_COMPONENT";
break;
}
case ICAL_XDAYLIGHT_COMPONENT:
{
DEBUG << "parsed component: ICAL_XDAYLIGHT_COMPONENT";
break;
}
case ICAL_X_COMPONENT:
{
DEBUG << "parsed component: ICAL_X_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VSCHEDULE_COMPONENT:
{
DEBUG << "parsed component: ICAL_VSCHEDULE_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VQUERY_COMPONENT:
{
DEBUG << "parsed component: ICAL_VQUERY_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VREPLY_COMPONENT:
{
DEBUG << "parsed component: ICAL_VREPLY_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VCAR_COMPONENT:
{
DEBUG << "parsed component: ICAL_VCAR_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VCOMMAND_COMPONENT:
{
DEBUG << "parsed component: ICAL_VCOMMAND_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XLICINVALID_COMPONENT:
{
DEBUG << "parsed component: ICAL_XLICINVALID_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XLICMIMEPART_COMPONENT:
{
DEBUG << "parsed component: ICAL_XLICMIMEPART_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VAVAILABILITY_COMPONENT:
{
DEBUG << "parsed component: ICAL_VAVAILABILITY_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XAVAILABLE_COMPONENT:
{
DEBUG << "parsed component: ICAL_XAVAILABLE_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VPOLL_COMPONENT:
{
DEBUG << "parsed component: ICAL_VPOLL_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VVOTER_COMPONENT:
{
DEBUG << "parsed component: ICAL_VVOTER_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XVOTE_COMPONENT:
{
DEBUG << "parsed component: ICAL_XVOTE_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_VPATCH_COMPONENT:
{
DEBUG << "parsed component: ICAL_VPATCH_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
case ICAL_XPATCH_COMPONENT:
{
DEBUG << "parsed component: ICAL_XPATCH_COMPONENT";
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
break;
}
default:
DEBUG << "parse_component: something else found";
break;
}
}
std::string slurp(std::ifstream& in) {
std::ostringstream sstr;
sstr << in.rdbuf();
return sstr.str();
}
icalcomponent* parse_ics_file(std::string filename) {
std::ifstream ifs (filename, std::ifstream::in);
return icalparser_parse_string(slurp(ifs).c_str());
}
void debug(icalcomponent* component) {
DEBUG << "\n" << icalcomponent_as_ical_string_r(component);
}
}

28
util/calendar_parsing.h

@ -0,0 +1,28 @@
#pragma once
#include <fstream>
#include <sstream>
#include <iostream>
#include <libical/ical.h>
#include <ical/IcalObject.h>
#include <ical/Alarm.h>
#include <ical/Event.h>
#include <boost/filesystem.hpp>
#include <io/debug.h>
const std::string cal_dir = "/home/stefan/.local/share/khal/calendars/dummy/";
namespace util {
std::vector<ical::ical_object*> parse_cal_dir();
icalcomponent* parse_main_component(ical::ical_object* object, icalcomponent* component);
void parse_component(ical::ical_object* object, icalcomponent* component);
std::string slurp(std::ifstream& in);
icalcomponent* parse_ics_file(std::string filename);
void debug(icalcomponent* component);
}

BIN
util/calendar_parsing.o

2
util/calendar_parsing.o.d

@ -0,0 +1,2 @@
util/calendar_parsing.o: util/calendar_parsing.cpp \
util/calendar_parsing.h io/debug.h

12
util/notifications.h

@ -0,0 +1,12 @@
#pragma once
//#include <libnotify/notify.h>
#include <string>
const std::string exec = "notify-send";
namespace util {
uint notify(std::string summary, std::string body /* */) {
std::string cmd = exec + " " + summary + " " + body;
return system(cmd.c_str());
}
}
Loading…
Cancel
Save