Introduction
Introduction Statistics Contact Development Disclaimer Help
cgi.c - frontends - front-ends for some sites (experiment)
Log
Files
Refs
README
LICENSE
---
cgi.c (10387B)
---
1 #include <sys/socket.h>
2 #include <sys/types.h>
3
4 #include <ctype.h>
5 #include <errno.h>
6 #include <netdb.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #include "https.h"
14 #include "util.h"
15 #include "youtube.h"
16
17 #define OUT(s) (fputs((s), stdout))
18
19 extern char **environ;
20
21 /* page title */
22 char title[1024];
23
24 /* CGI parameters */
25 static char rawsearch[4096], search[4096], order[16], page[64];
26 static char videoid[256];
27 static char channelid[256], userid[256];
28
29 /* Escape characters below as HTML 2.0 / XML 1.0.
30 Translate multi-line to <br/> */
31 void
32 xmlencode_multiline(const char *s)
33 {
34 for (; *s; s++) {
35 switch(*s) {
36 case '<': fputs("&lt;", stdout); break;
37 case '>': fputs("&gt;", stdout); break;
38 case '\'': fputs("&#39;", stdout); break;
39 case '&': fputs("&amp;", stdout); break;
40 case '"': fputs("&quot;", stdout); break;
41 case '\n': fputs("<br/>", stdout); break;
42 default: putchar(*s);
43 }
44 }
45 }
46
47 void
48 parsecgi(void)
49 {
50 char *query, *p;
51 size_t len;
52
53 if (!(query = getenv("QUERY_STRING")))
54 query = "";
55
56 /* order */
57 if ((p = getparam(query, "o"))) {
58 if (decodeparam(order, sizeof(order), p) == -1 ||
59 (strcmp(order, "date") &&
60 strcmp(order, "relevance") &&
61 strcmp(order, "views") &&
62 strcmp(order, "rating")))
63 order[0] = '\0';
64 }
65 if (!order[0])
66 snprintf(order, sizeof(order), "relevance");
67
68 /* search */
69 if ((p = getparam(query, "q"))) {
70 if ((len = strcspn(p, "&")) && len + 1 < sizeof(rawsearc…
71 memcpy(rawsearch, p, len);
72 rawsearch[len] = '\0';
73 }
74
75 if (decodeparam(search, sizeof(search), p) == -1) {
76 OUT("Status: 401 Bad Request\r\n\r\n");
77 exit(1);
78 }
79 }
80
81 /* channel ID */
82 if ((p = getparam(query, "chan"))) {
83 if (decodeparam(channelid, sizeof(channelid), p) == -1)
84 channelid[0] = '\0';
85 }
86
87 /* user ID */
88 if ((p = getparam(query, "user"))) {
89 if (decodeparam(userid, sizeof(userid), p) == -1)
90 userid[0] = '\0';
91 }
92
93 /* video ID */
94 if ((p = getparam(query, "v"))) {
95 if (decodeparam(videoid, sizeof(videoid), p) == -1)
96 videoid[0] = '\0';
97 }
98 }
99
100 void
101 header(void)
102 {
103 OUT(
104 "Content-Type: text/html; charset=utf-8\r\n\r\n"
105 "<!DOCTYPE html>\n<html>\n<head>\n"
106 "<meta name=\"referrer\" content=\"no-referrer\" />\n"
107 "<meta http-equiv=\"Content-Type\" content=\"text/html; …
108
109 if (title[0]) {
110 OUT("<title>");
111 xmlencode(title);
112 OUT("</title>");
113 }
114
115 OUT(
116 "<link rel=\"stylesheet\" href=\"css/style.css\" type=\"…
117 "<link rel=\"icon\" type=\"image/png\" href=\"/favicon.p…
118 "<meta content=\"width=device-width\" name=\"viewport\" …
119 "</head>\n"
120 "<body class=\"search\">\n"
121 "<form method=\"get\" action=\"\">\n");
122
123 OUT(
124 "<table class=\"search\" width=\"100%\" border=\"0\" cel…
125 "<tr>\n"
126 " <td width=\"100%\" class=\"input\">\n"
127 " <input type=\"search\" name=\"q\" value…
128 xmlencode(search);
129 OUT(
130 "\" placeholder=\"Search...\" size=\"72\" autofocus=\"au…
131 " </td>\n"
132 " <td nowrap class=\"nowrap\">\n"
133 " <input type=\"submit\" value=\"Search\"…
134 " <select name=\"o\" title=\"Order by\" a…
135 printf(" <option value=\"date\"%s>Creatio…
136 printf(" <option value=\"relevance\"%s>Re…
137 printf(" <option value=\"views\"%s>Views<…
138 printf(" <option value=\"rating\"%s>Ratin…
139 OUT(
140 " </select>\n"
141 " </td>\n"
142 "</tr>\n"
143 "</table>\n"
144 "</form>\n");
145 }
146
147 void
148 footer(void)
149 {
150 OUT("</body>\n</html>\n");
151 }
152
153 int
154 render_search(struct search_response *r)
155 {
156 struct item *v;
157 int n;
158 size_t i, len;
159
160 if (pledge("stdio", NULL) == -1) {
161 OUT("Status: 500 Internal Server Error\r\n\r\n");
162 exit(1);
163 }
164
165 n = -1;
166 if (search[0])
167 n = snprintf(title, sizeof(title), "Search: \"%s\" sorte…
168 else if (channelid[0])
169 n = snprintf(title, sizeof(title), "Channel videos: %s",…
170 else if (userid[0])
171 n = snprintf(title, sizeof(title), "User videos: %s", us…
172 if (n < 0 || n >= sizeof(title))
173 title[0] = '\0';
174
175 header();
176
177 if (r && r->nitems) {
178 OUT(
179 "<hr/>\n"
180 "<table class=\"videos\" width=\"100%\" border=\…
181 "<tbody>\n");
182
183 for (i = 0; i < r->nitems; i++) {
184 v = &(r->items[i]);
185
186 OUT("<tr class=\"v\">\n"
187 " <td class=\"thumb\" width=\"120\" align…
188
189 if (v->id[0]) {
190 OUT(" <a href=\"https://w…
191 xmlencode(v->id);
192 OUT("\"><img src=\"https://i.ytimg.com/v…
193 xmlencode(v->id);
194 OUT("/default.jpg\" alt=\"\" height=\"90…
195 } else {
196 /* placeholder image */
197 OUT(" <img src=\"https://…
198 }
199 OUT(" </td>\n"
200 " <td>\n"
201 " <span class=\"title\">"…
202
203 if (v->id[0]) {
204 OUT("<a href=\"https://www.youtube.com/e…
205 xmlencode(v->id);
206 printf("\" accesskey=\"%zu\"", i);
207 /* if (v->shortdescription[0]) {
208 OUT(" title=\"");
209 xmlencode(v->shortdescription);
210 OUT("\"");
211 }*/
212 OUT(">");
213 }
214
215 switch (v->linktype) {
216 case Channel:
217 OUT("[Channel] ");
218 xmlencode(v->channeltitle);
219 break;
220 case Movie:
221 OUT("[Movie] ");
222 xmlencode(v->title);
223 break;
224 case Playlist:
225 OUT("[Playlist] ");
226 xmlencode(v->title);
227 break;
228 default:
229 xmlencode(v->title);
230 break;
231 }
232
233 if (v->id[0])
234 OUT("</a>");
235
236 /* link to video information */
237 if (v->id[0]) {
238 OUT(" | <a href=\"?v=");
239 xmlencode(v->id);
240 OUT("\" title=\"More video details\">Det…
241 }
242
243 OUT(
244 "</span><br/>\n"
245 "\t\t<span class=\"channel\">");
246
247 if (v->channelid[0]) {
248 OUT("<a href=\"?chan=");
249 xmlencode(v->channelid);
250 OUT("\">");
251 xmlencode(v->channeltitle);
252 OUT("</a>");
253 } else if (v->userid[0]) {
254 OUT("<a href=\"?user=");
255 xmlencode(v->channelid);
256 OUT("\">");
257 xmlencode(v->channeltitle);
258 OUT("</a>");
259 } else {
260 xmlencode(v->channeltitle);
261 }
262
263 if (v->channelid[0] || v->userid[0]) {
264 OUT(" | <a title=\"");
265 xmlencode(v->channeltitle);
266 OUT(" Atom feed\" href=\"https://www.you…
267 if (v->channelid[0]) {
268 OUT("channel_id=");
269 xmlencode(v->channelid);
270 } else if (v->userid[0]) {
271 OUT("user=");
272 xmlencode(v->userid);
273 }
274 OUT("\">Atom feed</a>");
275 }
276
277 OUT("</span><br/>\n");
278 if (v->publishedat[0]) {
279 OUT(" <span class=\"publi…
280 OUT(v->publishedat);
281 OUT("</span><br/>\n");
282 }
283 OUT(" <span class=\"stats\">");
284 if (v->viewcount[0]) {
285 if (!printnumsep(v->viewcount))
286 OUT("0");
287 OUT(" views");
288 }
289 OUT(
290 "</span><br/>\n"
291 " </td>\n"
292 " <td align=\"right\" class=\"a-r…
293 " <span class=\"duration\…
294 OUT(v->duration);
295 OUT(
296 "</span>\n"
297 " </td>\n"
298 "</tr>\n"
299 "<tr class=\"hr\">\n"
300 " <td colspan=\"3\"><hr/></td>\n"
301 "</tr>\n");
302 }
303 OUT("</tbody>\n</table>\n");
304 }
305
306 footer();
307
308 return 0;
309 }
310
311 int
312 render_video(struct video_response *r)
313 {
314 char buf[256];
315 int n;
316
317 if (pledge("stdio", NULL) == -1) {
318 OUT("Status: 500 Internal Server Error\r\n\r\n");
319 exit(1);
320 }
321
322 n = snprintf(title, sizeof(title), "%s - %s", r->title, r->autho…
323 if (n < 0 || n >= sizeof(title))
324 title[0] = '\0';
325
326 header();
327
328 OUT("<hr/>\n");
329
330 OUT("<table class=\"video\" border=\"0\" cellpadding=\"0\" cells…
331 OUT("<tbody>\n");
332
333 OUT("<tr><td colspan=\"2\"><center>\n");
334 OUT("<a href=\"https://www.youtube.com/embed/");
335 xmlencode(r->id);
336 OUT("\"><img src=\"https://i.ytimg.com/vi/");
337 xmlencode(r->id);
338 OUT("/hqdefault.jpg\" alt=\"\" border=\"0\" /></a>\n");
339 OUT("</center><br/></td></tr>\n");
340
341 OUT("<tr><td><b>Title:</b></td><td>");
342 OUT("<a href=\"https://www.youtube.com/embed/");
343 xmlencode(r->id);
344 OUT("\">");
345 xmlencode(r->title);
346 OUT("</a></td></tr>\n");
347
348 if (r->lengthseconds > 0) {
349 OUT("<tr><td><b>Length:</b></td><td>");
350 if (durationstr(r->lengthseconds, buf, sizeof(buf)) < si…
351 xmlencode(buf);
352 OUT("</td></tr>\n");
353 }
354
355 if (r->author[0]) {
356 OUT("<tr><td><b>Channel:</b></td><td>");
357 if (r->channelid[0]) {
358 OUT("<a href=\"?chan=");
359 xmlencode(r->channelid);
360 OUT("\">");
361 xmlencode(r->author);
362 OUT("</a>");
363 OUT(": <a href=\"https://www.youtube.com/feeds/v…
364 xmlencode(r->channelid);
365 OUT("\">Atom feed</a>");
366 } else {
367 xmlencode(r->author);
368 }
369 OUT("</td></tr>\n");
370 }
371
372 OUT("<tr><td><b>Views:</b></td><td>");
373 snprintf(buf, sizeof(buf), "%ld", r->viewcount);
374 if (!printnumsep(buf))
375 OUT("0");
376 OUT("</td></tr>\n");
377
378 if (r->publishdate[0]) {
379 OUT("<tr><td><b>Published:</b></td><td>");
380 xmlencode(r->publishdate);
381 OUT("</td></tr>\n");
382 }
383
384 if (r->uploaddate[0]) {
385 OUT("<tr><td><b>Uploaded:</b></td><td>");
386 xmlencode(r->uploaddate);
387 OUT("</td></tr>\n");
388 }
389
390 if (r->shortdescription[0]) {
391 OUT("<tr><td valign=\"top\"><b>Description:&nbsp;</b></t…
392 xmlencode_multiline(r->shortdescription);
393 OUT("</code></td></tr>\n");
394 }
395
396 OUT("</tbody>\n");
397 OUT("</table>\n");
398
399 footer();
400
401 return 0;
402 }
403
404 int
405 main(void)
406 {
407 struct search_response *r = NULL;
408 struct video_response *vr = NULL;
409
410 if (pledge("stdio dns inet rpath unveil", NULL) == -1 ||
411 unveil(TLS_CA_CERT_FILE, "r") == -1 ||
412 unveil(NULL, NULL) == -1) {
413 OUT("Status: 500 Internal Server Error\r\n\r\n");
414 exit(1);
415 }
416
417 parsecgi();
418
419 if (rawsearch[0]) {
420 r = youtube_search(rawsearch, page, order);
421 } else if (channelid[0]) {
422 r = youtube_channel_videos(channelid);
423 } else if (userid[0]) {
424 r = youtube_user_videos(userid);
425 } else if (videoid[0]) {
426 vr = youtube_video(videoid);
427 if (!vr || vr->isfound == 0) {
428 OUT("Status: 500 Internal Server Error\r\n\r\n");
429 exit(1);
430 }
431 render_video(vr);
432 return 0;
433 } else {
434 goto show;
435 }
436 if (!r || r->nitems == 0) {
437 OUT("Status: 500 Internal Server Error\r\n\r\n");
438 exit(1);
439 }
440
441 show:
442 render_search(r);
443
444 return 0;
445 }
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.