Introduction
Introduction Statistics Contact Development Disclaimer Help
jf2atom.c - jfconvert - JSON Feed (subset) to sfeed or Atom converter
git clone git://git.codemadness.org/jfconvert
Log
Files
Refs
README
LICENSE
---
jf2atom.c (7078B)
---
1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #ifdef __OpenBSD__
7 #include <unistd.h>
8 #else
9 #define pledge(a,b) 0
10 #endif
11
12 #include "json.h"
13
14 /* control-character in the ASCII range 0-127: compatible with UTF-8 */
15 #define ISCNTRL(c) ((c) < ' ' || (c) == 0x7f)
16
17 /* compare attributes case-sensitively */
18 #define attrcmp strcmp
19
20 static int itemisopen = 0, enclosureisopen = 0;
21
22 /* Escape characters below as HTML 2.0 / XML 1.0. */
23 void
24 xmlencode(const char *s, FILE *fp)
25 {
26 for (; *s; ++s) {
27 switch (*s) {
28 case '<': fputs("&lt;", fp); break;
29 case '>': fputs("&gt;", fp); break;
30 case '\'': fputs("&#39;", fp); break;
31 case '&': fputs("&amp;", fp); break;
32 case '"': fputs("&quot;", fp); break;
33 default: putc(*s, fp);
34 }
35 }
36 }
37
38 void
39 processnode(struct json_node *nodes, size_t depth, const char *value, si…
40 {
41 const char *outtag, *outtype, *outhref;
42
43 /* feed / channel */
44 if (depth == 2) {
45 if (nodes[0].type == JSON_TYPE_OBJECT) {
46 if (nodes[1].type == JSON_TYPE_STRING) {
47 if (!attrcmp(nodes[1].name, "title")) {
48 fputs("<title type=\"text\">", s…
49 xmlencode(value, stdout);
50 fputs("</title>\n", stdout);
51 } else if (!attrcmp(nodes[1].name, "home…
52 fputs("<link rel=\"alternate\" t…
53 xmlencode(value, stdout);
54 fputs("\" />\n", stdout);
55 } else if (!attrcmp(nodes[1].name, "desc…
56 fputs("<subtitle>", stdout);
57 xmlencode(value, stdout);
58 fputs("</subtitle>\n", stdout);
59 }
60 }
61 }
62 }
63
64 /* item */
65 if (depth == 3) {
66 if (nodes[0].type == JSON_TYPE_OBJECT &&
67 nodes[1].type == JSON_TYPE_ARRAY &&
68 nodes[2].type == JSON_TYPE_OBJECT &&
69 !attrcmp(nodes[1].name, "items")) {
70 if (enclosureisopen) {
71 fputs(" />\n", stdout);
72 enclosureisopen = 0;
73 }
74 if (itemisopen)
75 fputs("</entry>\n", stdout);
76 fputs("<entry>\n", stdout);
77 itemisopen = 1;
78 }
79 }
80
81 /* item attributes */
82 if (depth == 4) {
83 if (nodes[0].type == JSON_TYPE_OBJECT &&
84 nodes[1].type == JSON_TYPE_ARRAY &&
85 nodes[2].type == JSON_TYPE_OBJECT &&
86 !attrcmp(nodes[1].name, "items")) {
87 outtag = NULL;
88 outtype = NULL;
89 outhref = NULL;
90
91 if (!attrcmp(nodes[3].name, "content_html")) {
92 outtag = "content";
93 outtype = "html";
94 } else if (!attrcmp(nodes[3].name, "content_text…
95 outtag = "content";
96 outtype = "text";
97 } else if (!attrcmp(nodes[3].name, "date_publish…
98 outtag = "published";
99 } else if (!attrcmp(nodes[3].name, "date_modifie…
100 outtag = "updated";
101 } else if (!attrcmp(nodes[3].name, "id")) {
102 outtag = "id";
103 } else if (!attrcmp(nodes[3].name, "summary")) {
104 outtag = "summary";
105 } else if (!attrcmp(nodes[3].name, "title")) {
106 outtag = "title";
107 } else if (!attrcmp(nodes[3].name, "url")) {
108 outtag = "link";
109 outhref = value;
110 value = NULL;
111 }
112
113 if (outtag) {
114 fputs("\t<", stdout);
115 fputs(outtag, stdout);
116 if (outhref) {
117 fputs(" href=\"", stdout);
118 xmlencode(outhref, stdout);
119 fputs("\"", stdout);
120 }
121 if (outtype) {
122 fputs(" type=\"", stdout);
123 xmlencode(outtype, stdout);
124 fputs("\"", stdout);
125 }
126 fputs(">", stdout);
127 if (value)
128 xmlencode(value, stdout);
129 fputs("</", stdout);
130 fputs(outtag, stdout);
131 fputs(">\n", stdout);
132 }
133 }
134 }
135
136 if (depth == 5) {
137 /* 1.0 author name */
138 if (nodes[0].type == JSON_TYPE_OBJECT &&
139 nodes[1].type == JSON_TYPE_ARRAY &&
140 nodes[2].type == JSON_TYPE_OBJECT &&
141 nodes[3].type == JSON_TYPE_OBJECT &&
142 nodes[4].type == JSON_TYPE_STRING &&
143 !attrcmp(nodes[1].name, "items") &&
144 !attrcmp(nodes[3].name, "author") &&
145 !attrcmp(nodes[4].name, "name")) {
146 fputs("\t<author><name>", stdout);
147 xmlencode(value, stdout);
148 fputs("</name></author>\n", stdout);
149 }
150
151 /* tags / categories */
152 if (nodes[0].type == JSON_TYPE_OBJECT &&
153 nodes[1].type == JSON_TYPE_ARRAY &&
154 nodes[2].type == JSON_TYPE_OBJECT &&
155 nodes[3].type == JSON_TYPE_ARRAY &&
156 nodes[4].type == JSON_TYPE_STRING &&
157 !attrcmp(nodes[1].name, "items") &&
158 !attrcmp(nodes[3].name, "tags")) {
159 fputs("\t<category term=\"", stdout);
160 xmlencode(value, stdout);
161 fputs("\" />\n", stdout);
162 }
163
164 /* enclosure */
165 if (nodes[0].type == JSON_TYPE_OBJECT &&
166 nodes[1].type == JSON_TYPE_ARRAY &&
167 nodes[2].type == JSON_TYPE_OBJECT &&
168 nodes[3].type == JSON_TYPE_ARRAY &&
169 nodes[4].type == JSON_TYPE_OBJECT &&
170 !attrcmp(nodes[1].name, "items") &&
171 !attrcmp(nodes[3].name, "attachments")) {
172 if (enclosureisopen)
173 fputs(" />\n", stdout);
174 fputs("\t<link rel=\"enclosure\"", stdout);
175 enclosureisopen = 1;
176 }
177 }
178
179 if (depth == 6) {
180 /* 1.1 author name */
181 if (nodes[0].type == JSON_TYPE_OBJECT &&
182 nodes[1].type == JSON_TYPE_ARRAY &&
183 nodes[2].type == JSON_TYPE_OBJECT &&
184 nodes[3].type == JSON_TYPE_ARRAY &&
185 nodes[4].type == JSON_TYPE_OBJECT &&
186 nodes[5].type == JSON_TYPE_STRING &&
187 !attrcmp(nodes[1].name, "items") &&
188 !attrcmp(nodes[3].name, "authors") &&
189 !attrcmp(nodes[5].name, "name")) {
190 fputs("\t<author><name>", stdout);
191 xmlencode(value, stdout);
192 fputs("</name></author>\n", stdout);
193 }
194
195 /* enclosure attributes */
196 if (nodes[0].type == JSON_TYPE_OBJECT &&
197 nodes[1].type == JSON_TYPE_ARRAY &&
198 nodes[2].type == JSON_TYPE_OBJECT &&
199 nodes[3].type == JSON_TYPE_ARRAY &&
200 nodes[4].type == JSON_TYPE_OBJECT &&
201 (nodes[5].type == JSON_TYPE_STRING || nodes[5].type …
202 !attrcmp(nodes[1].name, "items") &&
203 !attrcmp(nodes[3].name, "attachments")) {
204 if (!attrcmp(nodes[5].name, "url")) {
205 fputs(" href=\"", stdout);
206 xmlencode(value, stdout);
207 fputs("\"", stdout);
208 } else if (!attrcmp(nodes[5].name, "mime_type"))…
209 fputs(" type=\"", stdout);
210 xmlencode(value, stdout);
211 fputs("\"", stdout);
212 } else if (!attrcmp(nodes[5].name, "size_in_byte…
213 fputs(" length=\"", stdout);
214 xmlencode(value, stdout);
215 fputs("\"", stdout);
216 }
217 }
218 }
219
220 if (ferror(stdout)) {
221 fprintf(stderr, "write error: <stdout>\n");
222 exit(2);
223 }
224 }
225
226 int
227 main(int argc, char *argv[])
228 {
229 if (pledge("stdio", NULL) == -1) {
230 fprintf(stderr, "pledge stdio: %s\n", strerror(errno));
231 return 1;
232 }
233
234 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
235 "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n", stdout);
236
237 switch (parsejson(processnode)) {
238 case JSON_ERROR_MEM:
239 fputs("error: cannot allocate enough memory\n", stderr);
240 return 2;
241 case JSON_ERROR_INVALID:
242 fputs("error: invalid JSON\n", stderr);
243 return 1;
244 }
245
246 if (enclosureisopen)
247 fputs(" />\n", stdout);
248 if (itemisopen)
249 fputs("</entry>\n", stdout);
250 fputs("</feed>\n", stdout);
251
252 if (ferror(stdin)) {
253 fprintf(stderr, "read error: <stdin>\n");
254 return 2;
255 }
256 if (fflush(stdout) || ferror(stdout)) {
257 fprintf(stderr, "write error: <stdout>\n");
258 return 2;
259 }
260
261 return 0;
262 }
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.