From f2ee15e4ec3a02e4be6a522bb7b276bdf5703301 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 6 Apr 2021 01:42:13 +0200 Subject: m + add block utils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 3 + Makefile | 14 +++- TODO | 5 +- common-address.c | 6 +- common.h | 2 +- get-contact-blocks.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++ set-contact-blocks.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++ unblock-contact.c | 124 ++++++++++++++++++++++++++++++++++++ 8 files changed, 489 insertions(+), 6 deletions(-) create mode 100644 get-contact-blocks.c create mode 100644 set-contact-blocks.c create mode 100644 unblock-contact.c 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; +} -- cgit v1.2.3-70-g09d2