summaryrefslogtreecommitdiff
path: root/handler.c
blob: 782a3e2be3ab21054d5032d4e52c274df6e912e7 (plain)
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
#include <stdio.h>
#include <stdbool.h>
#include <tidy.h>
#include <tidybuffio.h>
#include <interchange.h>

#define SUBDIR "/items"

static void recurse_catalog(TidyDoc doc, TidyNode tnod, const char *image_dir,
		struct interchange_catalog **catalog)
{
	for (TidyNode child = tidyGetChild(tnod); child; child = tidyGetNext(child)) {
		ctmbstr name = tidyNodeGetName(child);
		if (!name)
		       continue;
		if (strcmp(name, "img")) {
			recurse_catalog(doc, child, image_dir, catalog);
			continue;
		}
		char prefix[strlen(image_dir) + strlen(SUBDIR) + 1];
		sprintf(prefix, "%s%s", image_dir, SUBDIR);
		size_t prefix_len = strlen(prefix);
		bool bail = false;
		for (TidyAttr attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr))
			if (!strcmp(tidyAttrName(attr), "src")
					&& strncmp(tidyAttrValue(attr), prefix, prefix_len)) {
				bail = true;
				break;
			}
		if (bail)
			continue;
		struct interchange_product *product = malloc(sizeof(struct interchange_product));
		memset(product, '\0', sizeof(struct interchange_product));
		for (TidyAttr attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) {
			name = tidyAttrName(attr);
			ctmbstr value = tidyAttrValue(attr);
			if (!strcmp(name, "src")) {
				size_t len = strlen(value) - prefix_len;
				product->image = malloc(len + 1);
				strncpy(product->image, value + prefix_len, len + 1);
			} else if (!strcmp(name, "alt")) {
				product->description = malloc(strlen(value) + 1);
				strcpy(product->description, value);
			} else if (!strcmp(name, "title")) {
				product->sku = malloc(strlen(value + 1));
				strcpy(product->sku, value);
			}
		}
		(*catalog)->length++;
		*catalog = realloc(*catalog, sizeof(struct interchange_catalog)
				+ sizeof(struct interchange_product *[(*catalog)->length]));
		(*catalog)->products[(*catalog)->length - 1] = product;
	}
}

struct interchange_catalog *catalog(const char *response, const char *image_dir)
{
	TidyDoc tdoc = tidyCreate();
	TidyBuffer output = {0};
	tidyParseString(tdoc, response);
	tidySaveBuffer(tdoc, &output);
	struct interchange_catalog *catalog = malloc(sizeof(struct interchange_catalog));
	catalog->length = 0;
	recurse_catalog(tdoc, tidyGetRoot(tdoc), image_dir, &catalog);
	tidyBufFree(&output);
	tidyRelease(tdoc);
	return catalog;
}