From 3ccf5d377d4d31eef2730f34c51067690443054f Mon Sep 17 00:00:00 2001 From: Matteo Bini Date: Tue, 19 Mar 2024 15:51:31 +0100 Subject: [PATCH] First! --- Makefile | 50 +++++ cnt2vcf | 40 ++++ vcf2cnt.c | 545 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 635 insertions(+) create mode 100644 Makefile create mode 100755 cnt2vcf create mode 100644 vcf2cnt.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0e52e0e --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +BIN = vcf2cnt +VERSION = 1.0 + +PREFIX = /usr/local + +INCS = +LIBS = + +CPPFLAGS_VCF2CNT = -DVERSION=\"${VERSION}\" ${CPPFLAGS} +# debug +#CFLAGS_VCF2CNT = -ggdb -ansi -pedantic ${INCS} ${CPPFLAGS_VCF2CNT} ${CLAGS} +CFLAGS_VCF2CNT = -Os -ansi -pedantic ${INCS} ${CPPFLAGS_VCF2CNT} ${CFLAGS} +LDFLAGS_VCF2CNT = ${LIBS} ${LDFLAGS} + +SRC = vcf2cnt.c +OBJ = ${SRC:.c=.o} + +all: options vcf2cnt + +options: + @echo vcf2cnt build options: + @echo "CFLAGS = ${CFLAGS_VCF2CNT}" + @echo "LDFLAGS = ${LDFLAGS_VCF2CNT}" + @echo "CC = ${CC}" + +.c.o: + ${CC} ${CFLAGS_VCF2CNT} -c $< -o $@ + +${BIN}: ${OBJ} + ${CC} -o ${BIN} ${OBJ} ${LDFLAGS_VCF2CNT} + +clean: + rm -f ${BIN} ${BIN}-${VERSION}.tar.gz *.o + +dist: clean + mkdir ${BIN}-${VERSION} + cp -R ${SRC} LICENSE Makefile README ${BIN}-${VERSION} + tar -cf ${BIN}-${VERSION}.tar ${BIN}-${VERSION} + gzip ${BIN}-${VERSION}.tar + rm -fr ${BIN}-${VERSION} + +install: ${BIN} + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f ${BIN} ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/${BIN} + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/${BIN} + +.PHONY: all options clean dist install uninstall diff --git a/cnt2vcf b/cnt2vcf new file mode 100755 index 0000000..853a80b --- /dev/null +++ b/cnt2vcf @@ -0,0 +1,40 @@ +#!/bin/sh + +set -e + +read -p 'Nome: ' name +read -p 'Cognome: ' surname +read -p 'Cellulare: ' cellphone +read -p 'Indirizzo: ' address +read -p 'Email: ' email +read -p 'Telefono: ' phone +read -p 'XMPP: ' xmpp +read -p 'Note: ' note + +printf 'BEGIN:VCARD\r\n' +printf 'VERSION:4.0\r\n' + +printf 'N:%s;%s;;;\r\n' "$surname" "$name" +printf 'FN:%s %s\r\n' "$name" "$surname" + +if [ -n "$cellphone" ]; then + printf 'TEL;TYPE=CELL:%s\r\n' "$cellphone" +fi + +if [ -n "$email" ]; then + printf 'EMAIL;TYPE=HOME:%s\r\n' "$email" +fi + +if [ -n "$phone" ]; then + printf 'TEL;TYPE=HOME:%s\r\n' "$phone" +fi + +if [ -n "$xmpp" ]; then + printf 'IMPP;TYPE=HOME:xmpp:%s\r\n' "$xmpp" +fi + +if [ -n "$note" ]; then + printf 'NOTE:%s\r\n' "$(echo "$note" | sed 's/\\/\\\\/g;s/,/\\,/g')" +fi + +printf 'END:VCARD\r\n' diff --git a/vcf2cnt.c b/vcf2cnt.c new file mode 100644 index 0000000..8be4700 --- /dev/null +++ b/vcf2cnt.c @@ -0,0 +1,545 @@ +#include +#include +#include + +/* macros */ +#define FBUF_SIZE 4096 + +typedef struct { + char *address; + char *birth_date; + char *cellphone; + char *email; + char *name; + char *note; + char *organization; + char *phone; + char *surname; + char *website; + char *work_address; + char *work_cellphone; + char *work_email; + char *work_phone; + char *work_xmpp; + char *xmpp; +} Contatto; + +/* function declarations */ +static int convert_vcard(char **contact); +static int convert_vcard_line(Contatto *contatto, const char *line); +static void convert_vcard_property_adr(Contatto *contatto, const char *value, const char *parameter); +static void convert_vcard_property_email(Contatto *contatto, const char *value, const char *parameter); +static void convert_vcard_property_n(Contatto *contatto, const char *value); +static void convert_vcard_property_note(Contatto *contatto, const char *value); +static void convert_vcard_property_org(Contatto *contatto, const char *value); +static void convert_vcard_property_tel(Contatto *contatto, const char *value, const char *parameter); +static Contatto *create_contatto(void); +static void free_contact(char ***contact); +static void free_contatto(Contatto *contatto); +static void *safe_malloc(const size_t size); +static void strcut_d(char **ds1, char **ds2, const char *src, const char s); +static void strexp_d(char ***dst, const char *src, const char s); +static void strncat_d(char **dst, const char *src, const size_t sz); +static void strrmchar_d(char **src, const char r); + +/* function implementations */ +int +convert_vcard(char **contact) +{ + Contatto *contatto; + + contatto = create_contatto(); + + while (*contact != NULL) { + convert_vcard_line(contatto, *contact); + (contact)++; + } + + printf("------------------------------------------------------------------------\n"); + if (contatto->cellphone != NULL) + printf("Cellulare: %s\n", contatto->cellphone); + if (contatto->work_cellphone != NULL) + printf("Cellulare di lavoro: %s\n", contatto->work_cellphone); + if (contatto->surname != NULL) + printf("Cognome: %s\n", contatto->surname); + if (contatto->email != NULL) + printf("Email: %s\n", contatto->email); + if (contatto->work_email != NULL) + printf("Email di lavoro: %s\n", contatto->work_email); + if (contatto->address != NULL) + printf("Indirizzo: %s\n", contatto->address); + if (contatto->work_address != NULL) + printf("Indirizzo di lavoro: %s\n", contatto->work_address); + if (contatto->name != NULL) + printf("Nome: %s\n", contatto->name); + if (contatto->note != NULL) + printf("Note: %s\n", contatto->note); + if (contatto->organization != NULL) + printf("Organizzazione: %s\n", contatto->organization); + if (contatto->phone != NULL) + printf("Telefono: %s\n", contatto->phone); + if (contatto->work_phone != NULL) + printf("Telefono di lavoro: %s\n", contatto->work_phone); + + free_contatto(contatto); + + return 1; +} + +int +convert_vcard_line(Contatto *contatto, const char *line) +{ + char *property, *parameter, *value, *tmp; + + strcut_d(&property, &value, line, ':'); + tmp = safe_malloc(sizeof(char) * (strlen(property) + 1)); + strcpy(tmp, property); + strcut_d(&property, ¶meter, tmp, ';'); + free(tmp); + + + if (!strcmp(property, "BEGIN")) { + if (strcmp(value, "VCARD") != 0) { + fprintf(stderr, "Unexpected value \"%s\" for BEGIN property.\n", value); + } + + } else if (!strcmp(property, "VERSION")) { + /* to do: handle different versions than 4.0 */ + + } else if (!strcmp(property, "FN")) { + /* ignore FN property, we don't need it */ + + } else if (!strcmp(property, "N")) { + convert_vcard_property_n(contatto, value); + + } else if (!strcmp(property, "ADR")) { + strrmchar_d(&value, '\\'); + convert_vcard_property_adr(contatto, value, parameter); + + } else if (!strcmp(property, "TEL")) { + convert_vcard_property_tel(contatto, value, parameter); + + } else if (!strcmp(property, "EMAIL")) { + convert_vcard_property_email(contatto, value, parameter); + + } else if (!strcmp(property, "ORG")) { + strrmchar_d(&value, '\\'); + convert_vcard_property_org(contatto, value); + + } else if (!strcmp(property, "NOTE")) { + strrmchar_d(&value, '\\'); + convert_vcard_property_note(contatto, value); + + } else if (!strcmp(property, "END")) { + if (strcmp(value, "VCARD") != 0) { + fprintf(stderr, "Unexpected value \"%s\" for END property.\n", value); + } + + } else { + fprintf(stderr, "Unknown property %s.\n", property); + } + + free(property); + free(parameter); + free(value); + + return 1; +} + +void +convert_vcard_property_adr(Contatto *contatto, const char *value, const char *parameter) +{ + char **dst, **tmp; + unsigned int i, to_trim; + size_t len; + + tmp = NULL; + to_trim = 0; + + dst = strstr(parameter, "WORK") != NULL ? &contatto->work_address : &contatto->address; + strexp_d(&tmp, value, ';'); + + if (*dst != NULL) + free(*dst); + *dst = safe_malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(*dst, ""); + for (i = 0; i < 6; i++) { + if (strcmp(tmp[i], "") != 0) { + strcat(*dst, tmp[i]); + strcat(*dst, ", "); + to_trim = 1; + } + } + if (to_trim) { + len = strlen(*dst); + (*dst)[len - 1] = '\0'; + (*dst)[len - 2] = '\0'; + } +} + +void +convert_vcard_property_email(Contatto *contatto, const char *value, const char *parameter) +{ + char **dst; + + dst = strstr(parameter, "WORK") != NULL ? &contatto->work_email : &contatto->email; + + if (*dst != NULL) + free(*dst); + *dst = safe_malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(*dst, value); +} + +void +convert_vcard_property_n(Contatto *contatto, const char *value) +{ + char *tmp1, *tmp2; + + strcut_d(&contatto->surname, &tmp1, value, ';'); + strcut_d(&contatto->name, &tmp2, tmp1, ';'); + + free(tmp1); + free(tmp2); +} + +void +convert_vcard_property_note(Contatto *contatto, const char *value) +{ + if (contatto->note != NULL) + free(contatto->note); + contatto->note = safe_malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(contatto->note, value); +} + +void +convert_vcard_property_org(Contatto *contatto, const char *value) +{ + if (contatto->organization != NULL) + free(contatto->organization); + contatto->organization = safe_malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(contatto->organization, value); + + /* to do: separate value components */ +} + +void +convert_vcard_property_tel(Contatto *contatto, const char *value, const char *parameter) +{ + char **dst; + + if (strstr(parameter, "CELL") != NULL) + dst = strstr(parameter, "WORK") != NULL ? &contatto->work_cellphone : &contatto->cellphone; + else + dst = strstr(parameter, "WORK") != NULL ? &contatto->work_phone : &contatto->phone; + + if (*dst != NULL) + free(*dst); + *dst = safe_malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(*dst, value); +} + +Contatto * +create_contatto(void) +{ + Contatto *contatto; + + contatto = safe_malloc(sizeof(Contatto)); + contatto->address = NULL; + contatto->birth_date = NULL; + contatto->cellphone = NULL; + contatto->email = NULL; + contatto->name = NULL; + contatto->note = NULL; + contatto->organization = NULL; + contatto->phone = NULL; + contatto->surname = NULL; + contatto->website = NULL; + contatto->work_address = NULL; + contatto->work_cellphone = NULL; + contatto->work_email = NULL; + contatto->work_phone = NULL; + contatto->work_xmpp = NULL; + contatto->xmpp = NULL; + + return contatto; +} + +void +free_contact(char ***contact) +{ + unsigned int i = 0; + + if (*contact != NULL) { + while (**contact != NULL) { + free(**contact); + **contact = NULL; + (*contact)++; + i++; + } + free(*contact - i); + } +} + +void +free_contatto(Contatto *contatto) +{ + + if (contatto->address != NULL) + free(contatto->address); + + if (contatto->birth_date != NULL) + free(contatto->birth_date); + + if (contatto->cellphone != NULL) + free(contatto->cellphone); + + if (contatto->email != NULL) + free(contatto->email); + + if (contatto->name != NULL) + free(contatto->name); + + if (contatto->note != NULL) + free(contatto->note); + + if (contatto->organization != NULL) + free(contatto->organization); + + if (contatto->phone != NULL) + free(contatto->phone); + + if (contatto->surname != NULL) + free(contatto->surname); + + if (contatto->website != NULL) + free(contatto->website); + + if (contatto->work_address != NULL) + free(contatto->work_address); + + if (contatto->work_cellphone != NULL) + free(contatto->work_cellphone); + + if (contatto->work_email != NULL) + free(contatto->work_email); + + if (contatto->work_phone != NULL) + free(contatto->work_phone); + + if (contatto->work_xmpp != NULL) + free(contatto->work_xmpp); + + if (contatto->xmpp != NULL) + free(contatto->xmpp); + + free(contatto); +} + +int +main (int argc, char *argv[]) +{ + FILE *file; + char buf[FBUF_SIZE]; + int alloc, c, found, l, n, read, x; + char **contact, **tmp_contact; + char *line, *part_line; + + l = 0; + contact = NULL; + tmp_contact = NULL; + line = ""; + part_line = ""; + + file = fopen(argv[1], "r"); + + if (file == NULL) { + fprintf(stderr, "Can't open %s.\n", argv[1]); + return 1; + } + + if (fseek(file, 0, SEEK_SET) == -1) { + fprintf(stderr, "Can't go to the start of %s.\n", argv[1]); + return 1; + } + + do { + read = fread(buf, 1, FBUF_SIZE, file); + for (c = 0; c < FBUF_SIZE && c < read; c++) { + found = 0; + for (n = c + 1; n < FBUF_SIZE && n < read; n++) { + if (n - 1 >= c && buf[n-1] == '\r' && buf[n] == '\n') { + found = 1; + line = safe_malloc(sizeof(char) * (n - c + strlen(part_line))); + strcpy(line, part_line); + if (strcmp(part_line, "") != 0) + free(part_line); + part_line = ""; + strncat(line, buf + c, n - c - 1); + if (!strncmp(line, "BEGIN:VCARD", 11)) { + free_contact(&contact); + l = 0; + } else if (l != 0 && l == alloc) { + tmp_contact = safe_malloc(sizeof(char *) * (alloc * 2 + 1)); + for (x = alloc; x <= alloc * 2; x++) + contact[x] = NULL; + memcpy(tmp_contact, contact, sizeof(char *) * alloc); + free_contact(&contact); + contact = tmp_contact; + alloc = alloc * 2; + } + if (l == 0) { + alloc = 24; + /* contact size is alloc + 1, so the last pointer is NULL */ + contact = safe_malloc(sizeof(char *) * (alloc + 1)); + for (x = 0; x <= alloc; x++) + contact[x] = NULL; + } + contact[l] = safe_malloc(sizeof(char) * (strlen(line) + 1)); + strcpy(contact[l], line); + if (!strncmp(line, "END:VCARD", 9)) { + convert_vcard(contact); + } + free(line); + l++; + c = n; + break; + } + } + if (!found && n == FBUF_SIZE) { + strncat_d(&part_line, buf + c, n - c); + break; + } + if (!found) + break; + } + } while (!feof(file)); + + free_contact(&contact); + + fclose(file); + + return 0; +} + +void * +safe_malloc(const size_t size) +{ + void *p; + + p = malloc(size); + if (p == NULL) { + fprintf(stderr, "Fatal: can't allocate %lu bytes.\n", size); + exit(1); + } + + return p; +} + +void +strcut_d(char **ds1, char **ds2, const char *src, const char s) +{ + char *part; + size_t ds1len, ds2len; + + part = strchr(src, s); + if (part == NULL) { + *ds1 = safe_malloc(sizeof(char) * (strlen(src) + 1)); + strcpy(*ds1, src); + + *ds2 = safe_malloc(sizeof(char) * 2); + strcpy(*ds2, ""); + } else { + ds2len = strlen(part) - 1; + *ds2 = safe_malloc(sizeof(char) * (ds2len + 1)); + strcpy(*ds2, part + 1); + + ds1len = strlen(src) - (ds2len + 1); + *ds1 = safe_malloc(sizeof(char) * (ds1len + 1)); + strncpy(*ds1, src, ds1len); + (*ds1)[ds1len] = '\0'; + } +} + +void +strexp_d(char ***dst, const char *src, const char s) +{ + size_t len, i; + char **tmp_dst; + char *tmp_str; + + len = 0; + i = 0; + + if (*dst == NULL) { + len = 3; + *dst = safe_malloc(sizeof(char *) * len); + } else { + while(**dst != NULL) { + len++; + (*dst)++; + } + *dst -= len; + i = len; + len += 3; + tmp_dst = safe_malloc(sizeof(char *) * len); + memcpy(tmp_dst, *dst, sizeof(char *) * (len - 3)); + free(*dst); + *dst = tmp_dst; + + } + for (i = i; i < len; i++) { + (*dst)[i] = NULL; + } + + strcut_d(&(*dst)[len - 3], &(*dst)[len - 2], src, s); + + if (strchr((*dst)[len - 2], s) != NULL) { + tmp_str = safe_malloc(sizeof(char) * strlen((*dst)[len - 2])); + strcpy(tmp_str, (*dst)[len - 2]); + free((*dst)[len - 2]); + (*dst)[len - 2] = NULL; + strexp_d(&(*dst), tmp_str, s); + free(tmp_str); + } +} + +void +strncat_d(char **dst, const char *src, const size_t sz) +{ + char *tmp; + + if (*dst == NULL) + *dst = ""; + + tmp = safe_malloc(sizeof(char) * (sz + strlen(*dst) + 1)); + + strcpy(tmp, *dst); + if (strcmp(*dst, "") != 0) + free(*dst); + strncat(tmp, src, sz); + *dst = tmp; +} + +void +strrmchar_d(char **str, const char r) +{ + char *tmp; + size_t len, i, c; + + len = strlen(*str); + tmp = safe_malloc(sizeof(char) * (len + 1)); + c = 0; + + for (i = 0; i < len; i++) { + if ((*str)[i] == r) + continue; + tmp[c] = (*str)[i]; + c++; + } + tmp[c] = '\0'; + + free(*str); + *str = safe_malloc(sizeof(char) * c); + strcpy(*str, tmp); + free(tmp); +}