export.c (5273B)
1 #include "export.h" 2 3 /* Export journal entries to an ics file */ 4 void ics_export(const char* ics_filepath, WINDOW* header, WINDOW* cal, WINDOW* aside, int* pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end){ 5 pthread_t progress_tid; 6 int conf_ch; 7 8 char* veventsr; 9 char* vevent_format = "BEGIN:VEVENT\n" 10 "UID:%s\n" 11 "DTSTART;VALUE=DATE:%s\n" 12 "SUMMARY:%s\n" 13 "%s\n" 14 "END:VEVENT\n"; 15 16 size_t begin_size = strlen("BEGIN:VCALENDAR\n"); 17 char* vevents = calloc(begin_size + 1, sizeof(char)); 18 strcat(vevents, "BEGIN:VCALENDAR\n"); 19 20 // prepare header for confirmation dialogue 21 curs_set(2); 22 noecho(); 23 wclear(header); 24 25 // ask for confirmation 26 mvwprintw(header, 0, 0, "Export diary entries to file '%s' (overwrite)? [(Y)es/(n)o] ", ics_filepath); 27 28 do { 29 conf_ch = wgetch(header); 30 31 if (conf_ch == 'n') { 32 return; 33 } else if (conf_ch == 'y' || conf_ch == 'Y' || conf_ch == '\n') { 34 // open ics file for writing 35 FILE* pfile = fopen(ics_filepath, "wb"); 36 if (pfile == NULL) { 37 perror("Error opening ics file for writing"); 38 return; 39 } 40 41 pthread_create(&progress_tid, NULL, show_progress, (void*)header); 42 pthread_detach(progress_tid); 43 44 struct tm it = *cal_start; 45 time_t it_time = mktime(&it); 46 time_t end_time = mktime(cal_end); 47 size_t dirs = strlen(CONFIG.dir); 48 49 for( ; it_time <= end_time; it_time = mktime(&it)) { 50 localtime_r(&it_time, &it); 51 52 if (date_has_entry(CONFIG.dir, dirs, &it)) { 53 // get path of entry 54 char path[100]; 55 char* ppath = path; 56 char* descr; 57 long descr_bytes; 58 59 fpath(CONFIG.dir, dirs, &it, &ppath, sizeof path); 60 61 if (ppath == NULL) { 62 tracepoint(diary, error_date, "Cannot get file path for entry", &it); 63 return; 64 } 65 66 FILE* fp = fopen(path, "r"); 67 if (fp == NULL) perror("Error opening entry path for reading"); 68 69 fseek(fp, 0, SEEK_END); 70 descr_bytes = ftell(fp); 71 rewind(fp); 72 73 size_t descr_label_size = strlen("DESCRIPTION:"); 74 size_t descr_size = descr_bytes + descr_label_size; 75 descr = calloc(descr_size + 1, sizeof(char)); 76 if (descr == NULL) { 77 perror("malloc failed"); 78 return; 79 } 80 81 strcat(descr, "DESCRIPTION:"); 82 83 // read description bytes from journal entry file and append to descr 84 int items_read = fread(descr + descr_label_size, sizeof(char), descr_bytes, fp); 85 if (items_read != descr_bytes) { 86 tracepoint(diary, error_int_long, "Read n items but expected m items, aborting.", items_read, descr_bytes); 87 return; 88 } 89 90 descr[descr_size] = '\0'; 91 92 char* folded_descr = fold(descr); 93 94 char uid[9]; 95 strftime(uid, sizeof uid, "%Y%m%d", &it); 96 97 char* vevent = calloc(strlen(vevent_format) + strlen(folded_descr) + 100, sizeof(char)); 98 sprintf(vevent, vevent_format, 99 uid, 100 uid, 101 uid, // todo: display first few chars of DESCRIPTION as SUMMARY 102 folded_descr); 103 104 veventsr = realloc(vevents, strlen(vevents) + strlen(vevent) + 1); 105 if (veventsr == NULL) { 106 perror("failed to realloc vevents buffer"); 107 free(vevents); 108 break; 109 } else { 110 // vevents ptr already freed by realloc if moved 111 vevents = (char*) veventsr; 112 // append vevent to vevents buffer 113 strcat(vevents, vevent); 114 } 115 116 free(folded_descr); 117 free(descr); 118 free(vevent); 119 } // end date_has_entry 120 121 it.tm_mday++; 122 } // endfor each entry 123 124 veventsr = realloc(vevents, strlen(vevents) + strlen("END:VCALENDAR\n") + 1); 125 if (veventsr == NULL) { 126 perror("failed to realloc vevents buffer"); 127 free(vevents); 128 break; 129 } else { 130 vevents = (char*) veventsr; 131 strcat(vevents, "END:VCALENDAR\n"); 132 } 133 134 fputs(vevents, pfile); 135 fclose(pfile); 136 pthread_cancel(progress_tid); 137 } // end confirm to write 138 } while (!(conf_ch == 'q' || conf_ch == 'n' || conf_ch == 'y' || conf_ch == 'Y' || conf_ch == '\n')); 139 140 free(vevents); 141 }