summaryrefslogtreecommitdiffstats
path: root/src/metainfo.c
blob: 1a0adcca78030ce654fc5aee1f0b5d7dd0fa033f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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");
		}
	}
}