shithub: vcardfs

Download patch

ref: 29ecb5f41a832a68cad00ad9314fabeb30f16ad8
parent: a0054fa2fc711277c267fbd7d6b48bff6e0d4a82
author: sirjofri <sirjofri@sirjofri.de>
date: Thu Nov 7 12:03:34 EST 2024

adds support for duplicate fields using <N>:group.name syntax

--- a/john.vcf
+++ b/john.vcf
@@ -1,6 +1,7 @@
 BEGIN:VCARD
 VERSION:4.0
 N;TYPE=ABC;value="A;B;C":Doe;John;;
+N;TYPE=Another:Do;Jon;;
 FN:John 
  Doe
 END:VCARD
--- a/vcardfs.c
+++ b/vcardfs.c
@@ -84,6 +84,14 @@
 					[Qparamdata] "paramdata",
 };
 
+typedef struct Vlinenumber Vlinenumber;
+struct Vlinenumber
+{
+	char *name;
+	int value;
+	Vlinenumber *next;
+};
+
 typedef struct Vfile Vfile;
 struct Vfile {
 	int level;
@@ -93,8 +101,55 @@
 	Vfile *cardfile;
 	File *file;
 	char *serialized;
+	Vlinenumber *linenumbers;
 };
 
+static Vlinenumber*
+findlinenumber(Vfile *f, char *line)
+{
+	Vlinenumber *l, *last;
+
+	if (!f->linenumbers) {
+		f->linenumbers = emalloc(sizeof(Vlinenumber));
+		last = f->linenumbers;
+		goto Out;
+	}
+
+	last = nil;
+	for (l = f->linenumbers; l; l = l->next) {
+		if (cistrcmp(l->name, line) == 0)
+			return l;
+		last = l;
+	}
+
+	if (!last)
+		return nil;
+	last->next = emalloc(sizeof(Vlinenumber));
+	last = last->next;
+	Out:
+		last->name = estrdup(line);
+	last->value = 0;
+	return last;
+}
+
+static int
+getcurrentlinenumber(Vfile *f, char *line)
+{
+	Vlinenumber *l;
+	l = findlinenumber(f, line);
+	return l ? l->value : -1;
+}
+
+static void
+inclinenumber(Vfile *f, char *line)
+{
+	Vlinenumber *l;
+	l = findlinenumber(f, line);
+	if (!l)
+		return;
+	l->value++;
+}
+
 static char*
 vfqn(Vfile *f)
 {
@@ -121,6 +176,20 @@
 static char* getcardname(Vcard*);
 static void initcardfiles(Vcard *chain);
 
+static char*
+ecreatelinename(Vfile *cf, Vline *l)
+{
+	char *s;
+	s = smprint("%d:%s%s%s",
+		getcurrentlinenumber(cf, l->name),
+		l->group ? l->group : "",
+		l->group ? "." : "",
+		l->name);
+	if (!s)
+		sysfatal("createlinename: %r");
+	return s;
+}
+
 static Vfile*
 emkvfile(int level, Vcard *c, Vline *l, Vparam *p, Vfile *cfile)
 {
@@ -506,6 +575,7 @@
 {
 	File *dirf, *paramf, *dataf;
 	Vline *l, *nl;
+	char *s;
 	
 	if (!vf->card) {
 		respond(r, "invalid card file");
@@ -512,14 +582,21 @@
 		return nil;
 	}
 	
-	dirf = createfile(r->fid->file, r->ifcall.name, user, DMDIR|0777, nil);
+	nl = mallocz(sizeof(Vline), 1);
+	nl->name = estrdup(r->ifcall.name);
+	nl->value = estrdup("");
+
+	s = ecreatelinename(vf, nl);
+	
+	dirf = createfile(r->fid->file, s, user, DMDIR|0777, nil);
+	free(s);
 	if (!dirf) {
 		responderror(r);
+		free(nl->name);
+		free(nl->value);
+		free(nl);
 		return nil;
 	}
-	nl = mallocz(sizeof(Vline), 1);
-	nl->name = estrdup(r->ifcall.name);
-	nl->value = estrdup("");
 	
 	if (!vf->card->content) {
 		vf->card->content = nl;
@@ -958,14 +1035,11 @@
 		
 		for (l = c->content; l; l = l->next) {
 			vf = emkvfile(Qline, c, l, nil, cf);
-			if (l->group && *l->group) {
-				s = smprint("%s.%s", l->group, l->name);
-			}
-			fl = createfile(fc, (l->group && *l->group ? s : l->name), user, DMDIR|0777, vf);
-			if (l->group) {
-				free(s);
-				s = nil;
-			}
+			s = ecreatelinename(cf, l);
+			inclinenumber(cf, l->name);
+			fl = createfile(fc, s, user, DMDIR|0777, vf);
+			free(s);
+			s = nil;
 			vf = emkvfile(Qdata, c, l, nil, cf);
 			f = createfile(fl, "data", user, 0666, vf);
 			closefile(f);