aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--common.h1
-rw-r--r--libcontacts.h37
-rw-r--r--libcontacts_contact_destroy.c1
-rw-r--r--libcontacts_format_contact.c27
-rw-r--r--libcontacts_parse_contact.c101
6 files changed, 105 insertions, 63 deletions
diff --git a/TODO b/TODO
index f7d9e7a..1084a8d 100644
--- a/TODO
+++ b/TODO
@@ -3,3 +3,4 @@ Add man pages
Add readme
Add tests
Add cache (only number->ids, id->photos, number->photos)
+Add handle different calendars
diff --git a/common.h b/common.h
index aa6a1b3..d74dde5 100644
--- a/common.h
+++ b/common.h
@@ -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;