aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--common.h3
-rw-r--r--libcontacts.h42
-rw-r--r--libcontacts_block_destroy.c10
-rw-r--r--libcontacts_contact_destroy.c1
-rw-r--r--libcontacts_format_contact.c26
-rw-r--r--libcontacts_parse_contact.c43
7 files changed, 122 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 33521e9..8d845fe 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ include $(CONFIGFILE)
OBJ =\
libcontacts_address_destroy.o\
libcontacts_birthday_destroy.o\
+ libcontacts_block_destroy.o\
libcontacts_chat_destroy.o\
libcontacts_contact_destroy.o\
libcontacts_email_destroy.o\
diff --git a/common.h b/common.h
index bf886cd..aa6a1b3 100644
--- a/common.h
+++ b/common.h
@@ -12,6 +12,9 @@
#include <unistd.h>
+#define TIME_MAX ((time_t)((1ULL << (8 * sizeof(time_t) - 1)) - 1ULL))
+
+
#define DESTROY_ALL(LIST, FUNC)\
do {\
void *destroy_all_temp__;\
diff --git a/libcontacts.h b/libcontacts.h
index cd65bf4..4a7373f 100644
--- a/libcontacts.h
+++ b/libcontacts.h
@@ -17,6 +17,36 @@ enum libcontacts_gender {
};
/**
+ * Block type for contact
+ */
+enum libcontacts_block_type {
+ LIBCONTACTS_SILENT, /* The contact is blocked blocked, the phone shall not call its owner's attention */
+ LIBCONTACTS_BLOCK_OFF, /* The contact is blocked, phone shall appear as turned off */
+ LIBCONTACTS_BLOCK_BUSY, /* The contact is blocked, phone shall appear as turned busy */
+ LIBCONTACTS_BLOCK_IGNORE /* The contact is blocked, phone shall appear as on but with no one answering */
+};
+
+/**
+ * Block for contact
+ */
+struct libcontacts_block {
+ /**
+ * The service the block is applied to,
+ * must be begin with a dot, except if
+ * it is:
+ * - ".call" Telephone calls
+ * - ".sms" SMS, MMS, and similar
+ * - ".global" Block everywhere (least priorities)
+ */
+ char *service;
+ int explicit; /* Whether to make an explicit block if possible */
+ enum libcontacts_block_type shadow_block; /* How block shall appear unless explicit */
+ time_t soft_unblock; /* When (positive) to ask whether to unblock, 0 if never */
+ time_t hard_unblock; /* When (positive) to unblock, 0 if never */
+ char **unrecognised_data; /* Data not recognised by the library */
+};
+
+/**
* Organisation information for contact
*/
struct libcontacts_organisation {
@@ -84,7 +114,7 @@ struct libcontacts_site {
*/
struct libcontacts_chat {
char *context; /* Work account (which job?)? Personal account? … */
- char *service; /* What service is the account */
+ char *service; /* What service is the account, must not begin with a dot */
char *address; /* What is the name/address/number of the account */
char **unrecognised_data; /* Data not recognised by the library */
};
@@ -107,8 +137,8 @@ struct libcontacts_contact {
* The ID of the contact, used to select filename
*
* Must not begin with a dot, except if it is:
- * ".me" - The user himself.
- * ".nobody" - Unused data, such as created groups without any members.
+ * - ".me" The user himself.
+ * - ".nobody" Unused data, such as created groups without any members.
* Additionally, it must not end with ~ or contain an /,
* and it should be short enough for a filename
*/
@@ -161,6 +191,11 @@ struct libcontacts_contact {
char *notes;
/**
+ * Block information for contact
+ */
+ struct libcontacts_block **blocks;
+
+ /**
* Organisation information for contact
*/
struct libcontacts_organisation **organisations;
@@ -234,6 +269,7 @@ char *libcontacts_get_path(const char *, const struct passwd *);
int libcontacts_parse_contact(char *, struct libcontacts_contact *); /* does not load .id, not stored in file, but is the filename */
int libcontacts_format_contact(const struct libcontacts_contact *, char **);
+void libcontacts_block_destroy(struct libcontacts_block *);
void libcontacts_organisation_destroy(struct libcontacts_organisation *);
void libcontacts_email_destroy(struct libcontacts_email *);
void libcontacts_pgpkey_destroy(struct libcontacts_pgpkey *);
diff --git a/libcontacts_block_destroy.c b/libcontacts_block_destroy.c
new file mode 100644
index 0000000..1298aca
--- /dev/null
+++ b/libcontacts_block_destroy.c
@@ -0,0 +1,10 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+void
+libcontacts_block_destroy(struct libcontacts_block *this)
+{
+ free(this->service);
+ DESTROY_ALL(this->unrecognised_data, free);
+}
diff --git a/libcontacts_contact_destroy.c b/libcontacts_contact_destroy.c
index ef208d5..974473d 100644
--- a/libcontacts_contact_destroy.c
+++ b/libcontacts_contact_destroy.c
@@ -13,6 +13,7 @@ libcontacts_contact_destroy(struct libcontacts_contact *this)
DESTROY_ALL(this->photos, free);
DESTROY_ALL(this->groups, free);
free(this->notes);
+ DESTROY_ALL(this->blocks, libcontacts_block_destroy);
DESTROY_ALL(this->organisations, libcontacts_organisation_destroy);
DESTROY_ALL(this->emails, libcontacts_email_destroy);
DESTROY_ALL(this->pgpkeys, libcontacts_pgpkey_destroy);
diff --git a/libcontacts_format_contact.c b/libcontacts_format_contact.c
index 1752026..8be830e 100644
--- a/libcontacts_format_contact.c
+++ b/libcontacts_format_contact.c
@@ -9,6 +9,7 @@ libcontacts_format_contact(const struct libcontacts_contact *contact, char **dat
size_t siz = 0;
char **list, *p, *q;
const char *suffix;
+ struct libcontacts_block **blocks, *block;
struct libcontacts_organisation **organisations, *organisation;
struct libcontacts_email **emails, *email;
struct libcontacts_pgpkey **pgpkeys, *pgpkey;
@@ -51,11 +52,34 @@ libcontacts_format_contact(const struct libcontacts_contact *contact, char **dat
}
}
+ if ((blocks = contact->blocks)) {
+ for (; (block = *blocks); blocks++) {
+ fprintf(fp, "BLOCK:\n");
+ if (block->service)
+ fprintf(fp, "\tSRV %s\n", block->service);
+ if (block->explicit)
+ fprintf(fp, "\tEXPLICIT\n");
+ if (block->soft_unblock > 0)
+ fprintf(fp, "\tASK %ji\n", block->soft_unblock);
+ if (block->hard_unblock > 0)
+ fprintf(fp, "\tREMOVE %ji\n", block->hard_unblock);
+ if (block->shadow_block == LIBCONTACTS_BLOCK_OFF)
+ fprintf(fp, "\tOFF\n");
+ else if (block->shadow_block == LIBCONTACTS_BLOCK_BUSY)
+ fprintf(fp, "\tBUSY\n");
+ else if (block->shadow_block == LIBCONTACTS_BLOCK_IGNORE)
+ fprintf(fp, "\tIGNORE\n");
+ if ((list = block->unrecognised_data))
+ for (; *list; list++)
+ fprintf(fp, "\t%s\n", *list);
+ }
+ }
+
if ((organisations = contact->organisations)) {
for (; (organisation = *organisations); organisations++) {
fprintf(fp, "ORG:\n");
if (organisation->organisation)
- fprintf(fp, "\tORG %s\n", *organisation->organisation);
+ fprintf(fp, "\tORG %s\n", organisation->organisation);
if (organisation->title)
fprintf(fp, "\tTITLE %s\n", organisation->title);
if ((list = organisation->unrecognised_data))
diff --git a/libcontacts_parse_contact.c b/libcontacts_parse_contact.c
index da39432..a81a744 100644
--- a/libcontacts_parse_contact.c
+++ b/libcontacts_parse_contact.c
@@ -2,6 +2,22 @@
#include "common.h"
+static time_t
+gettime(const char *data)
+{
+ time_t ret = 0;
+ if (*data > '1' || '9' > *data)
+ return 0;
+ for (; isdigit(*data); data++) {
+ if (ret > (TIME_MAX - (*data & 15)) / 10)
+ return 0;
+ ret = ret * 10 + (*data & 15);
+ }
+ if (*data)
+ return 0;
+ return ret;
+}
+
static char *
getstr(char *data)
{
@@ -169,6 +185,7 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact)
char *p, *q;
size_t i;
+ time_t t;
void *temp;
int state = 0;
@@ -358,6 +375,32 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact)
}
break;
+ } else if (!strcmp(p, "BLOCK:")) {
+ ADD(contact->blocks);
+ state = 8;
+ break;
+ case 8:
+ if (TEST(unindent(p), "SRV") && !contact->blocks[i]->service) {
+ if (!(contact->blocks[i]->service = strdup(getstr(p))))
+ goto fail;
+ } else if (!strcmp(p, "OFF") && !contact->blocks[i]->shadow_block) {
+ contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_OFF;
+ } else if (!strcmp(p, "BUSY") && !contact->blocks[i]->shadow_block) {
+ contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_BUSY;
+ } else if (!strcmp(p, "IGNORE") && !contact->blocks[i]->shadow_block) {
+ contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_IGNORE;
+ } else if (!strcmp(p, "EXPLICIT")) {
+ contact->blocks[i]->explicit = 1;
+ } else if (TEST(unindent(p), "ASK") && !contact->blocks[i]->soft_unblock && (t = gettime(p))) {
+ contact->blocks[i]->soft_unblock = t;
+ } else if (TEST(unindent(p), "REMOVE") && !contact->blocks[i]->hard_unblock && (t = gettime(p))) {
+ contact->blocks[i]->hard_unblock = t;
+ } else {
+ if (addstr(&contact->organisations[i]->unrecognised_data, getstr(p)))
+ goto fail;
+ }
+ break;
+
} else if (TEST(p, "BIRTH") && !contact->birthday) {
contact->birthday = malloc(sizeof(*contact->birthday));
if (!contact->birthday)