diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | common.h | 1 | ||||
-rw-r--r-- | libcontacts.h | 37 | ||||
-rw-r--r-- | libcontacts_contact_destroy.c | 1 | ||||
-rw-r--r-- | libcontacts_format_contact.c | 27 | ||||
-rw-r--r-- | libcontacts_parse_contact.c | 101 |
6 files changed, 105 insertions, 63 deletions
@@ -3,3 +3,4 @@ Add man pages Add readme Add tests Add cache (only number->ids, id->photos, number->photos) +Add handle different calendars @@ -6,6 +6,7 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/libcontacts.h b/libcontacts.h index 4a7373f..bae5fc6 100644 --- a/libcontacts.h +++ b/libcontacts.h @@ -123,9 +123,35 @@ struct libcontacts_chat { * Birthday of contact */ struct libcontacts_birthday { - unsigned int year; /* asis, 0 for unknown */ - unsigned char month; /* january = 1, 0 for unknown */ - unsigned char day; /* asis, 0 for unknown */ + unsigned int year; /* asis, 0 for unknown */ + unsigned char month; /* january = 1, 0 for unknown */ + unsigned char day; /* asis, 0 for unknown */ + + /** + * This is applicable only if the birthday + * is on a leap day. One non-leap years, a + * birthday that occurs on a leap day is + * observed the day after the leap day had + * it existed; but if this flag is set, the + * person observes his birthday the day + * before instead. + * + * (Even if it is not true (as it wasn't in + * the past), the leap day is treated as if at + * the end of the month, for example a person + * born 1970-02-27, would celebrate his birthday + * on 1980-02-27, not on 1980-02-28; similarly, + * person born 1980-02-27 would celebrate his + * birthday on 1989-02-27, not on 1989-02-26.) + * + * For example, if a person is born 2000-02-29, + * his birthday is observed 2011-03-01, but if + * this flag is set, he observes it on 2011-02-28 + * instead. + */ + unsigned char before_on_common; + + char **unrecognised_data; /* Data not recognised by the library */ }; @@ -160,6 +186,11 @@ struct libcontacts_contact { char *last_name; /** + * The full name of the contact + */ + char *full_name; + + /** * Nick name of the contact, if any */ char *nickname; diff --git a/libcontacts_contact_destroy.c b/libcontacts_contact_destroy.c index 974473d..70d1335 100644 --- a/libcontacts_contact_destroy.c +++ b/libcontacts_contact_destroy.c @@ -9,6 +9,7 @@ libcontacts_contact_destroy(struct libcontacts_contact *this) free(this->name); free(this->first_name); free(this->last_name); + free(this->full_name); free(this->nickname); DESTROY_ALL(this->photos, free); DESTROY_ALL(this->groups, free); diff --git a/libcontacts_format_contact.c b/libcontacts_format_contact.c index 9a20fcf..002dd4a 100644 --- a/libcontacts_format_contact.c +++ b/libcontacts_format_contact.c @@ -32,6 +32,9 @@ libcontacts_format_contact(const struct libcontacts_contact *contact, char **dat if (contact->last_name) fprintf(fp, "LNAME %s\n", contact->last_name); + if (contact->full_name) + fprintf(fp, "FLNAME %s\n", contact->full_name); + if (contact->nickname) fprintf(fp, "NICK %s\n", contact->nickname); @@ -183,18 +186,18 @@ libcontacts_format_contact(const struct libcontacts_contact *contact, char **dat } if (contact->birthday) { - if (contact->birthday->year && contact->birthday->day) { - fprintf(fp, "BIRTH %04i-%02i-%02i\n", - contact->birthday->year, contact->birthday->month, contact->birthday->day); - } else if (contact->birthday->year && contact->birthday->month) { - fprintf(fp, "BIRTH %04i-%02i\n", contact->birthday->year, contact->birthday->month); - } else if (contact->birthday->year) { - fprintf(fp, "BIRTH %04i\n", contact->birthday->year); - } else if (contact->birthday->day) { - fprintf(fp, "BIRTH %02i-%02i\n", contact->birthday->month, contact->birthday->day); - } else if (contact->birthday->month) { - fprintf(fp, "BIRTH %02i\n", contact->birthday->month); - } + fprintf(fp, "BIRTH:\n"); + if (contact->birthday->year) + fprintf(fp, "YEAR %u\n", contact->birthday->year); + if (contact->birthday->month) + fprintf(fp, "MONTH %u\n", (unsigned int)contact->birthday->month); + if (contact->birthday->day) + fprintf(fp, "DAY %u\n", (unsigned int)contact->birthday->day); + if (contact->birthday->before_on_common) + fprintf(fp, "EARLY\n"); + if ((list = contact->birthday->unrecognised_data)) + for (; *list; list++) + fprintf(fp, "\t%s\n", *list); } if (contact->in_case_of_emergency) diff --git a/libcontacts_parse_contact.c b/libcontacts_parse_contact.c index a81a744..2d7ae95 100644 --- a/libcontacts_parse_contact.c +++ b/libcontacts_parse_contact.c @@ -18,6 +18,38 @@ gettime(const char *data) return ret; } +static unsigned int +getposuint(const char *data) +{ + unsigned int ret = 0; + if (*data > '1' || '9' > *data) + return 0; + for (; isdigit(*data); data++) { + if (ret > (UINT_MAX - (*data & 15)) / 10) + return 0; + ret = ret * 10 + (*data & 15); + } + if (*data) + return 0; + return ret; +} + +static unsigned char +getposuchar(const char *data) +{ + unsigned char ret = 0; + if (*data > '1' || '9' > *data) + return 0; + for (; isdigit(*data); data++) { + if (ret > (UCHAR_MAX - (*data & 15)) / 10) + return 0; + ret = ret * 10 + (*data & 15); + } + if (*data) + return 0; + return ret; +} + static char * getstr(char *data) { @@ -120,49 +152,6 @@ bad: return -1; } -static int -parse_birth(char *s, struct libcontacts_birthday *birth) -{ - birth->year = 0; - birth->month = 0; - birth->day = 0; - - if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])) { - birth->year = (s[0] & 15) * 1000; - birth->year += (s[1] & 15) * 100; - birth->year += (s[2] & 15) * 10; - birth->year += (s[3] & 15) * 1; - if (s[4] == '-') - s = &s[5]; - else if (s[4]) - goto bad; - else - return 0; - } - - if (isdigit(s[0]) && isdigit(s[1])) { - birth->month = (s[0] & 15) * 10; - birth->month += (s[1] & 15) * 1; - if (s[2] == '-') - s = &s[3]; - else if (s[2]) - goto bad; - else - return 0; - } - - if (isdigit(s[0]) && isdigit(s[1])) { - birth->day = (s[0] & 15) * 10; - birth->day += (s[1] & 15) * 1; - if (!s[2]) - return 0; - } - -bad: - errno = EINVAL; - return -1; -} - int libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) @@ -188,6 +177,8 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) time_t t; void *temp; int state = 0; + unsigned int u; + unsigned char uc; memset(contact, 0, sizeof(*contact)); @@ -212,6 +203,10 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) if (!(contact->last_name = strdup(getstr(p)))) goto fail; + } else if (TEST(p, "FLNAME") && !contact->full_name) { + if (!(contact->full_name = strdup(getstr(p)))) + goto fail; + } else if (TEST(p, "NICK") && !contact->nickname) { if (!(contact->nickname = strdup(getstr(p)))) goto fail; @@ -401,16 +396,26 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) } break; - } else if (TEST(p, "BIRTH") && !contact->birthday) { + } else if (!strcmp(p, "BIRTH:") && !contact->birthday) { contact->birthday = malloc(sizeof(*contact->birthday)); if (!contact->birthday) goto fail; - if (!parse_birth(getstr(p), contact->birthday)) { - free(contact->birthday); - contact->birthday = NULL; - if (addstr(&contact->unrecognised_data, getstr(p))) + state = 9; + break; + case 9: + if (TEST(unindent(p), "YEAR") && !contact->birthday->year && (u = getposuint(p))) { + contact->birthday->year = u; + } else if (TEST(unindent(p), "MONTH") && !contact->birthday->month && (uc = getposuchar(p))) { + contact->birthday->month = uc; + } else if (TEST(unindent(p), "DAY") && !contact->birthday->day && (uc = getposuchar(p))) { + contact->birthday->day = uc; + } else if (!strcmp(p, "EARLY")) { + contact->birthday->before_on_common = 1; + } else { + if (addstr(&contact->birthday->unrecognised_data, getstr(p))) goto fail; } + break; } else if (!strcmp(p, "ICE")) { contact->in_case_of_emergency = 1; |