"Fossies" - the Fresh Open Source Software Archive 
Member "jpilot-2_0_1/dat.c" (3 Apr 2021, 35669 Bytes) of package /linux/privat/jpilot-2_0_1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*******************************************************************************
2 * dat.c
3 * A module of J-Pilot http://jpilot.org
4 *
5 * Copyright (C) 2001-2014 by Judd Montgomery
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program 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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ******************************************************************************/
20 /*
21 * Thanks to nseessle@mail.hh.provi.de
22 * http://ourworld.compuserve.com/homepages/nseessle/frames/pilot/dat_e.htm
23 * http://www.geocities.com/Heartland/Acres/3216/todo_dat.htm
24 * Scott Leighton helphand@pacbell.net
25 *
26 * for their descriptions of the dat formats.
27 */
28
29 /********************************* Includes ***********************************/
30 #include "config.h"
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35
36 #include "i18n.h"
37 #include "utils.h"
38 #include "log.h"
39
40 /********************************* Constants **********************************/
41 #define DAT_STATUS_ADD 0x01
42 #define DAT_STATUS_UPDATE 0x02
43 #define DAT_STATUS_DELETE 0x04
44 #define DAT_STATUS_PENDING 0x08
45 #define DAT_STATUS_ARCHIVE 0x80
46 /* I made this one up for a bit to store the private flag */
47 #define DAT_STATUS_PRIVATE 0x10
48
49 /* Repeat types */
50 #define DAILY 1
51 #define WEEKLY 2
52 #define MONTHLY_BY_DAY 3
53 #define MONTHLY_BY_DATE 4
54 #define YEARLY_BY_DATE 5
55 #define YEARLY_BY_DAY 6
56
57 /* DAT field types */
58 #define DAT_TYPE_INTEGER 1
59 #define DAT_TYPE_CSTRING 5
60 #define DAT_TYPE_DATE 3
61 #define DAT_TYPE_BOOLEAN 6
62 #define DAT_TYPE_BITFLAG 7
63 #define DAT_TYPE_REPEAT 8
64
65 /* #define JPILOT_DEBUG */
66
67 /****************************** Prototypes ************************************/
68 #ifdef JPILOT_DEBUG
69 static int print_date(int palm_date);
70 #endif
71
72 struct field {
73 int type;
74 int i;
75 long date;
76 char *str;
77 };
78
79 /****************************** Main Code *************************************/
80 static int x86_short(unsigned char *str)
81 {
82 return str[1] * 0x100 + str[0];
83 }
84
85 static long x86_long(unsigned char *str)
86 {
87 return str[3]*0x1000000 + str[2]*0x0010000 + str[1]*0x0000100 + str[0];
88 }
89
90 /* Returns the length of the CString read */
91 static int get_CString(FILE *in, char **PStr)
92 {
93 unsigned char size1;
94 unsigned char size2[2];
95 int size;
96
97 if (fread(&size1, 1, 1, in) < 1) {
98 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
99 }
100 if (size1==0) {
101 *PStr = NULL;
102 return 0;
103 }
104 if (size1==0xFF) {
105 if (fread(size2, 2, 1, in) < 1) {
106 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
107 }
108 size = x86_short(size2);
109 #ifdef JPILOT_DEBUG
110 printf("BIG STRING size=%d\n", size);
111 #endif
112 } else {
113 size=size1;
114 }
115 /* malloc an extra byte just to be safe */
116 *PStr=malloc(size+2);
117 if (fread(*PStr, size, 1, in) < 1) {
118 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
119 }
120 (*PStr)[size]='\0';
121
122 return size;
123 }
124
125 static int get_categories(FILE *in, struct CategoryAppInfo *ai)
126 {
127 unsigned char str_long[4];
128 char *PStr;
129 long count;
130 int i;
131
132 /* Get the category count */
133 if (fread(str_long, 4, 1, in) < 1) {
134 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
135 }
136 count = x86_long(str_long);
137
138 for (i=0; i<16; i++) {
139 ai->renamed[i]=0;
140 ai->name[i][0]=0;
141 ai->ID[i]=0;
142 }
143 ai->lastUniqueID=0;
144
145 for (i=0; i<count; i++) {
146 /* category index */
147 if (fread(str_long, 4, 1, in) < 1) {
148 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
149 }
150
151 /* category ID */
152 if (fread(str_long, 4, 1, in) < 1) {
153 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
154 }
155 ai->ID[i] = x86_long(str_long);
156
157 /* category dirty flag */
158 if (fread(str_long, 4, 1, in) < 1) {
159 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
160 }
161
162 /* long category name */
163 get_CString(in, &PStr);
164 strncpy(ai->name[i], PStr, 16);
165 ai->name[i][15]='\0';
166 free(PStr);
167
168 /* short category name */
169 get_CString(in, &PStr);
170 free(PStr);
171 }
172 return count;
173 }
174
175 static int get_repeat(FILE *in, struct Appointment *appt)
176 {
177 time_t t = 0;
178 struct tm *now;
179 unsigned char str_long[4];
180 unsigned char str_short[2];
181 int l, s, i, bit;
182 char *PStr;
183 int repeat_type;
184
185 if (fread(str_short, 2, 1, in) < 1) {
186 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
187 }
188 s = x86_short(str_short);
189 #ifdef JPILOT_DEBUG
190 printf(" repeat entry follows:\n");
191 printf("%d exceptions\n", s);
192 #endif
193 if (!appt)
194 return EXIT_FAILURE;
195
196 appt->exception=NULL;
197 memset(&(appt->repeatEnd), 0, sizeof(appt->repeatEnd));
198
199 appt->exceptions=s;
200 if (s>0) {
201 appt->exception=malloc(sizeof(struct tm) * s);
202 if (!(appt->exceptions)) {
203 jp_logf(JP_LOG_WARN, "get_repeat(): %s\n", _("Out of memory"));
204 }
205 }
206
207 for (i=0; i<s; i++) {
208 if (fread(str_long, 4, 1, in) < 1) {
209 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
210 }
211 l = x86_long(str_long);
212 {
213 t = l;
214 now = localtime(&t);
215 memcpy(&(appt->exception[i]), now, sizeof(struct tm));
216 }
217 #ifdef JPILOT_DEBUG
218 printf("date_exception_entry: ");
219 print_date(l);
220 #endif
221 }
222
223 if (fread(str_short, 2, 1, in) < 1) {
224 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
225 }
226 s = x86_short(str_short);
227 #ifdef JPILOT_DEBUG
228 printf("0x%x repeat event flag\n", s);
229 #endif
230
231 if (s==0x0000) {
232 appt->repeatType=calendarRepeatNone;
233 return EXIT_SUCCESS;
234 }
235
236 if (s==0xFFFF) {
237 /* Class entry here */
238 if (fread(str_short, 2, 1, in) < 1) {
239 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
240 }
241 s = x86_short(str_short);
242 #ifdef JPILOT_DEBUG
243 printf("constant of 1 = %d\n", s);
244 #endif
245 if (fread(str_short, 2, 1, in) < 1) {
246 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
247 }
248 s = x86_short(str_short);
249 #ifdef JPILOT_DEBUG
250 printf("class name length = %d\n", s);
251 #endif
252
253 PStr = malloc(s+1);
254 if (fread(PStr, s, 1, in) < 1) {
255 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
256 }
257 PStr[s]='\0';
258 #ifdef JPILOT_DEBUG
259 printf("class = [%s]\n", PStr);
260 #endif
261 free(PStr);
262 }
263
264 if (fread(str_long, 4, 1, in) < 1) {
265 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
266 }
267 repeat_type = x86_long(str_long);
268 appt->repeatType=repeat_type;
269 #ifdef JPILOT_DEBUG
270 printf("repeatType=%d ", repeat_type);
271 switch (repeat_type) {
272 case DAILY:
273 printf("Daily\n");
274 break;
275 case WEEKLY:
276 printf("Weekly\n");
277 break;
278 case MONTHLY_BY_DAY:
279 printf("MonthlyByDay\n");
280 break;
281 case MONTHLY_BY_DATE:
282 printf("Monthly By Date\n");
283 break;
284 case YEARLY_BY_DATE:
285 printf("Yearly By Date\n");
286 break;
287 case YEARLY_BY_DAY:
288 printf("Yearly By Day\n");
289 break;
290 default:
291 printf("unknown repeat type %d\n", l);
292 }
293 #endif
294
295 if (fread(str_long, 4, 1, in) < 1) {
296 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
297 }
298 l = x86_long(str_long);
299 #ifdef JPILOT_DEBUG
300 printf("Interval = %d\n", l);
301 #endif
302 appt->repeatFrequency=l;
303
304 if (fread(str_long, 4, 1, in) < 1) {
305 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
306 }
307 l = x86_long(str_long);
308 {
309 t = l;
310 now = localtime(&t);
311 memcpy(&(appt->repeatEnd), now, sizeof(struct tm));
312 }
313 if (t==0x749e77bf) {
314 appt->repeatForever=TRUE;
315 } else {
316 appt->repeatForever=FALSE;
317 }
318 #ifdef JPILOT_DEBUG
319 printf("repeatEnd: 0x%x -> ", l); print_date(l);
320 #endif
321 if (fread(str_long, 4, 1, in) < 1) {
322 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
323 }
324 l = x86_long(str_long);
325 appt->repeatWeekstart=l;
326 #ifdef JPILOT_DEBUG
327 printf("First Day of Week = %d\n", l);
328 #endif
329
330 switch (repeat_type) {
331 case DAILY:
332 if (fread(str_long, 4, 1, in) < 1) {
333 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
334 }
335 l = x86_long(str_long);
336 #ifdef JPILOT_DEBUG
337 printf("Day Index = %d\n", l);
338 #endif
339 break;
340 case WEEKLY:
341 if (fread(str_long, 4, 1, in) < 1) {
342 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
343 }
344 l = x86_long(str_long);
345 #ifdef JPILOT_DEBUG
346 printf("Day Index = %d\n", l);
347 #endif
348
349 if (fread(str_long, 1, 1, in) < 1) {
350 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
351 }
352 for (i=0, bit=1; i<7; i++, bit=bit<<1) {
353 appt->repeatDays[i]=( str_long[0] & bit );
354 }
355 #ifdef JPILOT_DEBUG
356 printf("Days Mask = %x\n", str_long[0]);
357 #endif
358 break;
359 case MONTHLY_BY_DAY:
360 if (fread(str_long, 4, 1, in) < 1) {
361 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
362 }
363 s = x86_long(str_long);
364 #ifdef JPILOT_DEBUG
365 printf("Day Index = %d\n", l);
366 #endif
367
368 if (fread(str_long, 4, 1, in) < 1) {
369 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
370 }
371 l = x86_long(str_long);
372 #ifdef JPILOT_DEBUG
373 printf("Week Index = %d\n", l);
374 #endif
375
376 appt->repeatDay = 7*l + s;
377 break;
378 case MONTHLY_BY_DATE:
379 if (fread(str_long, 4, 1, in) < 1) {
380 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
381 }
382 l = x86_long(str_long);
383 #ifdef JPILOT_DEBUG
384 printf("Day Number = %d\n", l);
385 #endif
386 break;
387 case YEARLY_BY_DATE:
388 if (fread(str_long, 4, 1, in) < 1) {
389 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
390 }
391 l = x86_long(str_long);
392 #ifdef JPILOT_DEBUG
393 printf("Day Number = %d\n", l);
394 #endif
395 if (fread(str_long, 4, 1, in) < 1) {
396 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
397 }
398 l = x86_long(str_long);
399 #ifdef JPILOT_DEBUG
400 printf("Month Index = %d\n", l);
401 #endif
402 break;
403 case YEARLY_BY_DAY:
404 break;
405 default:
406 #ifdef JPILOT_DEBUG
407 printf("unknown repeat type2 %d\n", l);
408 #endif
409 break;
410 }
411
412 return EXIT_SUCCESS;
413 }
414
415 #ifdef JPILOT_DEBUG
416 static int print_date(int palm_date)
417 {
418 time_t t;
419 struct tm *now;
420 char text[256];
421
422 t = palm_date; /* - 20828448800; */
423 now = localtime(&t);
424 strftime(text, sizeof(text), "%02m/%02d/%Y %02H:%02M:%02S", now);
425 printf("%s\n", text);
426
427 return EXIT_SUCCESS;
428 }
429 #endif
430
431 #ifdef JPILOT_DEBUG
432 static int print_field(struct field *f)
433 {
434
435 switch (f->type) {
436 case DAT_TYPE_INTEGER:
437 printf("%d\n", f->i);
438 break;
439 case DAT_TYPE_CSTRING:
440 if (f->str)
441 printf("%s\n", f->str);
442 else
443 printf("\n");
444 break;
445 case DAT_TYPE_BOOLEAN:
446 if (f->i) {
447 printf("True\n");
448 } else {
449 printf("False\n");
450 }
451 break;
452 case DAT_TYPE_DATE:
453 print_date(f->date);
454 break;
455 case DAT_TYPE_REPEAT:
456 printf("Repeat Type\n");
457 break;
458 default:
459 printf("print_field: unknown type = %d\n", f->type);
460 break;
461 }
462
463 return EXIT_SUCCESS;
464 }
465 #endif
466
467 static int get_field(FILE *in, struct field *f)
468 {
469 unsigned char str_long[4];
470 long type;
471 char *PStr;
472
473 if (fread(str_long, 4, 1, in) < 1) {
474 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
475 }
476 type = x86_long(str_long);
477 f->type=type;
478 f->str=NULL;
479
480 switch (type) {
481 case DAT_TYPE_INTEGER:
482 if (fread(str_long, 4, 1, in) < 1) {
483 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
484 }
485 f->i = x86_long(str_long);
486 break;
487 case DAT_TYPE_CSTRING:
488 fseek(in, 4, SEEK_CUR); /* padding */
489 get_CString(in, &PStr);
490 f->str = PStr;
491 break;
492 case DAT_TYPE_BOOLEAN:
493 if (fread(str_long, 4, 1, in) < 1) {
494 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
495 }
496 f->i = x86_long(str_long);
497 break;
498 case DAT_TYPE_DATE:
499 if (fread(str_long, 4, 1, in) < 1) {
500 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
501 }
502 f->date = x86_long(str_long);
503 break;
504 case DAT_TYPE_BITFLAG:
505 /* I currently do not know how to read this datatype */
506 break;
507 case DAT_TYPE_REPEAT:
508 /* The calling function needs to call this */
509 /* get_repeat(in, NULL); */
510 break;
511 default:
512 jp_logf(JP_LOG_WARN, "get_field(): %s %ld\n", _("unknown type ="), type);
513 break;
514 }
515
516 return EXIT_SUCCESS;
517 }
518
519 int dat_check_if_dat_file(FILE *in)
520 {
521 char version[6];
522
523 memset(version, 0, sizeof(version));
524 fseek(in, 0, SEEK_SET);
525 /* Version */
526 if (fread(version, 4, 1, in) < 1) {
527 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
528 }
529 fseek(in, 0, SEEK_SET);
530 jp_logf(JP_LOG_DEBUG, "dat_check_if_dat_file(): version = [%c%c%d%d]\n", version[3],version[2],version[1],version[0]);
531 if ((version[3]=='D') && (version[2]=='B') &&
532 (version[1]==1) && (version[0]==0)) {
533 return DAT_DATEBOOK_FILE;
534 }
535 if ((version[3]=='A') && (version[2]=='B') &&
536 (version[1]==1) && (version[0]==0)) {
537 return DAT_ADDRESS_FILE;
538 }
539 if ((version[3]=='T') && (version[2]=='D') &&
540 (version[1]==1) && (version[0]==0)) {
541 return DAT_TODO_FILE;
542 }
543 if ((version[3]=='M') && (version[2]=='P') &&
544 (version[1]==1) && (version[0]==0)) {
545 return DAT_MEMO_FILE;
546 }
547 return EXIT_SUCCESS;
548 }
549
550 static int dat_read_header(FILE *in,
551 int expected_field_count,
552 char *schema,
553 struct CategoryAppInfo *ai,
554 int *schema_count, int *field_count, long *rec_count)
555 {
556 int i;
557 unsigned char filler[100];
558 char version[4];
559 char *PStr;
560 unsigned char str_long[4];
561
562 fseek(in, 0, SEEK_SET);
563
564 /* Version */
565 if (fread(version, 4, 1, in) < 1) {
566 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
567 }
568 jp_logf(JP_LOG_DEBUG, "version = [%c%c%d%d]\n", version[3],version[2],version[1],version[0]);
569
570 /* Full file path name */
571 get_CString(in, &PStr);
572 jp_logf(JP_LOG_DEBUG, "path:[%s]\n",PStr);
573 free(PStr);
574
575 /* Show Header */
576 get_CString(in, &PStr);
577 jp_logf(JP_LOG_DEBUG, "show header:[%s]\n",PStr);
578 free(PStr);
579
580 /* Next free category ID */
581 if (fread(filler, 4, 1, in) < 1) {
582 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
583 }
584
585 /* Categories */
586 get_categories(in, ai);
587 #ifdef JPILOT_DEBUG
588 for (i=0; i<16; i++) {
589 printf("%d [%s]\n", ai->ID[i], ai->name[i]);
590 }
591 #endif
592
593 /* Schema resource ID */
594 if (fread(filler, 4, 1, in) < 1) {
595 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
596 }
597 /* Schema fields per row */
598 if (fread(filler, 4, 1, in) < 1) {
599 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
600 }
601 *field_count=x86_long(filler);
602 if (*field_count != expected_field_count) {
603 jp_logf(JP_LOG_WARN, _("fields per row count != %d, unknown format\n"),
604 expected_field_count);
605 return EXIT_FAILURE;
606 }
607 /* Schema record ID position */
608 if (fread(filler, 4, 1, in) < 1) {
609 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
610 }
611 /* Schema record status position */
612 if (fread(filler, 4, 1, in) < 1) {
613 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
614 }
615 /* Schema placement position */
616 if (fread(filler, 4, 1, in) < 1) {
617 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
618 }
619 /* Schema fields count */
620 if (fread(filler, 2, 1, in) < 1) {
621 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
622 }
623 *field_count = x86_short(filler);
624 if (*field_count != expected_field_count) {
625 jp_logf(JP_LOG_WARN, _("field count != %d, unknown format\n"),
626 expected_field_count);
627 return EXIT_FAILURE;
628 }
629
630 /* Schema fields */
631 if (fread(filler, (*field_count)*2, 1, in) < 1) {
632 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
633 }
634 if (memcmp(filler, schema, (*field_count)*2)) {
635 jp_logf(JP_LOG_WARN, _("Unknown format, file has wrong schema\n"));
636 jp_logf(JP_LOG_WARN, _("File schema is:"));
637 for (i=0; i<(*field_count)*2; i++) {
638 jp_logf(JP_LOG_WARN, " %02d\n", (char)filler[i]);
639 }
640 jp_logf(JP_LOG_WARN, _("It should be:"));
641 for (i=0; i<(*field_count)*2; i++) {
642 jp_logf(JP_LOG_WARN, " %02d\n", (char)schema[i]);
643 }
644 return EXIT_FAILURE;
645 }
646
647 /* Get record count */
648 if (fread(str_long, 4, 1, in) < 1) {
649 jp_logf(JP_LOG_WARN, "fread failed %s %d\n", __FILE__, __LINE__);
650 }
651 if ((*field_count)) {
652 *rec_count = x86_long(str_long) / (*field_count);
653 }
654 #ifdef JPILOT_DEBUG
655 printf("Record Count = %ld\n", *rec_count);
656 #endif
657 return EXIT_SUCCESS;
658 }
659
660
661 int dat_get_appointments(FILE *in, AppointmentList **alist,
662 struct CategoryAppInfo *ai)
663 {
664 #ifdef JPILOT_DEBUG
665 struct field hack_f;
666 #endif
667 int ret, i, j;
668 struct field fa[28];
669 int schema_count, field_count;
670 long rec_count;
671 AppointmentList *temp_alist;
672 AppointmentList *last_alist;
673 time_t t;
674 struct tm *now;
675 /* Should be 1, 1, 1, 3, 1, 5, 1, 5, 6, 6, 1, 6, 1, 1, 8 */
676 char schema[30]={
677 DAT_TYPE_INTEGER,0,
678 DAT_TYPE_INTEGER,0,
679 DAT_TYPE_INTEGER,0,
680 DAT_TYPE_DATE,0,
681 DAT_TYPE_INTEGER,0,
682 DAT_TYPE_CSTRING,0,
683 DAT_TYPE_INTEGER,0,
684 DAT_TYPE_CSTRING,0,
685 DAT_TYPE_BOOLEAN,0,
686 DAT_TYPE_BOOLEAN,0,
687 DAT_TYPE_INTEGER,0,
688 DAT_TYPE_BOOLEAN,0,
689 DAT_TYPE_INTEGER,0,
690 DAT_TYPE_INTEGER,0,
691 DAT_TYPE_REPEAT,0
692 };
693 #ifdef JPILOT_DEBUG
694 char *rec_fields[]={
695 "Record ID",
696 "Status field",
697 "Position"
698 };
699 char *field_names[]={
700 "Start Time",
701 "End Time",
702 "Description",
703 "Duration",
704 "Note",
705 "Untimed",
706 "Private",
707 "Category",
708 "Alarm Set",
709 "Alarm Advance Units",
710 "Alarm Advance Type",
711 "Repeat Event"
712 };
713 #endif
714
715 jp_logf(JP_LOG_DEBUG, "dat_get_appointments\n");
716
717 if (!alist) return EXIT_SUCCESS;
718 *alist=NULL;
719
720 ret = dat_read_header(in, 15, schema, ai,
721 &schema_count, &field_count, &rec_count);
722
723 if (ret<0) return ret;
724
725 /* Get records */
726 last_alist=*alist;
727 #ifdef JPILOT_DEBUG
728 printf("---------- Records ----------\n");
729 #endif
730 for (i=0; i<rec_count; i++) {
731 temp_alist = malloc(sizeof(AppointmentList));
732 if (!temp_alist) {
733 jp_logf(JP_LOG_WARN, "dat_get_appointments(): %s\n", _("Out of memory"));
734 return i;
735 }
736 #ifdef JPILOT_DEBUG
737 printf("----- record %d -----\n", i+1);
738 #endif
739 memset(&(temp_alist->mappt.appt), 0, sizeof(temp_alist->mappt.appt));
740 temp_alist->next=NULL;
741 temp_alist->app_type=DATEBOOK;
742
743 /* Record ID */
744 /* Status Field */
745 /* Position */
746 for (j=0; j<3; j++) {
747 get_field(in, &(fa[j]));
748 #ifdef JPILOT_DEBUG
749 printf("rec field %d %s: ", j, rec_fields[j]); print_field(&(fa[j]));
750 #endif
751 if (fa[j].type!=schema[j*2]) {
752 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2], fa[j].type);
753 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
754 free(temp_alist);
755 return EXIT_FAILURE;
756 }
757 }
758 /* Get Fields */
759 for (j=0; j<12; j++) {
760 get_field(in, &(fa[j]));
761 #ifdef JPILOT_DEBUG
762 printf("field %d %s: ", j, field_names[j]); print_field(&(fa[j]));
763 if (j==1) {
764 hack_f.type=DAT_TYPE_DATE;
765 hack_f.date=fa[j].i;
766 printf(" "); print_field(&hack_f);
767 }
768 #endif
769 if (fa[j].type!=schema[j*2+6]) {
770 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2+6], fa[j].type);
771 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
772 free(temp_alist);
773 return EXIT_FAILURE;
774 }
775 if (fa[j].type==DAT_TYPE_REPEAT) {
776 get_repeat(in, &(temp_alist->mappt.appt));
777 }
778 }
779 /* Start Time */
780 t = fa[0].date;
781 now = localtime(&t);
782 memcpy(&(temp_alist->mappt.appt.begin), now, sizeof(struct tm));
783 /* End Time */
784 t = fa[1].i;
785 now = localtime(&t);
786 memcpy(&(temp_alist->mappt.appt.end), now, sizeof(struct tm));
787 /* Description */
788 if (fa[2].str) {
789 temp_alist->mappt.appt.description=fa[2].str;
790 } else {
791 temp_alist->mappt.appt.description=strdup("");
792 }
793 /* Duration */
794 /* what is duration? (repeatForever?) */
795
796 /* Note */
797 if (fa[4].str) {
798 temp_alist->mappt.appt.note=fa[4].str;
799 } else {
800 temp_alist->mappt.appt.note=strdup("");
801 }
802 /* Untimed */
803 temp_alist->mappt.appt.event=fa[5].i;
804 /* Private */
805 temp_alist->mappt.attrib = 0;
806 if (fa[6].i) {
807 temp_alist->mappt.attrib |= DAT_STATUS_PRIVATE;
808 }
809 /* Category */
810 temp_alist->mappt.unique_id = fa[7].i;
811 if (temp_alist->mappt.unique_id > 15) {
812 temp_alist->mappt.unique_id = 15;
813 }
814 if (temp_alist->mappt.unique_id < 0) {
815 temp_alist->mappt.unique_id = 0;
816 }
817 /* Alarm Set */
818 temp_alist->mappt.appt.alarm=fa[8].i;
819 /* Alarm Advance Units */
820 temp_alist->mappt.appt.advance=fa[9].i;
821 /* Alarm Advance Type */
822 temp_alist->mappt.appt.advanceUnits=fa[10].i;
823
824 /* Append onto the end of the list */
825 if (last_alist) {
826 last_alist->next=temp_alist;
827 last_alist=temp_alist;
828 } else {
829 last_alist=temp_alist;
830 *alist=last_alist;
831 }
832 }
833 return EXIT_SUCCESS;
834 }
835
836 int dat_get_addresses(FILE *in, AddressList **addrlist,
837 struct CategoryAppInfo *ai)
838 {
839 int ret, i, j, k;
840 struct field fa[28];
841 int schema_count, field_count;
842 long rec_count;
843 AddressList *temp_addrlist;
844 AddressList *last_addrlist;
845 int dat_order[19]={
846 0,1,3,5,7,9,11,13,14,15,16,17,18,2,22,23,24,25,19
847 };
848 /* Should be 1, 1, 1, 5, 5, 5, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5,
849 5, 5, 5, 5, 5, 5, 6, 1, 5, 5, 5, 5, 1 */
850 char schema[60]={
851 DAT_TYPE_INTEGER,0,
852 DAT_TYPE_INTEGER,0,
853 DAT_TYPE_INTEGER,0,
854 DAT_TYPE_CSTRING,0,
855 DAT_TYPE_CSTRING,0,
856 DAT_TYPE_CSTRING,0,
857 DAT_TYPE_CSTRING,0,
858 DAT_TYPE_INTEGER,0,
859 DAT_TYPE_CSTRING,0,
860 DAT_TYPE_INTEGER,0,
861 DAT_TYPE_CSTRING,0,
862 DAT_TYPE_INTEGER,0,
863 DAT_TYPE_CSTRING,0,
864 DAT_TYPE_INTEGER,0,
865 DAT_TYPE_CSTRING,0,
866 DAT_TYPE_INTEGER,0,
867 DAT_TYPE_CSTRING,0,
868 DAT_TYPE_CSTRING,0,
869 DAT_TYPE_CSTRING,0,
870 DAT_TYPE_CSTRING,0,
871 DAT_TYPE_CSTRING,0,
872 DAT_TYPE_CSTRING,0,
873 DAT_TYPE_CSTRING,0,
874 DAT_TYPE_BOOLEAN,0,
875 DAT_TYPE_INTEGER,0,
876 DAT_TYPE_CSTRING,0,
877 DAT_TYPE_CSTRING,0,
878 DAT_TYPE_CSTRING,0,
879 DAT_TYPE_CSTRING,0,
880 DAT_TYPE_INTEGER,0
881 };
882 #ifdef JPILOT_DEBUG
883 char *rec_fields[]={
884 "Record ID",
885 "Status field",
886 "Position"
887 };
888 char *field_names[]={
889 "Last Name",
890 "First Name",
891 "Title",
892 "Company",
893 "Phone1 Label",
894 "Phone1",
895 "Phone2 Label",
896 "Phone2",
897 "Phone3 Label",
898 "Phone3",
899 "Phone4 Label",
900 "Phone4",
901 "Phone5 Label",
902 "Phone5",
903 "Address",
904 "City",
905 "State",
906 "Zip",
907 "Country",
908 "Note",
909 "Private",
910 "Category",
911 "Custom1",
912 "Custom2",
913 "Custom3",
914 "Custom4",
915 "Display Phone"
916 };
917 #endif
918
919 jp_logf(JP_LOG_DEBUG, "dat_get_addresses\n");
920
921 if (!addrlist) return EXIT_SUCCESS;
922 *addrlist=NULL;
923
924 ret = dat_read_header(in, 30, schema, ai,
925 &schema_count, &field_count, &rec_count);
926
927 if (ret<0) return ret;
928
929 /* Get records */
930 last_addrlist=*addrlist;
931 #ifdef JPILOT_DEBUG
932 printf("---------- Records ----------\n");
933 #endif
934 for (i=0; i<rec_count; i++) {
935 temp_addrlist = malloc(sizeof(AddressList));
936 if (!temp_addrlist) {
937 jp_logf(JP_LOG_WARN, "dat_get_addresses(): %s\n", _("Out of memory"));
938 return i;
939 }
940 temp_addrlist->next=NULL;
941 temp_addrlist->app_type=ADDRESS;
942 #ifdef JPILOT_DEBUG
943 printf("----- record %d -----\n", i+1);
944 #endif
945 /* Record ID */
946 /* Status Field */
947 /* Position */
948 for (j=0; j<3; j++) {
949 get_field(in, &(fa[j]));
950 #ifdef JPILOT_DEBUG
951 printf("rec field %d %s: ", j, rec_fields[j]); print_field(&(fa[j]));
952 #endif
953 if (fa[j].type!=schema[j*2]) {
954 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2], fa[j].type);
955 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
956 free(temp_addrlist);
957 return EXIT_FAILURE;
958 }
959 }
960 /* Get Fields */
961 for (j=0; j<27; j++) {
962 get_field(in, &(fa[j]));
963 #ifdef JPILOT_DEBUG
964 printf("field %d %s: ", j, field_names[j]); print_field(&(fa[j]));
965 #endif
966 if (fa[j].type!=schema[j*2+6]) {
967 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2+6], fa[j].type);
968 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
969 free(temp_addrlist);
970 return EXIT_FAILURE;
971 }
972 }
973 for (k=0; k<19; k++) {
974 temp_addrlist->maddr.addr.entry[k]=fa[dat_order[k]].str;
975 }
976 temp_addrlist->maddr.addr.phoneLabel[0] = fa[4].i;
977 temp_addrlist->maddr.addr.phoneLabel[1] = fa[6].i;
978 temp_addrlist->maddr.addr.phoneLabel[2] = fa[8].i;
979 temp_addrlist->maddr.addr.phoneLabel[3] = fa[10].i;
980 temp_addrlist->maddr.addr.phoneLabel[4] = fa[12].i;
981 /* Private */
982 temp_addrlist->maddr.attrib = 0;
983 if (fa[20].i) {
984 temp_addrlist->maddr.attrib |= DAT_STATUS_PRIVATE;
985 }
986 /* Category */
987 temp_addrlist->maddr.unique_id = fa[21].i;
988 if (temp_addrlist->maddr.unique_id > 15) {
989 temp_addrlist->maddr.unique_id = 15;
990 }
991 if (temp_addrlist->maddr.unique_id < 0) {
992 temp_addrlist->maddr.unique_id = 0;
993 }
994 /* Show phone in list */
995 temp_addrlist->maddr.addr.showPhone = fa[26].i - 1;
996 for (k=0; k<19; k++) {
997 if (temp_addrlist->maddr.addr.entry[k]==NULL) {
998 temp_addrlist->maddr.addr.entry[k]=strdup("");
999 }
1000 }
1001 /* Append onto the end of the list */
1002 if (last_addrlist) {
1003 last_addrlist->next=temp_addrlist;
1004 last_addrlist=temp_addrlist;
1005 } else {
1006 last_addrlist=temp_addrlist;
1007 *addrlist=last_addrlist;
1008 }
1009 }
1010 return EXIT_SUCCESS;
1011 }
1012
1013 int dat_get_todos(FILE *in, ToDoList **todolist, struct CategoryAppInfo *ai)
1014 {
1015 int ret, i, j;
1016 struct field fa[10];
1017 int schema_count, field_count;
1018 long rec_count;
1019 time_t t;
1020 struct tm *now;
1021 ToDoList *temp_todolist;
1022 ToDoList *last_todolist;
1023 /* Should be 1, 1, 1, 5, 3, 6, 1, 6, 1, 5 */
1024 char schema[20]={
1025 DAT_TYPE_INTEGER,0,
1026 DAT_TYPE_INTEGER,0,
1027 DAT_TYPE_INTEGER,0,
1028 DAT_TYPE_CSTRING,0,
1029 DAT_TYPE_DATE,0,
1030 DAT_TYPE_BOOLEAN,0,
1031 DAT_TYPE_INTEGER,0,
1032 DAT_TYPE_BOOLEAN,0,
1033 DAT_TYPE_INTEGER,0,
1034 DAT_TYPE_CSTRING,0
1035 };
1036 #ifdef JPILOT_DEBUG
1037 char *rec_fields[]={
1038 "Record ID",
1039 "Status field",
1040 "Position"
1041 };
1042 char *field_names[]={
1043 "Description",
1044 "Due Date",
1045 "Completed",
1046 "Priority",
1047 "Private",
1048 "Category",
1049 "Note"
1050 };
1051 #endif
1052
1053 jp_logf(JP_LOG_DEBUG, "dat_get_todos\n");
1054
1055 if (!todolist) return EXIT_SUCCESS;
1056 *todolist=NULL;
1057
1058 ret = dat_read_header(in, 10, schema, ai,
1059 &schema_count, &field_count, &rec_count);
1060
1061 if (ret<0) return ret;
1062
1063 /* Get records */
1064 last_todolist=*todolist;
1065 #ifdef JPILOT_DEBUG
1066 printf("---------- Records ----------\n");
1067 #endif
1068 for (i=0; i<rec_count; i++) {
1069 temp_todolist = malloc(sizeof(ToDoList));
1070 if (!temp_todolist) {
1071 jp_logf(JP_LOG_WARN, "dat_get_todos(): %s\n", _("Out of memory"));
1072 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
1073 free(temp_todolist);
1074 return i;
1075 }
1076 temp_todolist->next=NULL;
1077 temp_todolist->app_type=TODO;
1078 #ifdef JPILOT_DEBUG
1079 printf("----- record %d -----\n", i+1);
1080 #endif
1081 /* Record ID */
1082 /* Status Field */
1083 /* Position */
1084 for (j=0; j<3; j++) {
1085 get_field(in, &(fa[j]));
1086 #ifdef JPILOT_DEBUG
1087 printf("rec field %d %s: ", j, rec_fields[j]); print_field(&(fa[j]));
1088 #endif
1089 if (fa[j].type!=schema[j*2]) {
1090 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2], fa[j].type);
1091 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
1092 free(temp_todolist);
1093 return EXIT_FAILURE;
1094 }
1095 }
1096 /* Get Fields */
1097 for (j=0; j<7; j++) {
1098 get_field(in, &(fa[j]));
1099 #ifdef JPILOT_DEBUG
1100 printf("field %d %s: ", j, field_names[j]); print_field(&(fa[j]));
1101 #endif
1102 if (fa[j].type!=schema[j*2+6]) {
1103 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2+6], fa[j].type);
1104 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
1105 free(temp_todolist);
1106 return EXIT_FAILURE;
1107 }
1108 }
1109 /* Description */
1110 if (fa[0].str) {
1111 temp_todolist->mtodo.todo.description=fa[0].str;
1112 } else {
1113 temp_todolist->mtodo.todo.description=strdup("");
1114 }
1115 /* Due Date */
1116 if (fa[1].date==0x749E77BF) {
1117 temp_todolist->mtodo.todo.indefinite=1;
1118 memset(&(temp_todolist->mtodo.todo.due), 0, sizeof(temp_todolist->mtodo.todo.due));
1119 } else {
1120 t = fa[1].date;
1121 now = localtime(&t);
1122 memcpy(&(temp_todolist->mtodo.todo.due), now, sizeof(struct tm));
1123 temp_todolist->mtodo.todo.indefinite=0;
1124 }
1125 /* Completed */
1126 temp_todolist->mtodo.todo.complete = (fa[2].i==0) ? 0 : 1;
1127 /* Priority */
1128 if (fa[3].i < 0) fa[3].i=0;
1129 if (fa[3].i > 5) fa[3].i=5;
1130 temp_todolist->mtodo.todo.priority = fa[3].i;
1131 /* Private */
1132 temp_todolist->mtodo.attrib = 0;
1133 if (fa[4].i) {
1134 temp_todolist->mtodo.attrib |= DAT_STATUS_PRIVATE;
1135 }
1136 /* Category */
1137 /* Normally the category would go into 4 bits of the attrib.
1138 * They jumbled the attrib bits, so to make things easy I'll put it
1139 * here.
1140 */
1141 if (fa[5].i < 0) fa[5].i=0;
1142 if (fa[5].i > 15) fa[5].i=15;
1143 temp_todolist->mtodo.unique_id = fa[5].i;
1144 /* Note */
1145 if (fa[6].str) {
1146 temp_todolist->mtodo.todo.note=fa[6].str;
1147 } else {
1148 temp_todolist->mtodo.todo.note=strdup("");
1149 }
1150 /* Append onto the end of the list */
1151 if (last_todolist) {
1152 last_todolist->next=temp_todolist;
1153 last_todolist=temp_todolist;
1154 } else {
1155 last_todolist=temp_todolist;
1156 *todolist=last_todolist;
1157 }
1158 }
1159
1160 return EXIT_SUCCESS;
1161 }
1162
1163 int dat_get_memos(FILE *in, MemoList **memolist, struct CategoryAppInfo *ai)
1164 {
1165 int ret, i, j;
1166 struct field fa[10];
1167 int schema_count, field_count;
1168 long rec_count;
1169 MemoList *temp_memolist;
1170 MemoList *last_memolist;
1171 char schema[12]={
1172 DAT_TYPE_INTEGER,0,
1173 DAT_TYPE_INTEGER,0,
1174 DAT_TYPE_INTEGER,0,
1175 DAT_TYPE_CSTRING,0,
1176 DAT_TYPE_BOOLEAN,0,
1177 DAT_TYPE_INTEGER,0
1178 };
1179 #ifdef JPILOT_DEBUG
1180 char *rec_fields[]={
1181 "Record ID",
1182 "Status field",
1183 "Position"
1184 };
1185 char *field_names[]={
1186 "Memo",
1187 "Private",
1188 "Category"
1189 };
1190 #endif
1191
1192 jp_logf(JP_LOG_DEBUG, "dat_get_memos\n");
1193
1194 if (!memolist) return EXIT_SUCCESS;
1195 *memolist=NULL;
1196
1197 ret = dat_read_header(in, 6, schema, ai,
1198 &schema_count, &field_count, &rec_count);
1199
1200 if (ret<0) return ret;
1201
1202 /* Get records */
1203 last_memolist=*memolist;
1204 #ifdef JPILOT_DEBUG
1205 printf("---------- Records ----------\n");
1206 #endif
1207 for (i=0; i<rec_count; i++) {
1208 temp_memolist = malloc(sizeof(MemoList));
1209 if (!temp_memolist) {
1210 jp_logf(JP_LOG_WARN, "dat_get_memos(): %s\n", _("Out of memory"));
1211 return i;
1212 }
1213 temp_memolist->next=NULL;
1214 temp_memolist->app_type=MEMO;
1215 #ifdef JPILOT_DEBUG
1216 printf("----- record %d -----\n", i+1);
1217 #endif
1218 /* Record ID */
1219 /* Status Field */
1220 /* Position */
1221 for (j=0; j<3; j++) {
1222 get_field(in, &(fa[j]));
1223 #ifdef JPILOT_DEBUG
1224 printf("rec field %d %s: ", j, rec_fields[j]); print_field(&(fa[j]));
1225 #endif
1226 if (fa[j].type!=schema[j*2]) {
1227 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2], fa[j].type);
1228 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
1229 free(temp_memolist);
1230 return EXIT_FAILURE;
1231 }
1232 }
1233 /* Get Fields */
1234 for (j=0; j<3; j++) {
1235 get_field(in, &(fa[j]));
1236 #ifdef JPILOT_DEBUG
1237 printf("field %d %s: ", j, field_names[j]); print_field(&(fa[j]));
1238 #endif
1239 if (fa[j].type!=schema[j*2+6]) {
1240 jp_logf(JP_LOG_WARN, _("%s:%d Record %d, field %d: Invalid type. Expected %d, found %d\n"), __FILE__, __LINE__, i+1, j+3, schema[j*2+6], fa[j].type);
1241 jp_logf(JP_LOG_WARN, _("read of file terminated\n"));
1242 free(temp_memolist);
1243 return EXIT_FAILURE;
1244 }
1245 }
1246 /* Memo */
1247 temp_memolist->mmemo.memo.text=fa[0].str;
1248 /* Private */
1249 temp_memolist->mmemo.attrib = 0;
1250 if (fa[1].i) {
1251 temp_memolist->mmemo.attrib |= DAT_STATUS_PRIVATE;
1252 }
1253 /* Category */
1254 /* Normally the category would go into 4 bits of the attrib.
1255 * They jumbled the attrib bits, so to make things easy I'll put it
1256 * here.
1257 */
1258 if (fa[2].i < 0) fa[2].i=0;
1259 if (fa[2].i > 15) fa[2].i=15;
1260 temp_memolist->mmemo.unique_id = fa[2].i;
1261 /* Append onto the end of the list */
1262
1263 if (last_memolist) {
1264 last_memolist->next=temp_memolist;
1265 last_memolist=temp_memolist;
1266 } else {
1267 last_memolist=temp_memolist;
1268 *memolist=last_memolist;
1269 }
1270 }
1271
1272 return EXIT_SUCCESS;
1273 }