aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-04 23:48:03 +0200
committerMattias Andrée <maandree@kth.se>2021-04-04 23:48:03 +0200
commit4e07377ba62a1877a150faf196c8a9d3ac3fdcd7 (patch)
tree2e7434adcc7bf4d2f05ea0551ecda414a18e8ce4
parentm (diff)
downloadcontacts-4e07377ba62a1877a150faf196c8a9d3ac3fdcd7.tar.gz
contacts-4e07377ba62a1877a150faf196c8a9d3ac3fdcd7.tar.bz2
contacts-4e07377ba62a1877a150faf196c8a9d3ac3fdcd7.tar.xz
Add find-contact-by-address and get-contact-addresses
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--.gitignore3
-rw-r--r--Makefile13
-rw-r--r--TODO4
-rw-r--r--common-address.c89
-rw-r--r--common.h5
-rw-r--r--find-contact-by-address.c107
-rw-r--r--get-contact-addresses.c169
7 files changed, 388 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 2867b2c..af6aaab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
/contacts
/contacts.c
/add-contact
+/find-contact-by-address
/find-contact-by-chat
/find-contact-by-email
/find-contact-by-name
@@ -18,6 +19,7 @@
/find-contact-by-pgpkey
/find-contact-by-photo
/find-contact-by-site
+/get-contact-addresses
/get-contact-birthday
/get-contact-chats
/get-contact-emails
@@ -41,6 +43,7 @@
/list-organisation-contacts
/print-contact
/remove-contact
+/set-contact-addresses
/set-contact-birthday
/set-contact-chats
/set-contact-emails
diff --git a/Makefile b/Makefile
index 0bbc52e..3daf44f 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ CALLTYPE = multicall-hardlinks
BIN =\
add-contact\
+ find-contact-by-address\
find-contact-by-chat\
find-contact-by-email\
find-contact-by-name\
@@ -18,6 +19,7 @@ BIN =\
find-contact-by-pgpkey\
find-contact-by-photo\
find-contact-by-site\
+ get-contact-addresses\
get-contact-birthday\
get-contact-chats\
get-contact-emails\
@@ -58,7 +60,7 @@ BIN =\
HDR =\
common.h
-OBJ = $(BIN:=.o) common-birthday.o
+OBJ = $(BIN:=.o) common-birthday.o common-address.o
BOBJ = $(OBJ:.o=.bo)
@@ -87,6 +89,9 @@ contacts.c: contacts.c.in Makefile
add-contact: add-contact.o
$(CC) -o $@ $@.o $(LDFLAGS)
+find-contact-by-address: find-contact-by-address.o common-address.o
+ $(CC) -o $@ $@.o common-address.o $(LDFLAGS)
+
find-contact-by-chat: find-contact-by-chat.o
$(CC) -o $@ $@.o $(LDFLAGS)
@@ -111,6 +116,9 @@ find-contact-by-photo: find-contact-by-photo.o
find-contact-by-site: find-contact-by-site.o
$(CC) -o $@ $@.o $(LDFLAGS)
+get-contact-addresses: get-contact-addresses.o common-address.o
+ $(CC) -o $@ $@.o common-address.o $(LDFLAGS)
+
get-contact-birthday: get-contact-birthday.o common-birthday.o
$(CC) -o $@ $@.o common-birthday.o $(LDFLAGS)
@@ -180,6 +188,9 @@ print-contact: print-contact.o
remove-contact: remove-contact.o
$(CC) -o $@ $@.o $(LDFLAGS)
+set-contact-addresses: set-contact-addresses.o
+ $(CC) -o $@ $@.o $(LDFLAGS)
+
set-contact-birthday: set-contact-birthday.o
$(CC) -o $@ $@.o $(LDFLAGS)
diff --git a/TODO b/TODO
index c16c1de..2cb5755 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,7 @@
Add tools for checking context for contact info
Add tools for .blocks
-Add tools for .addresses
+
+set-contact-addresses
Test find-contact-by-chat
Test find-contact-by-email
@@ -19,6 +20,7 @@ Test get-contact-sites
Test list-chat-contacts
Test list-contact-organisations
Test list-organisation-contacts
+Test set-contact-addresses
Test set-contact-birthday
Test set-contact-chats
Test set-contact-emails
diff --git a/common-address.c b/common-address.c
new file mode 100644
index 0000000..8ad8712
--- /dev/null
+++ b/common-address.c
@@ -0,0 +1,89 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+int
+parse_coord(char *s, double *lat_min, double *lat_max, double *lon_min, double *lon_max)
+{
+ int withsign = 0, neg;
+ long int tmp;
+ double prec;
+
+ errno = 0;
+
+ if (s[0] == ':') {
+ *lat_min = -90;
+ *lat_max = +90;
+ } else {
+ prec = 1;
+ withsign = (s[0] == '-' || s[0] == '+');
+ neg = s[0] == '-';
+ s = &s[withsign];
+ tmp = 0;
+ if (isdigit(s[withsign])) {
+ tmp = strtol(s, &s, 0);
+ if (errno || tmp > INT_MAX)
+ return -1;
+ }
+ *lat_min = (double)tmp;
+ if (s[0] == '.') {
+ for (s++; isdigit(*s); s++) {
+ *lat_min *= 10;
+ *lat_min += (double)(*s & 15);
+ prec *= 10;
+ }
+ *lat_min /= prec;
+ }
+ if (!withsign && (s[0] == 'N' || s[0] == 'S')) {
+ neg = s[0] == 'S';
+ s = &s[1];
+ }
+ if (neg)
+ *lat_min = -*lat_min;
+ prec = (1 / prec) / 2;
+ *lat_max = *lat_min + prec;
+ *lat_min -= prec;
+ if (s[0] != ':')
+ return -1;
+ }
+
+ s = &s[1];
+
+ if (!s[0]) {
+ *lon_min = -180;
+ *lon_max = +180;
+ } else {
+ prec = 1;
+ withsign = (s[0] == '-' || s[0] == '+');
+ neg = s[0] == '-';
+ s = &s[withsign];
+ tmp = 0;
+ if (isdigit(s[withsign])) {
+ tmp = strtol(s, &s, 0);
+ if (errno || tmp > INT_MAX)
+ return -1;
+ }
+ *lon_min = (double)tmp;
+ if (s[0] == '.') {
+ for (s++; isdigit(*s); s++) {
+ *lon_min *= 10;
+ *lon_min += (double)(*s & 15);
+ prec *= 10;
+ }
+ *lon_min /= prec;
+ }
+ if (!withsign && (s[0] == 'E' || s[0] == 'W')) {
+ neg = s[0] == 'W';
+ s = &s[1];
+ }
+ if (neg)
+ *lon_min = -*lon_min;
+ prec = (1 / prec) / 2;
+ *lon_max = *lon_min + prec;
+ *lon_min -= prec;
+ if (s[0])
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/common.h b/common.h
index 7abe91a..6993070 100644
--- a/common.h
+++ b/common.h
@@ -7,6 +7,8 @@
#include <libsimple.h>
#include <libsimple-arg.h>
+#include <math.h>
+
#ifndef BUFSIZ
# define BUFSIZ 4096
@@ -20,3 +22,6 @@ __attribute__((__pure__))
int get_age(struct libcontacts_birthday *bday, const struct tm *now);
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_min, double *lat_max, double *lon_min, double *lon_max);
diff --git a/find-contact-by-address.c b/find-contact-by-address.c
new file mode 100644
index 0000000..646d0d5
--- /dev/null
+++ b/find-contact-by-address.c
@@ -0,0 +1,107 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a address] [-c context] [-g [latitude]:[longitude]] [-l country] [-o care-of] [-p post-code] [-t city]");
+
+
+int
+main(int argc, char *argv[])
+{
+ struct passwd *user;
+ struct libcontacts_contact **contacts;
+ struct libcontacts_address **addresses, *addr;
+ char *lookup_addr = NULL, *lookup_ctx = NULL, *lookup_loc = NULL;
+ char *lookup_country = NULL, *lookup_careof = NULL;
+ char *lookup_postcode = NULL, *lookup_city = NULL;
+ double lat, lon, lat_min = 0, lat_max = 0, lon_min = 0, lon_max = 0;
+ size_t i;
+
+ ARGBEGIN {
+ case 'c':
+ if (lookup_ctx)
+ usage();
+ lookup_ctx = ARG();
+ break;
+ case 'o':
+ if (lookup_careof)
+ usage();
+ lookup_careof = ARG();
+ break;
+ case 'a':
+ if (lookup_addr)
+ usage();
+ lookup_addr = ARG();
+ break;
+ case 'p':
+ if (lookup_postcode)
+ usage();
+ lookup_postcode = ARG();
+ break;
+ case 't':
+ if (lookup_city)
+ usage();
+ lookup_city = ARG();
+ break;
+ case 'l':
+ if (lookup_country)
+ usage();
+ lookup_country = ARG();
+ break;
+ case 'g':
+ if (lookup_loc)
+ usage();
+ lookup_loc = ARG();
+ if (parse_coord(lookup_loc, &lat_min, &lat_max, &lon_min, &lon_max))
+ usage();
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ errno = 0;
+ user = getpwuid(getuid());
+ if (!user)
+ eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");
+
+ if (libcontacts_load_contacts(&contacts, user))
+ eprintf("libcontacts_load_contacts:");
+ for (i = 0; contacts[i]; i++) {
+ if ((addresses = contacts[i]->addresses)) {
+ for (; (addr = *addresses); addresses++) {
+ if (lookup_ctx && strcmpnul(addr->context, lookup_ctx))
+ continue;
+ if (lookup_careof && strcmpnul(addr->care_of, lookup_careof))
+ continue;
+ if (lookup_addr && strcmpnul(addr->address, lookup_addr))
+ continue;
+ if (lookup_postcode && strcmpnul(addr->postcode, lookup_postcode))
+ continue;
+ if (lookup_city && strcmpnul(addr->city, lookup_city))
+ continue;
+ if (lookup_country && strcmpnul(addr->country, lookup_country))
+ continue;
+ if (lookup_loc && !addr->have_coordinates)
+ continue;
+ lat = addr->latitude;
+ lon = addr->longitude;
+ if (lookup_loc && !(lat_min <= lat && lat <= lat_max && lon_min <= lon && lon <= lon_max))
+ continue;
+ if (!addr->context && !addr->care_of && !addr->address && !addr->postcode && !addr->city &&
+ !addr->country && !addr->have_coordinates)
+ continue;
+ printf("%s\n", contacts[i]->id);
+ }
+ }
+ libcontacts_contact_destroy(contacts[i]);
+ free(contacts[i]);
+ }
+ free(contacts);
+
+ if (fflush(stdout) || ferror(stdout) || fclose(stdout))
+ eprintf("printf:");
+
+ return 0;
+}
diff --git a/get-contact-addresses.c b/get-contact-addresses.c
new file mode 100644
index 0000000..89b4707
--- /dev/null
+++ b/get-contact-addresses.c
@@ -0,0 +1,169 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a address] [-c context] [-g [latitude]:[longitude]] [-l country] "
+ "[-o care-of] [-p post-code] [-t city] [-ACGLOPT] contact-id ...");
+
+
+int
+main(int argc, char *argv[])
+{
+ int fields = 0;
+ struct passwd *user;
+ struct libcontacts_contact contact;
+ struct libcontacts_address **addresses, *addr;
+ char *lookup_addr = NULL, *lookup_ctx = NULL, *lookup_loc = NULL;
+ char *lookup_country = NULL, *lookup_careof = NULL;
+ char *lookup_postcode = NULL, *lookup_city = NULL;
+ double lat, lon, lat_min = 0, lat_max = 0, lon_min = 0, lon_max = 0;
+ int ret = 0, f;
+ size_t i;
+
+ ARGBEGIN {
+ case 'c':
+ if (lookup_ctx)
+ usage();
+ lookup_ctx = ARG();
+ break;
+ case 'o':
+ if (lookup_careof)
+ usage();
+ lookup_careof = ARG();
+ break;
+ case 'a':
+ if (lookup_addr)
+ usage();
+ lookup_addr = ARG();
+ break;
+ case 'p':
+ if (lookup_postcode)
+ usage();
+ lookup_postcode = ARG();
+ break;
+ case 't':
+ if (lookup_city)
+ usage();
+ lookup_city = ARG();
+ break;
+ case 'l':
+ if (lookup_country)
+ usage();
+ lookup_country = ARG();
+ break;
+ case 'g':
+ if (lookup_loc)
+ usage();
+ lookup_loc = ARG();
+ if (parse_coord(lookup_loc, &lat_min, &lat_max, &lon_min, &lon_max))
+ usage();
+ break;
+ case 'C':
+ fields |= 0x01;
+ break;
+ case 'O':
+ fields |= 0x02;
+ break;
+ case 'A':
+ fields |= 0x04;
+ break;
+ case 'P':
+ fields |= 0x08;
+ break;
+ case 'T':
+ fields |= 0x10;
+ break;
+ case 'L':
+ fields |= 0x20;
+ break;
+ case 'G':
+ fields |= 0x40;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!argc)
+ usage();
+
+ if (!fields)
+ fields = 0x7F;
+
+ for (i = 0; argv[i]; i++)
+ if (!*argv[i] || strchr(argv[i], '/'))
+ usage();
+
+ 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 ((addresses = contact.addresses)) {
+ for (; (addr = *addresses); addresses++) {
+ if (lookup_ctx && strcmpnul(addr->context, lookup_ctx))
+ continue;
+ if (lookup_careof && strcmpnul(addr->care_of, lookup_careof))
+ continue;
+ if (lookup_addr && strcmpnul(addr->address, lookup_addr))
+ continue;
+ if (lookup_postcode && strcmpnul(addr->postcode, lookup_postcode))
+ continue;
+ if (lookup_city && strcmpnul(addr->city, lookup_city))
+ continue;
+ if (lookup_country && strcmpnul(addr->country, lookup_country))
+ continue;
+ if (lookup_loc && !addr->have_coordinates)
+ continue;
+ lat = addr->latitude;
+ lon = addr->longitude;
+ if (lookup_loc && !(lat_min <= lat && lat <= lat_max && lon_min <= lon && lon <= lon_max))
+ continue;
+ if (argc > 1)
+ printf("%s: ", *argv);
+ f = fields;
+ if (f & 0x01) {
+ f ^= 0x01;
+ if (addr->context)
+ printf("%s: ", addr->context);
+ }
+ if (f & 0x02) {
+ f ^= 0x02;
+ printf("%s%s", addr->care_of ? addr->care_of : "", f ? "; " : "\n");
+ }
+ if (f & 0x04) {
+ f ^= 0x04;
+ printf("%s%s", addr->address ? addr->address : "", f ? "; " : "\n");
+ }
+ if (f & 0x08) {
+ f ^= 0x08;
+ printf("%s%s", addr->postcode ? addr->postcode : "", f ? "; " : "\n");
+ }
+ if (f & 0x10) {
+ f ^= 0x10;
+ printf("%s%s", addr->city ? addr->city : "", f ? "; " : "\n");
+ }
+ if (f & 0x20) {
+ f ^= 0x20;
+ printf("%s%s", addr->country ? addr->country : "", f ? "; " : "\n");
+ }
+ if (f & 0x40) {
+ if (addr->have_coordinates) {
+ printf("%lg%s ", fabs(lat), lat < 0 ? "S" : lat > 0 ? "N" : "");
+ printf("%lg%s", fabs(lon), lon < 0 ? "W" : lon > 0 ? "E" : "");
+ }
+ printf("\n");
+ }
+ }
+ }
+ libcontacts_contact_destroy(&contact);
+ }
+
+ if (fflush(stdout) || ferror(stdout) || fclose(stdout))
+ eprintf("printf:");
+ return ret;
+}