youtube/cgi: output improvements - frontends - front-ends for some sites (experiment) (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit 4d8ef4606fcdb808af8b505fc84318f22fe1c552 (DIR) parent 2237f8c69f34d8f48a37e34d1462d327b9ddc40d (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org> 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(-) --- (DIR) 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; charset=UTF-8\" />\n"); - 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/css\" media=\"screen\" />\n" "<link rel=\"icon\" type=\"image/png\" href=\"/favicon.png\" />\n" @@ -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 %s", search, order); + else if (channelid[0]) + n = snprintf(title, sizeof(title), "Channel videos: %s", channelid); + 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</a>"); } 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>-->\n"); - } - 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=\"0\">\n"); + 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(buf)) 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.xml?channel_id="); + 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?channel_id="); - 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><code>"); + xmlencode_multiline(r->shortdescription); + OUT("</code></td></tr>\n"); } - OUT("</pre>"); + OUT("</tbody>\n"); + OUT("</table>\n"); footer();