1 /*
2 
3   $Id$
4 
5   G N O K I I
6 
7   A Linux/Unix toolset and driver for the mobile phones.
8 
9   This file is part of gnokii.
10 
11   Gnokii is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2 of the License, or
14   (at your option) any later version.
15 
16   Gnokii is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   You should have received a copy of the GNU General Public License
22   along with gnokii; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 
25   Copyright (C) 1999-2000  Hugh Blemings & Pavel Janik ml.
26   Copyright (C) 1999-2000  Gary Reuter, Reinhold Jordan
27   Copyright (C) 1999-2006  Pawel Kot
28   Copyright (C) 2000-2002  Marcin Wiacek, Chris Kemp, Manfred Jonsson
29   Copyright (C) 2001       Marian Jancar, Bartek Klepacz
30   Copyright (C) 2001-2002  Pavel Machek, Markus Plail
31   Copyright (C) 2002       Ladis Michl, Simon Huggins
32   Copyright (C) 2002-2004  BORBELY Zoltan
33   Copyright (C) 2003       Bertrik Sikken
34   Copyright (C) 2004       Martin Goldhahn
35 
36   Mainline code for gnokii utility. Calendar functions.
37 
38 */
39 
40 #include "config.h"
41 #include "misc.h"
42 #include "compat.h"
43 
44 #include <stdio.h>
45 #ifndef _GNU_SOURCE
46 #  define _GNU_SOURCE 1
47 #endif
48 #include <getopt.h>
49 
50 #include "gnokii-app.h"
51 #include "gnokii.h"
52 
calendar_usage(FILE * f)53 void calendar_usage(FILE *f)
54 {
55 	fprintf(f, _(
56 		     "Calendar options:\n"
57 		     "          --getcalendarnote start_number [end_number|end] [-v|--vCal]\n"
58 		     "          --writecalendarnote vcalendarfile start_number [end_number|end]\n"
59 		     "          --deletecalendarnote start [end_number|end]\n"
60 		     ));
61 }
62 
getcalendarnote_usage(FILE * f,int exitval)63 int getcalendarnote_usage(FILE *f, int exitval)
64 {
65 	fprintf(f, _("usage: --getcalendarnote start_number [end_number | end] [-v|--vCal]\n"
66 			"                        start_number - entry number in the phone calendar (numeric)\n"
67 			"                        end_number   - read to this entry in the phone calendar (numeric, optional)\n"
68 			"                        end          - the string \"end\" indicates all entries from start to end\n"
69 			"                        -v           - output in iCalendar format\n"
70 			"  NOTE: if no end is given, only the start entry is read\n"
71 	));
72 	return exitval;
73 }
74 
75 /* Calendar notes receiving. */
getcalendarnote(int argc,char * argv[],gn_data * data,struct gn_statemachine * state)76 gn_error getcalendarnote(int argc, char *argv[], gn_data *data, struct gn_statemachine *state)
77 {
78 	gn_calnote_list		calnotelist;
79 	gn_calnote		calnote;
80 	gn_error		error = GN_ERR_NONE;
81 	int			i, first_location, last_location;
82 	bool			vcal = false;
83 
84 	struct option options[] = {
85 		{ "vCal",    optional_argument, NULL, 'v'},
86 		{ NULL,      0,                 NULL, 0}
87 	};
88 
89 	first_location = gnokii_atoi(optarg);
90 	if (errno || first_location < 0)
91 		return getcalendarnote_usage(stderr, -1);
92 	last_location = parse_end_value_option(argc, argv, optind, first_location);
93 	if (errno || last_location < 0)
94 		return getcalendarnote_usage(stderr, -1);
95 
96 	while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
97 		switch (i) {
98 		case 'v':
99 			vcal = true;
100 			break;
101 		default:
102 			return getcalendarnote_usage(stderr, -1);
103 		}
104 	}
105 	if (argc > optind + 1) {
106 		/* There are too many arguments that don't start with '-' */
107 		return getcalendarnote_usage(stderr, -1);
108 	}
109 
110 	for (i = first_location; i <= last_location; i++) {
111 		memset(&calnote, 0, sizeof(calnote));
112 		memset(&calnotelist, 0, sizeof(calnotelist));
113 		calnote.location = i;
114 
115 		gn_data_clear(data);
116 		data->calnote = &calnote;
117 		data->calnote_list = &calnotelist;
118 
119 		error = gn_sm_functions(GN_OP_GetCalendarNote, data, state);
120 
121 		if (error == GN_ERR_NONE) {
122 			if (vcal) {
123 				char *ical;
124 
125 				ical = gn_calnote2icalstr(&calnote);
126 				fprintf(stdout, "%s\n", ical);
127 				free (ical);
128 			} else {  /* Plain text output */
129 				/* Translators: this is the header of a calendar note. Example: 1 (1). Type: Meeting */
130 				fprintf(stdout, _("%d (%d). %s: %s\n"), i, calnote.location, _("Type"), gn_calnote_type2str(calnote.type));
131 
132 				fprintf(stdout, _("   Start date: %d-%02d-%02d\n"), calnote.time.year,
133 					calnote.time.month,
134 					calnote.time.day);
135 
136 				if (calnote.type != GN_CALNOTE_BIRTHDAY) {
137 					fprintf(stdout, _("   Start time: %02d:%02d:%02d\n"), calnote.time.hour,
138 						calnote.time.minute,
139 						calnote.time.second);
140 
141 					if (calnote.end_time.year) {
142 						fprintf(stdout, _("   End date: %d-%02d-%02d\n"), calnote.end_time.year,
143 							calnote.end_time.month,
144 							calnote.end_time.day);
145 
146 						fprintf(stdout, _("   End time: %02d:%02d:%02d\n"), calnote.end_time.hour,
147 							calnote.end_time.minute,
148 							calnote.end_time.second);
149 					}
150 				}
151 
152 				if (calnote.alarm.enabled) {
153 					if (calnote.type == GN_CALNOTE_BIRTHDAY) {
154 						fprintf(stdout, _("   Alarm date: %02d-%02d\n"),
155 							calnote.alarm.timestamp.month,
156 							calnote.alarm.timestamp.day);
157 					} else {
158 						fprintf(stdout, _("   Alarm date: %d-%02d-%02d\n"),
159 							calnote.alarm.timestamp.year,
160 							calnote.alarm.timestamp.month,
161 							calnote.alarm.timestamp.day);
162 					}
163 					fprintf(stdout, _("   Alarm time: %02d:%02d:%02d\n"),
164 						calnote.alarm.timestamp.hour,
165 						calnote.alarm.timestamp.minute,
166 						calnote.alarm.timestamp.second);
167 					fprintf(stdout, _("   Alarm tone %s\n"),
168 						calnote.alarm.tone ? _("enabled") : _("disabled"));
169 				}
170 
171 				fprintf(stdout, _("   %s: "), _("Repeat"));
172 				switch (calnote.recurrence) {
173 				case GN_CALNOTE_NEVER:
174 				case GN_CALNOTE_DAILY:
175 				case GN_CALNOTE_WEEKLY:
176 				case GN_CALNOTE_2WEEKLY:
177 				case GN_CALNOTE_MONTHLY:
178 				case GN_CALNOTE_YEARLY:
179 					fprintf(stdout,"%s\n", gn_calnote_recurrence2str(calnote.recurrence));
180 					break;
181 				default:
182 					fprintf(stdout, _("Every %d hours"), calnote.recurrence);
183 					break;
184 				}
185 
186 				if (calnote.recurrence != GN_CALNOTE_NEVER) {
187 					fprintf(stdout, _("   The event will be repeated "));
188 					switch (calnote.occurrences) {
189 					case 0:
190 						fprintf(stdout, _("forever."));
191 						break;
192 					default:
193 						fprintf(stdout, _("%d times."), calnote.occurrences);
194 						break;
195 					}
196 					fprintf(stdout, "\n");
197 				}
198 
199 				fprintf(stdout, _("   Text: %s\n"), calnote.text);
200 
201 				switch (calnote.type) {
202 				case GN_CALNOTE_CALL:
203 					fprintf(stdout, _("   %s: %s\n"), _("Phone"), calnote.phone_number);
204 					break;
205 				case GN_CALNOTE_MEETING:
206 					fprintf(stdout, _("   %s: %s\n"), _("Location"), calnote.mlocation);
207 					break;
208 				case GN_CALNOTE_BIRTHDAY:
209 				case GN_CALNOTE_REMINDER:
210 				case GN_CALNOTE_MEMO:
211 					/* was already printed as calnote.text above */
212 					break;
213 				}
214 			}
215 
216 		} else { /* error != GN_ERR_NONE */
217 			/* stop processing if the last note was specified as "end" */
218 			if (last_location == INT_MAX) {
219 				/* it's not an error if we read at least a note and the rest is empty */
220 				if ((i > first_location) && ((error == GN_ERR_EMPTYLOCATION) || (error == GN_ERR_INVALIDLOCATION))) {
221 					error = GN_ERR_NONE;
222 				}
223 				last_location = 0;
224 			}
225 			if (error != GN_ERR_NONE) {
226 				fprintf(stderr, _("The calendar note can not be read: %s\n"), gn_error_print(error));
227 			}
228 		}
229 	}
230 
231 	return error;
232 }
233 
writecalendarnote_usage(FILE * f,int exitval)234 int writecalendarnote_usage(FILE *f, int exitval)
235 {
236 	fprintf(f, _("usage: --writecalendarnote vcalendarfile start_number [end_number|end]\n"
237 			"                        vcalendarfile - file containing calendar notes in vCal format\n"
238 			"                        start_number  - first calendar note from vcalendarfile to read\n"
239 			"                        end_number    - last calendar note from vcalendarfile to read\n"
240 			"                        end           - read all notes from vcalendarfile from start_number\n"
241 			"  NOTE: it stores the note at the first empty location.\n"
242 	));
243 	return exitval;
244 }
245 
246 /* Writing calendar notes. */
writecalendarnote(int argc,char * argv[],gn_data * data,struct gn_statemachine * state)247 gn_error writecalendarnote(int argc, char *argv[], gn_data *data, struct gn_statemachine *state)
248 {
249 	gn_calnote calnote;
250 	gn_error error = GN_ERR_NONE;
251 	int first_location, last_location, i;
252 	FILE *f;
253 
254 	f = fopen(optarg, "r");
255 	if (f == NULL) {
256 		fprintf(stderr, _("Can't open file %s for reading!\n"), optarg);
257 		return GN_ERR_FAILED;
258 	}
259 
260 	first_location = gnokii_atoi(argv[optind]);
261 	if (errno || first_location < 0) {
262 		fclose(f);
263 		return writecalendarnote_usage(stderr, -1);
264 	}
265 	last_location = parse_end_value_option(argc, argv, optind + 1, first_location);
266 	if (errno || last_location < 0) {
267 		fclose(f);
268 		return writecalendarnote_usage(stderr, -1);
269 	}
270 
271 	for (i = first_location; i <= last_location; i++) {
272 
273 		memset(&calnote, 0, sizeof(calnote));
274 		gn_data_clear(data);
275 		data->calnote = &calnote;
276 
277 		/* TODO: gn_ical2note expects the pointer to begin file to
278 		 * iterate. Fix it to not rewind the file each time
279 		 */
280 		rewind(f);
281 		error = gn_ical2calnote(f, &calnote, i);
282 
283 #ifndef WIN32
284 		if (error == GN_ERR_NOTIMPLEMENTED) {
285 			switch (gn_vcal_file_event_read(optarg, &calnote, i)) {
286 			case 0:
287 				error = GN_ERR_NONE;
288 				break;
289 			default:
290 				error = GN_ERR_FAILED;
291 				break;
292 			}
293 		}
294 #endif
295 		if (error != GN_ERR_NONE) {
296 			/* when reading until 'end' it's not an error if it tried to read a non existant note */
297 			if ((last_location == INT_MAX) && (error == GN_ERR_EMPTYLOCATION)) {
298 				error = GN_ERR_NONE;
299 			} else {
300 				fprintf(stderr, _("Failed to load vCalendar file: %s\n"), gn_error_print(error));
301 			}
302 			fclose(f);
303 			return error;
304 		}
305 
306 		error = gn_sm_functions(GN_OP_WriteCalendarNote, data, state);
307 
308 		if (error == GN_ERR_NONE)
309 			fprintf(stderr, _("Successfully written!\n"));
310 		else
311 			fprintf(stderr, _("Failed to write calendar note: %s\n"), gn_error_print(error));
312 	}
313 	fclose(f);
314 
315 	return error;
316 }
317 
deletecalendarnote_usage(FILE * f,int exitval)318 int deletecalendarnote_usage(FILE *f, int exitval)
319 {
320 	fprintf(f, _("usage: --deletecalendarnote start_number [end_number | end]\n"
321 			"                        start_number - first number in the phone calendar (numeric)\n"
322 			"                        end_number   - until this entry in the phone calendar (numeric, optional)\n"
323 			"                        end          - the string \"end\" indicates all entries from start to end\n"
324 			"  NOTE: if no end is given, only the start entry is deleted\n"
325 	));
326 	return exitval;
327 }
328 
329 /* Calendar note deleting. */
deletecalendarnote(int argc,char * argv[],gn_data * data,struct gn_statemachine * state)330 gn_error deletecalendarnote(int argc, char *argv[], gn_data *data, struct gn_statemachine *state)
331 {
332 	gn_calnote calnote;
333 	gn_calnote_list clist;
334 	int i, first_location, last_location;
335 	gn_error error = GN_ERR_NONE;
336 
337 	gn_data_clear(data);
338 	memset(&calnote, 0, sizeof(gn_calnote));
339 	data->calnote = &calnote;
340 	memset(&clist, 0, sizeof(gn_calnote_list));
341 	data->calnote_list = &clist;
342 
343 	first_location = gnokii_atoi(optarg);
344 	if (errno || first_location < 0)
345 		return deletecalendarnote_usage(stderr, -1);
346 	last_location = parse_end_value_option(argc, argv, optind, first_location);
347 	if (errno || last_location < 0)
348 		return deletecalendarnote_usage(stderr, -1);
349 
350 	for (i = first_location; i <= last_location; i++) {
351 		calnote.location = i;
352 
353 		error = gn_sm_functions(GN_OP_DeleteCalendarNote, data, state);
354 		if (error == GN_ERR_NONE)
355 			fprintf(stderr, _("Calendar note deleted.\n"));
356 		else {
357 			fprintf(stderr, _("The calendar note cannot be deleted: %s\n"), gn_error_print(error));
358 			if (last_location == INT_MAX)
359 				last_location = 0;
360 		}
361 	}
362 
363 	return error;
364 }
365