diff options
Diffstat (limited to 'libcontacts_parse_contact.c')
-rw-r--r-- | libcontacts_parse_contact.c | 101 |
1 files changed, 53 insertions, 48 deletions
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; |