aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-06 01:42:13 +0200
committerMattias Andrée <maandree@kth.se>2021-04-06 01:42:13 +0200
commitf2ee15e4ec3a02e4be6a522bb7b276bdf5703301 (patch)
treebfc43bf5dc1b2d8fec9a1c68c8c8e140f696f09f
parentm (diff)
downloadcontacts-f2ee15e4ec3a02e4be6a522bb7b276bdf5703301.tar.gz
contacts-f2ee15e4ec3a02e4be6a522bb7b276bdf5703301.tar.bz2
contacts-f2ee15e4ec3a02e4be6a522bb7b276bdf5703301.tar.xz
m + add block utils
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--.gitignore3
-rw-r--r--Makefile14
-rw-r--r--TODO5
-rw-r--r--common-address.c6
-rw-r--r--common.h2
-rw-r--r--get-contact-blocks.c177
-rw-r--r--set-contact-blocks.c164
-rw-r--r--unblock-contact.c124
8 files changed, 489 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
index af6aaab..69e74f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@
/find-contact-by-site
/get-contact-addresses
/get-contact-birthday
+/get-contact-blocks
/get-contact-chats
/get-contact-emails
/get-contact-file
@@ -45,6 +46,7 @@
/remove-contact
/set-contact-addresses
/set-contact-birthday
+/set-contact-blocks
/set-contact-chats
/set-contact-emails
/set-contact-gender
@@ -57,3 +59,4 @@
/set-contact-pgpkeys
/set-contact-photos
/set-contact-sites
+/unblock-contact
diff --git a/Makefile b/Makefile
index 2e3cb7f..f71def1 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@ BIN =\
find-contact-by-site\
get-contact-addresses\
get-contact-birthday\
+ get-contact-blocks\
get-contact-chats\
get-contact-emails\
get-contact-file\
@@ -45,6 +46,7 @@ BIN =\
remove-contact\
set-contact-addresses\
set-contact-birthday\
+ set-contact-blocks\
set-contact-chats\
set-contact-emails\
set-contact-gender\
@@ -56,7 +58,8 @@ BIN =\
set-contact-organisations\
set-contact-pgpkeys\
set-contact-photos\
- set-contact-sites
+ set-contact-sites\
+ unblock-contact
HDR =\
common.h
@@ -123,6 +126,9 @@ get-contact-addresses: get-contact-addresses.o common-address.o
get-contact-birthday: get-contact-birthday.o common-birthday.o
$(CC) -o $@ $@.o common-birthday.o $(LDFLAGS)
+get-contact-blocks: get-contact-blocks.o
+ $(CC) -o $@ $@.o $(LDFLAGS)
+
get-contact-chats: get-contact-chats.o
$(CC) -o $@ $@.o $(LDFLAGS)
@@ -195,6 +201,9 @@ set-contact-addresses: set-contact-addresses.o common-address.o
set-contact-birthday: set-contact-birthday.o
$(CC) -o $@ $@.o $(LDFLAGS)
+set-contact-blocks: set-contact-blocks.o
+ $(CC) -o $@ $@.o $(LDFLAGS)
+
set-contact-chats: set-contact-chats.o
$(CC) -o $@ $@.o $(LDFLAGS)
@@ -231,6 +240,9 @@ set-contact-photos: set-contact-photos.o
set-contact-sites: set-contact-sites.o
$(CC) -o $@ $@.o $(LDFLAGS)
+unblock-contact: unblock-contact.o
+ $(CC) -o $@ $@.o $(LDFLAGS)
+
uninstall:
-cd -- "$(DESTDIR)$(PREFIX)/bin" && rm -f -- $(BIN)
-rm -f -- "$(DESTDIR)$(PREFIX)/lib/contacts"
diff --git a/TODO b/TODO
index 90e03e9..a334e06 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-Add tools for .blocks
+update list-contacts to handle block status
Test find-contact-by-chat
Test find-contact-by-email
@@ -7,6 +7,7 @@ Test find-contact-by-organisation
Test find-contact-by-pgpkey
Test find-contact-by-photo
Test find-contact-by-site
+Test get-contact-blocks
Test get-contact-chats
Test get-contact-emails
Test get-contact-numbers
@@ -19,6 +20,7 @@ Test list-contact-organisations
Test list-organisation-contacts
Test set-contact-addresses
Test set-contact-birthday
+Test set-contact-blocks
Test set-contact-chats
Test set-contact-emails
Test set-contact-groups
@@ -28,6 +30,7 @@ Test set-contact-organisations
Test set-contact-pgpkeys
Test set-contact-photos
Test set-contact-sites
+Test unblock-contact
Add ability to filter on unset values in entries
Add ability to remove values in entries
Add man pages
diff --git a/common-address.c b/common-address.c
index 2f66208..c8dbf7e 100644
--- a/common-address.c
+++ b/common-address.c
@@ -3,7 +3,7 @@
int
-parse_coord(char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max)
+parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max)
{
int withsign = 0, neg;
long int tmp;
@@ -22,7 +22,7 @@ parse_coord(char *s, double *lat, double *lat_min, double *lat_max, double *lon,
s = &s[withsign];
tmp = 0;
if (isdigit(s[withsign])) {
- tmp = strtol(s, &s, 0);
+ tmp = strtol(s, (void *)&s, 0);
if (errno || tmp > INT_MAX)
return -1;
}
@@ -61,7 +61,7 @@ parse_coord(char *s, double *lat, double *lat_min, double *lat_max, double *lon,
s = &s[withsign];
tmp = 0;
if (isdigit(s[withsign])) {
- tmp = strtol(s, &s, 0);
+ tmp = strtol(s, (void *)&s, 0);
if (errno || tmp > INT_MAX)
return -1;
}
diff --git a/common.h b/common.h
index a230e55..6aecf6c 100644
--- a/common.h
+++ b/common.h
@@ -24,4 +24,4 @@ void print_birthdate(struct libcontacts_birthday *bday, const struct tm *now);
void print_birthday(struct libcontacts_birthday *bday, const struct tm *now);
/* common-address.c */
-int parse_coord(char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max);
+int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max);
diff --git a/get-contact-blocks.c b/get-contact-blocks.c
new file mode 100644
index 0000000..63dc713
--- /dev/null
+++ b/get-contact-blocks.c
@@ -0,0 +1,177 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a ask-at] [-s service] [-t type] [-u unblock-at] [-y style] [-ASTUY] contact-id ...");
+
+
+int
+main(int argc, char *argv[])
+{
+ int display_srv = 0, display_type = 0, display_style = 0;
+ int display_ask = 0, display_ublk = 0, explicit = 0;
+ enum libcontacts_block_type style = 0;
+ time_t soft_unblock = 0, hard_unblock = 0;
+ const char *lookup_srv = NULL, *lookup_type = NULL, *lookup_style = NULL;
+ const char *lookup_ask = NULL, *lookup_ublk = NULL;
+ char *p;
+ struct passwd *user;
+ struct libcontacts_contact contact;
+ struct libcontacts_block **blocks, *block;
+ int ret = 0;
+ size_t i;
+
+ errno = 0;
+
+ ARGBEGIN {
+ case 's':
+ if (lookup_srv)
+ usage();
+ lookup_srv = ARG();
+ break;
+ case 't':
+ if (lookup_type)
+ usage();
+ lookup_type = ARG();
+ break;
+ case 'y':
+ if (lookup_style)
+ usage();
+ lookup_style = ARG();
+ break;
+ case 'a':
+ if (lookup_ask)
+ usage();
+ lookup_ask = ARG();
+ if (!isdigit(*lookup_ask))
+ usage();
+ soft_unblock = (time_t)strtoumax(lookup_ask, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 'u':
+ if (lookup_ublk)
+ usage();
+ lookup_ublk = ARG();
+ if (!isdigit(*lookup_ublk))
+ usage();
+ hard_unblock = (time_t)strtoumax(lookup_ublk, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 'S':
+ display_srv = 1;
+ break;
+ case 'T':
+ display_type = 1;
+ break;
+ case 'Y':
+ display_style = 1;
+ break;
+ case 'A':
+ display_ask = 1;
+ break;
+ case 'U':
+ display_ublk = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!argc)
+ usage();
+
+ for (i = 0; argv[i]; i++)
+ if (!*argv[i] || strchr(argv[i], '/'))
+ usage();
+
+ if (lookup_type) {
+ if (!strcmp(lookup_type, "explicit"))
+ explicit = 1;
+ else if (!strcmp(lookup_type, "shadow"))
+ explicit = 0;
+ else
+ eprintf("value of -t shall be either \"explicit\" or \"shadow\"\n");
+ }
+
+ if (lookup_style) {
+ if (!strcmp(lookup_style, "silent"))
+ style = LIBCONTACTS_SILENT;
+ else if (!strcmp(lookup_style, "as-off"))
+ style = LIBCONTACTS_BLOCK_OFF;
+ else if (!strcmp(lookup_style, "as-busy"))
+ style = LIBCONTACTS_BLOCK_BUSY;
+ else if (!strcmp(lookup_style, "ignore"))
+ style = LIBCONTACTS_BLOCK_IGNORE;
+ else
+ eprintf("value of -y shall be either \"silent\", \"as-off\", \"as-busy\", or \"ignore\"\n");
+ }
+
+ if (!display_srv && !display_type && !display_style && !display_ask && !display_ublk) {
+ display_srv = !lookup_srv;
+ display_type = !lookup_type;
+ display_style = !lookup_style;
+ display_ask = !lookup_ask;
+ display_ublk = !lookup_ublk;
+ if (!display_srv && !display_type && !display_style && !display_ask && !display_ublk)
+ display_srv = display_type = display_style = display_ask = display_ublk = 1;
+ }
+
+ errno = 0;
+ user = getpwuid(getuid());
+ if (!user)
+ eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");
+
+ for (; *argv; argv++) {
+ if (libcontacts_load_contact(*argv, &contact, user)) {
+ weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted");
+ ret = 1;
+ continue;
+ }
+ if ((blocks = contact.blocks)) {
+ for (; (block = *blocks); blocks++) {
+ if (lookup_srv && strcmpnul(block->service, lookup_srv))
+ continue;
+ if (lookup_type && block->explicit != explicit)
+ continue;
+ if (lookup_style && block->shadow_block != style)
+ continue;
+ if (lookup_ask && block->soft_unblock != soft_unblock)
+ continue;
+ if (lookup_ublk && block->hard_unblock != hard_unblock)
+ continue;
+ if (argc > 1)
+ printf("%s: ", *argv);
+ if (display_srv) {
+ printf("%s%s", block->service, display_type + display_style +
+ display_ask + display_ublk ? "; " : "\n");
+ }
+ if (display_type) {
+ printf("%s%s", block->explicit ? "explicit" : "shadow",
+ display_style + display_ask + display_ublk ? "; " : "\n");
+ }
+ if (display_style) {
+ if (block->shadow_block == LIBCONTACTS_SILENT)
+ printf("silent");
+ else if (block->shadow_block == LIBCONTACTS_BLOCK_OFF)
+ printf("as-off");
+ else if (block->shadow_block == LIBCONTACTS_BLOCK_BUSY)
+ printf("as-busy");
+ else if (block->shadow_block == LIBCONTACTS_BLOCK_IGNORE)
+ printf("ignore");
+ else
+ printf("???");
+ printf("%s", display_ask + display_ublk ? "; " : "\n");
+ }
+ if (display_ask)
+ printf("%ju%s", (uintmax_t)block->soft_unblock, display_ublk ? "; " : "\n");
+ if (display_ublk)
+ printf("%ju\n", (uintmax_t)block->hard_unblock);
+ }
+ }
+ libcontacts_contact_destroy(&contact);
+ }
+
+ if (fflush(stdout) || ferror(stdout) || fclose(stdout))
+ eprintf("printf:");
+ return ret;
+}
diff --git a/set-contact-blocks.c b/set-contact-blocks.c
new file mode 100644
index 0000000..31e6626
--- /dev/null
+++ b/set-contact-blocks.c
@@ -0,0 +1,164 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a ask-at | -A ask-at] [-s service | -S service] [-t type | -T type] "
+ "[-u unblock-at | -U unblock-at] [-y style | -Y style] contact-id");
+
+
+int
+main(int argc, char *argv[])
+{
+ int edit_srv = 0, edit_type = 0, edit_style = 0, edit_ask = 0, edit_ublk = 0;
+ int edit = 0, explicit = 1;
+ enum libcontacts_block_type shadow_block = LIBCONTACTS_BLOCK_IGNORE;
+ time_t soft_unblock = 0, hard_unblock = 0;
+ const char *srv = NULL, *type = NULL, *style = NULL, *ask = NULL, *ublk = NULL;
+ struct passwd *user;
+ struct libcontacts_contact contact;
+ char *p;
+ size_t i;
+
+ ARGBEGIN {
+ case 'A':
+ edit_ask = 1;
+ edit = 1;
+ /* fall through */
+ case 'a':
+ if (ask)
+ usage();
+ ask = ARG();
+ if (!isdigit(*ask))
+ usage();
+ soft_unblock = (time_t)strtoumax(ask, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 'S':
+ edit_srv = 1;
+ edit = 1;
+ /* fall through */
+ case 's':
+ if (srv)
+ usage();
+ srv = ARG();
+ break;
+ case 'T':
+ edit_type = 1;
+ edit = 1;
+ /* fall through */
+ case 't':
+ if (type)
+ usage();
+ type = ARG();
+ break;
+ case 'U':
+ edit_ublk = 1;
+ edit = 1;
+ /* fall through */
+ case 'u':
+ if (ublk)
+ usage();
+ ublk = ARG();
+ if (!isdigit(*ublk))
+ usage();
+ hard_unblock = (time_t)strtoumax(ublk, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 'Y':
+ edit_style = 1;
+ edit = 1;
+ /* fall through */
+ case 'y':
+ if (style)
+ usage();
+ style = ARG();
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if ((!srv || edit_srv) && (!type || edit_type) && (!style || edit_style) &&
+ (!ask || edit_ask) && (!ublk || edit_ublk))
+ edit = 0;
+
+ if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
+ usage();
+
+ if (type) {
+ if (!strcmp(type, "explicit"))
+ explicit = 1;
+ else if (!strcmp(type, "shadow"))
+ explicit = 0;
+ else
+ eprintf("value of -%c shall be either \"explicit\" or \"shadow\"\n", edit_type ? 'T' : 't');
+ }
+
+ if (style) {
+ if (!strcmp(style, "silent"))
+ shadow_block = LIBCONTACTS_SILENT;
+ else if (!strcmp(style, "as-off"))
+ shadow_block = LIBCONTACTS_BLOCK_OFF;
+ else if (!strcmp(style, "as-busy"))
+ shadow_block = LIBCONTACTS_BLOCK_BUSY;
+ else if (!strcmp(style, "ignore"))
+ shadow_block = LIBCONTACTS_BLOCK_IGNORE;
+ else if (edit_style)
+ eprintf("value of -Y shall be either \"silent\", \"as-off\", \"as-busy\", or \"ignore\"\n");
+ else
+ eprintf("value of -y shall be either \"silent\", \"as-off\", \"as-busy\", or \"ignore\"\n");
+ }
+
+ errno = 0;
+ user = getpwuid(getuid());
+ if (!user)
+ eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");
+
+ if (libcontacts_load_contact(argv[0], &contact, user))
+ eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted");
+
+ if (edit && contact.blocks) {
+ for (i = 0; contact.blocks[i]; i++) {
+ if (srv && !edit_srv && strcmpnul(contact.blocks[i]->service, srv))
+ continue;
+ if (type && !edit_type && contact.blocks[i]->explicit != explicit)
+ continue;
+ if (style && !edit_style && contact.blocks[i]->shadow_block != shadow_block)
+ continue;
+ if (ask && !edit_ask && contact.blocks[i]->soft_unblock != soft_unblock)
+ continue;
+ if (ublk && !edit_ublk && contact.blocks[i]->hard_unblock != hard_unblock)
+ continue;
+ if (edit_srv) {
+ free(contact.blocks[i]->service);
+ contact.blocks[i]->service = estrdup(srv);
+ }
+ if (edit_type)
+ contact.blocks[i]->explicit = explicit;
+ if (edit_style)
+ contact.blocks[i]->shadow_block = shadow_block;
+ if (edit_ask)
+ contact.blocks[i]->soft_unblock = soft_unblock;
+ if (edit_ublk)
+ contact.blocks[i]->hard_unblock = hard_unblock;
+ }
+ } else if (!edit) {
+ i = 0;
+ if (contact.blocks)
+ for (; contact.blocks[i]; i++);
+ contact.blocks = erealloc(contact.blocks, (i + 2) * sizeof(*contact.blocks));
+ contact.blocks[i + 1] = NULL;
+ contact.blocks[i] = ecalloc(1, sizeof(**contact.emails));
+ contact.blocks[i]->service = estrdup(srv ? srv : ".global");
+ contact.blocks[i]->explicit = explicit;
+ contact.blocks[i]->shadow_block = shadow_block;
+ contact.blocks[i]->soft_unblock = soft_unblock;
+ contact.blocks[i]->hard_unblock = hard_unblock;
+ }
+
+ if (libcontacts_save_contact(&contact, user))
+ eprintf("libcontacts_save_contact %s:", argv[0]);
+ libcontacts_contact_destroy(&contact);
+
+ return 0;
+}
diff --git a/unblock-contact.c b/unblock-contact.c
new file mode 100644
index 0000000..ad2b5a0
--- /dev/null
+++ b/unblock-contact.c
@@ -0,0 +1,124 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a ask-at] [-s service] [-t type] [-u unblock-at] [-y style] contact-id ...");
+
+
+int
+main(int argc, char *argv[])
+{
+ int explicit = 0;
+ enum libcontacts_block_type shadow_block = 0;
+ time_t soft_unblock = 0, hard_unblock = 0;
+ const char *srv = NULL, *type = NULL, *style = NULL, *ask = NULL, *ublk = NULL;
+ struct passwd *user;
+ struct libcontacts_contact contact;
+ struct libcontacts_block **r, **w;
+ char *p;
+ size_t i;
+ int ret = 0;
+
+ ARGBEGIN {
+ case 'a':
+ if (ask)
+ usage();
+ ask = ARG();
+ if (!isdigit(*ask))
+ usage();
+ soft_unblock = (time_t)strtoumax(ask, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 's':
+ if (srv)
+ usage();
+ srv = ARG();
+ break;
+ case 't':
+ if (type)
+ usage();
+ type = ARG();
+ break;
+ case 'u':
+ if (ublk)
+ usage();
+ ublk = ARG();
+ if (!isdigit(*ublk))
+ usage();
+ hard_unblock = (time_t)strtoumax(ublk, &p, 10);
+ if (errno || *p)
+ usage();
+ break;
+ case 'y':
+ if (style)
+ usage();
+ style = ARG();
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!argc)
+ usage();
+
+ for (i = 0; argv[i]; i++)
+ if (!*argv[i] || strchr(argv[i], '/'))
+ usage();
+
+ if (type) {
+ if (!strcmp(type, "explicit"))
+ explicit = 1;
+ else if (!strcmp(type, "shadow"))
+ explicit = 0;
+ else
+ eprintf("value of -t shall be either \"explicit\" or \"shadow\"\n");
+ }
+
+ if (style) {
+ if (!strcmp(style, "silent"))
+ shadow_block = LIBCONTACTS_SILENT;
+ else if (!strcmp(style, "as-off"))
+ shadow_block = LIBCONTACTS_BLOCK_OFF;
+ else if (!strcmp(style, "as-busy"))
+ shadow_block = LIBCONTACTS_BLOCK_BUSY;
+ else if (!strcmp(style, "ignore"))
+ shadow_block = LIBCONTACTS_BLOCK_IGNORE;
+ else
+ eprintf("value of -y shall be either \"silent\", \"as-off\", \"as-busy\", or \"ignore\"\n");
+ }
+
+ errno = 0;
+ user = getpwuid(getuid());
+ if (!user)
+ eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");
+
+ for (; *argv; argv++) {
+ if (libcontacts_load_contact(*argv, &contact, user)) {
+ weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted");
+ ret = 1;
+ continue;
+ }
+ if ((r = contact.blocks)) {
+ for (w = r; *r; w++) {
+ *w = *r++;
+ if (srv && strcmpnul((*w)->service, srv))
+ continue;
+ if (type && (*w)->explicit != explicit)
+ continue;
+ if (style && (*w)->shadow_block != shadow_block)
+ continue;
+ if (ask && (*w)->soft_unblock != soft_unblock)
+ continue;
+ if (ublk && (*w)->hard_unblock != hard_unblock)
+ continue;
+ libcontacts_block_destroy(*w);
+ free(*w--);
+ }
+ if (libcontacts_save_contact(&contact, user))
+ eprintf("libcontacts_save_contact %s:", *argv);
+ }
+ libcontacts_contact_destroy(&contact);
+ }
+
+ return ret;
+}