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("&lt;", stdout);   break;
       +                case '>':  fputs("&gt;", stdout);   break;
       +                case '\'': fputs("&#39;", stdout);  break;
       +                case '&':  fputs("&amp;", stdout);  break;
       +                case '"':  fputs("&quot;", 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("&amp;page=");
       -                        snprintf(tmp, sizeof(tmp), "%d", curpage - 1);
       -                        xmlencode(tmp);
       -                        OUT("&amp;o=");
       -                        xmlencode(order);
       -                        OUT("\" rel=\"prev\" accesskey=\"p\">&larr; 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("&amp;page=");
       -                snprintf(tmp, sizeof(tmp), "%d", curpage + 1);
       -                xmlencode(tmp);
       -                OUT("&amp;o=");
       -                xmlencode(order);
       -                OUT("\" rel=\"next\" accesskey=\"n\">next &rarr;</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:&nbsp;</b></td><td><code>");
       +                xmlencode_multiline(r->shortdescription);
       +                OUT("</code></td></tr>\n");
                }
        
       -        OUT("</pre>");
       +        OUT("</tbody>\n");
       +        OUT("</table>\n");
        
                footer();