summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bencoding.c3
-rw-r--r--src/metainfo.c90
2 files changed, 93 insertions, 0 deletions
diff --git a/src/bencoding.c b/src/bencoding.c
index 9ff9f89..6e8a2a2 100644
--- a/src/bencoding.c
+++ b/src/bencoding.c
@@ -1,3 +1,6 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
#include <stdbool.h>
/**
diff --git a/src/metainfo.c b/src/metainfo.c
new file mode 100644
index 0000000..1a0adcc
--- /dev/null
+++ b/src/metainfo.c
@@ -0,0 +1,90 @@
+#include <bencoding.c>
+struct inode {
+ char * name;
+ int length;
+ struct inode * next;
+ struct inode * child;
+ struct inode * parent;
+};
+struct inode * next (struct inode * inode) {
+ if (inode->child)
+ return next(inode->child);
+ if (inode->next) {
+ if (inode->next->child)
+ return next(inode->next->child);
+ return inode->next;
+ }
+ struct inode * predecesor = inode;
+ while (!predecesor->next) {
+ predecesor = predecesor->parent;
+ if (!predecesor)
+ return NULL;
+ }
+ return predecesor->next;
+}
+enum type {
+ UNSPEC = 0,
+ V1 = 1,
+ V2 = 2
+ HYBRID = 1 | 2
+}
+struct metainfo {
+ struct inode * files;
+ struct sockaddr_in6 ip;
+ time_t retrieved;
+ time_t created;
+ enum type type;
+ char sha1[20];
+ char sha256[32];
+ char * name;
+ char * client;
+ char * source;
+ char * publisher;
+ char * publisher_url;
+ char * comment;
+};
+void metainfo_free (struct metainfo * metainfo) {
+ inode_free(metainfo->files);
+ free(metainfo->name);
+ free(metainfo->client);
+ free(metainfo->source);
+ free(metainfo->publisher);
+ free(metainfo->publisher_url)
+ free(metainfo->comment);
+ free(metainfo);
+}
+struct metainfo * parse (const struct bencoding * metainfo) {
+ struct metainfo * r = calloc(1, sizeof(metainfo));
+#define EXTRACT(attribute, localvar, from) \
+ struct bencoding * localvar = bpath(metainfo, from); \
+ if (localvar && localvar->valuelen) { \
+ free(r->attribute); \
+ r->attribute = localvar->value; \
+ localvar->value = NULL; /* this is nonstandard, but it's a monorepo */ \
+ }
+ EXTRACT(name, name, "info/name");
+ EXTRACT(name, nameutf8, "info/name.utf-8");
+ EXTRACT(client, client, "source/v");
+ EXTRACT(source, source, "info/source");
+ EXTRACT(publisher, publisher, "info/publisher");
+ EXTRACT(publisher, publisherutf8, "info/publisher.utf-8");
+ EXTRACT(publisher_url, publisher_url, "info/publisher-url");
+ EXTRACT(publisher_url, publisher_urlutf8, "info/publisher-url.utf-8");
+ EXTRACT(comment, comment, "comment");
+ struct bencoding * retrieved = bpath(metainfo, "info/creation date");
+ if (retrieved && retrieved->valuelen)
+ r->retrieved = atoi(retrieved->value);
+ struct bencoding * created = bpath(metainfo, "creation date");
+ if (created && created->intvalue)
+ r->created = created->intvalue;
+ struct bencoding * files = bpath(metainfo, "info/files");
+ if (files) {
+ r->type = V1;
+ bforeach (files, file) {
+ struct attr * bpath(file, "attr");
+ if (attr && attr->valuelen && strchr(attr, 'p'))
+ continue;
+ struct path * bpath(file, "path");
+ }
+ }
+}