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");
}
}
}
|