youtube/cgi: output improvements - frontends - front-ends for some sites (exper… | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 4d8ef4606fcdb808af8b505fc84318f22fe1c552 | |
parent 2237f8c69f34d8f48a37e34d1462d327b9ddc40d | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sun, 26 Feb 2023 13:47:32 +0100 | |
youtube/cgi: output improvements | |
Diffstat: | |
M youtube/cgi.c | 169 ++++++++++++++++-------------… | |
1 file changed, 86 insertions(+), 83 deletions(-) | |
--- | |
diff --git a/youtube/cgi.c b/youtube/cgi.c | |
@@ -18,13 +18,32 @@ | |
extern char **environ; | |
-static int curpage = 1; | |
+/* page title */ | |
+char title[1024]; | |
/* CGI parameters */ | |
static char rawsearch[4096], search[4096], order[16], page[64]; | |
static char videoid[256]; | |
static char channelid[256], userid[256]; | |
+/* Escape characters below as HTML 2.0 / XML 1.0. | |
+ Translate multi-line to <br/> */ | |
+void | |
+xmlencode_multiline(const char *s) | |
+{ | |
+ for (; *s; s++) { | |
+ switch(*s) { | |
+ case '<': fputs("<", stdout); break; | |
+ case '>': fputs(">", stdout); break; | |
+ case '\'': fputs("'", stdout); break; | |
+ case '&': fputs("&", stdout); break; | |
+ case '"': fputs(""", stdout); break; | |
+ case '\n': fputs("<br/>", stdout); break; | |
+ default: putchar(*s); | |
+ } | |
+ } | |
+} | |
+ | |
void | |
parsecgi(void) | |
{ | |
@@ -46,19 +65,6 @@ parsecgi(void) | |
if (!order[0]) | |
snprintf(order, sizeof(order), "relevance"); | |
- /* page */ | |
- if ((p = getparam(query, "page"))) { | |
- if (decodeparam(page, sizeof(page), p) == -1) | |
- page[0] = '\0'; | |
- /* check if it's a number > 0 and < 100 */ | |
- errno = 0; | |
- curpage = strtol(page, NULL, 10); | |
- if (errno || curpage < 0 || curpage > 100) { | |
- curpage = 1; | |
- page[0] = '\0'; | |
- } | |
- } | |
- | |
/* search */ | |
if ((p = getparam(query, "q"))) { | |
if ((len = strcspn(p, "&")) && len + 1 < sizeof(rawsearch)) { | |
@@ -100,15 +106,12 @@ header(void) | |
"<meta name=\"referrer\" content=\"no-referrer\" />\n" | |
"<meta http-equiv=\"Content-Type\" content=\"text/html; charse… | |
- if (videoid[0]) { | |
- OUT("<title>Video: "); | |
- xmlencode(videoid); | |
+ if (title[0]) { | |
+ OUT("<title>"); | |
+ xmlencode(title); | |
OUT("</title>"); | |
- } else { | |
- OUT("<title>Search: \""); | |
- xmlencode(search); | |
- printf("\" sorted by %s</title>\n", order); | |
} | |
+ | |
OUT( | |
"<link rel=\"stylesheet\" href=\"css/style.css\" type=\"text/c… | |
"<link rel=\"icon\" type=\"image/png\" href=\"/favicon.png\" /… | |
@@ -152,6 +155,7 @@ render_search(struct search_response *r) | |
{ | |
struct item *v; | |
char tmp[64]; | |
+ int n; | |
size_t i; | |
if (pledge("stdio", NULL) == -1) { | |
@@ -159,6 +163,16 @@ render_search(struct search_response *r) | |
exit(1); | |
} | |
+ n = -1; | |
+ if (search[0]) | |
+ n = snprintf(title, sizeof(title), "Search: \"%s\" sorted by %… | |
+ else if (channelid[0]) | |
+ n = snprintf(title, sizeof(title), "Channel videos: %s", chann… | |
+ else if (userid[0]) | |
+ n = snprintf(title, sizeof(title), "User videos: %s", userid); | |
+ if (n < 0 || n >= sizeof(title)) | |
+ title[0] = '\0'; | |
+ | |
header(); | |
if (r && r->nitems) { | |
@@ -222,9 +236,9 @@ render_search(struct search_response *r) | |
/* link to video information */ | |
if (v->id[0]) { | |
- OUT(" <a href=\"?v="); | |
+ OUT(" | <a href=\"?v="); | |
xmlencode(v->id); | |
- OUT("\">[I]</a>"); | |
+ OUT("\" title=\"More video details\">Details</… | |
} | |
OUT( | |
@@ -283,38 +297,7 @@ render_search(struct search_response *r) | |
" <td colspan=\"3\"><hr/></td>\n" | |
"</tr>\n"); | |
} | |
- OUT("</tbody>\n"); | |
- | |
- OUT( | |
- "<tfoot>\n" | |
- "<tr>\n" | |
- "\t<td align=\"left\" class=\"nowrap\" nowrap>\n"); | |
- if (curpage > 1) { | |
- OUT("\t\t<!--<a href=\"?q="); | |
- xmlencode(search); | |
- OUT("&page="); | |
- snprintf(tmp, sizeof(tmp), "%d", curpage - 1); | |
- xmlencode(tmp); | |
- OUT("&o="); | |
- xmlencode(order); | |
- OUT("\" rel=\"prev\" accesskey=\"p\">← prev</a>--… | |
- } | |
- OUT( | |
- "\t</td>\n\t<td></td>\n" | |
- "\t<td align=\"right\" class=\"a-r nowrap\" nowrap>\n"… | |
- | |
- OUT("\t\t<!--<a href=\"?q="); | |
- xmlencode(search); | |
- OUT("&page="); | |
- snprintf(tmp, sizeof(tmp), "%d", curpage + 1); | |
- xmlencode(tmp); | |
- OUT("&o="); | |
- xmlencode(order); | |
- OUT("\" rel=\"next\" accesskey=\"n\">next →</a>-->\n" | |
- "\t</td>\n" | |
- "</tr>\n" | |
- "</tfoot>\n" | |
- "</table>\n"); | |
+ OUT("</tbody>\n</table>\n"); | |
} | |
footer(); | |
@@ -326,65 +309,85 @@ int | |
render_video(struct video_response *r) | |
{ | |
char buf[256]; | |
+ int n; | |
if (pledge("stdio", NULL) == -1) { | |
OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
exit(1); | |
} | |
+ n = snprintf(title, sizeof(title), "%s - %s", r->title, r->author); | |
+ if (n < 0 || n >= sizeof(title)) | |
+ title[0] = '\0'; | |
+ | |
header(); | |
- OUT("<pre>"); | |
+ OUT("<hr/>\n"); | |
- OUT("URL: "); | |
- OUT("https://www.youtube.com/embed/"); | |
+ OUT("<center><a href=\"https://www.youtube.com/embed/"); | |
xmlencode(r->id); | |
- OUT("\n"); | |
+ OUT("\"><img src=\"https://i.ytimg.com/vi/"); | |
+ xmlencode(r->id); | |
+ OUT("/hqdefault.jpg\" alt=\"\" border=\"0\" /></a></center>\n"); | |
+ | |
+ OUT("<table class=\"video\" border=\"0\" cellpadding=\"0\" cellspacing… | |
+ OUT("<tbody>\n"); | |
- OUT("Title: "); | |
+ OUT("<tr><td><b>Title:</b></td><td>"); | |
+ OUT("<a href=\"https://www.youtube.com/embed/"); | |
+ xmlencode(r->id); | |
+ OUT("\">"); | |
xmlencode(r->title); | |
- OUT("\n"); | |
+ OUT("</a></td></tr>\n"); | |
if (r->lengthseconds > 0) { | |
- OUT("Length: "); | |
+ OUT("<tr><td><b>Length:</b></td><td>"); | |
if (durationstr(r->lengthseconds, buf, sizeof(buf)) < sizeof(b… | |
xmlencode(buf); | |
- OUT("\n"); | |
+ OUT("</td></tr>\n"); | |
+ } | |
+ | |
+ if (r->author[0]) { | |
+ OUT("<tr><td><b>Channel:</b></td><td>"); | |
+ if (r->channelid[0]) { | |
+ OUT("<a href=\"?chan="); | |
+ xmlencode(r->channelid); | |
+ OUT("\">"); | |
+ xmlencode(r->author); | |
+ OUT("</a>"); | |
+ OUT(": <a href=\"https://www.youtube.com/feeds/videos.… | |
+ xmlencode(r->channelid); | |
+ OUT("\">Atom feed</a>"); | |
+ } else { | |
+ xmlencode(r->author); | |
+ } | |
+ OUT("</td></tr>\n"); | |
} | |
- OUT("Views: "); | |
+ OUT("<tr><td><b>Views:</b></td><td>"); | |
printf("%ld", r->viewcount); | |
- OUT("\n"); | |
+ OUT("</td></tr>\n"); | |
if (r->publishdate[0]) { | |
- OUT("Published: "); | |
+ OUT("<tr><td><b>Published:</b></td><td>"); | |
xmlencode(r->publishdate); | |
- OUT("\n"); | |
+ OUT("</td></tr>\n"); | |
} | |
if (r->uploaddate[0]) { | |
- OUT("Uploaded: "); | |
+ OUT("<tr><td><b>Uploaded:</b></td><td>"); | |
xmlencode(r->uploaddate); | |
- OUT("\n"); | |
- } | |
- | |
- if (r->author[0]) { | |
- OUT("Channel: "); | |
- xmlencode(r->author); | |
- if (r->channelid[0]) { | |
- OUT(": https://www.youtube.com/feeds/videos.xml?channe… | |
- xmlencode(r->channelid); | |
- } | |
- OUT("\n"); | |
+ OUT("</td></tr>\n"); | |
} | |
if (r->shortdescription[0]) { | |
- OUT("Description:\n\n"); | |
- xmlencode(r->shortdescription); | |
- OUT("\n"); | |
+ OUT("<tr><td valign=\"top\"><b>Description: </b></td><td>… | |
+ xmlencode_multiline(r->shortdescription); | |
+ OUT("</code></td></tr>\n"); | |
} | |
- OUT("</pre>"); | |
+ OUT("</tbody>\n"); | |
+ OUT("</table>\n"); | |
footer(); | |