/* ui-shared.c: common web output functions * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" #include "cmd.h" #include "html.h" const char cgit_doctype[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; static char *http_date(time_t t) { static char day[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; struct tm *tm = gmtime(&t); return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } void cgit_print_error(char *msg) { html("<div class='error'>"); html_txt(msg); html("</div>\n"); } char *cgit_httpscheme() { if (ctx.env.https && !strcmp(ctx.env.https, "on")) return "https://"; else return "http://"; } char *cgit_hosturl() { if (ctx.env.http_host) return ctx.env.http_host; if (!ctx.env.server_name) return NULL; if (!ctx.env.server_port || atoi(ctx.env.server_port) == 80) return ctx.env.server_name; return xstrdup(fmt("%s:%s", ctx.env.server_name, ctx.env.server_port)); } char *cgit_rooturl() { if (ctx.cfg.virtual_root) return fmt("%s/", ctx.cfg.virtual_root); else return ctx.cfg.script_name; } char *cgit_repourl(const char *reponame) { if (ctx.cfg.virtual_root) { return fmt("%s/%s/", ctx.cfg.virtual_root, reponame); } else { return fmt("?r=%s", reponame); } } char *cgit_fileurl(const char *reponame, const char *pagename, const char *filename, const char *query) { char *tmp; char *delim; if (ctx.cfg.virtual_root) { tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame, pagename, (filename ? filename:"")); delim = "?"; } else { tmp = fmt("?url=%s/%s/%s", reponame, pagename, (filename ? filename : "")); delim = "&"; } if (query) tmp = fmt("%s%s%s", tmp, delim, query); return tmp; } char *cgit_pageurl(const char *reponame, const char *pagename, const char *query) { return cgit_fileurl(reponame,pagename,0,query); } const char *cgit_repobasename(const char *reponame) { /* I assume we don't need to store more than one repo basename */ static char rvbuf[1024]; int p; const char *rv; strncpy(rvbuf,reponame,sizeof(rvbuf)); if(rvbuf[sizeof(rvbuf)-1]) die("cgit_repobasename: truncated repository name '%s'", reponame); p = strlen(rvbuf)-1; /* strip trailing slashes */ while(p && rvbuf[p]=='/') rvbuf[p--]=0; /* strip trailing .git */ if(p>=3 && !strncmp(&rvbuf[p-3],".git",4)) { p -= 3; rvbuf[p--] = 0; } /* strip more trailing slashes if any */ while( p && rvbuf[p]=='/') rvbuf[p--]=0; /* find last slash in the remaining string */ rv = strrchr(rvbuf,'/'); if(rv) return ++rv; return rvbuf; } char *cgit_currurl() { if (!ctx.cfg.virtual_root) return ctx.cfg.script_name; else if (ctx.qry.page) return fmt("%s/%s/%s/", ctx.cfg.virtual_root, ctx.qry.repo, ctx.qry.page); else if (ctx.qry.repo) return fmt("%s/%s/", ctx.cfg.virtual_root, ctx.qry.repo); else return fmt("%s/", ctx.cfg.virtual_root); } static void site_url(char *page, char *search, int ofs) { char *delim = "?"; if (ctx.cfg.virtual_root) { html_attr(ctx.cfg.virtual_root); if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') html("/"); } else html(ctx.cfg.script_name); if (page) { htmlf("?p=%s", page); delim = "&"; } if (search) { html(delim); html("q="); html_attr(search); delim = "&"; } if (ofs) { html(delim); htmlf("ofs=%d", ofs); } } static void site_link(char *page, char *name, char *title, char *class, char *search, int ofs) { html("<a"); if (title) { html(" title='"); html_attr(title); html("'"); } if (class) { html(" class='"); html_attr(class); html("'"); } html(" href='"); site_url(page, search, ofs); html("'>"); html_txt(name); html("</a>"); } void cgit_index_link(char *name, char *title, char *class, char *pattern, int ofs) { site_link(NULL, name, title, class, pattern, ofs); } static char *repolink(char *title, char *class, char *page, char *head, char *path) { char *delim = "?"; html("<a"); if (title) { html(" title='"); html_attr(title); html("'"); } if (class) { html(" class='"); html_attr(class); html("'"); } html(" href='"); if (ctx.cfg.virtual_root) { html_url_path(ctx.cfg.virtual_root); if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') html("/"); html_url_path(ctx.repo->url); if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') html("/"); if (page) { html_url_path(page); html("/"); if (path) html_url_path(path); } } else { html(ctx.cfg.script_name); html("?url="); html_url_arg(ctx.repo->url); if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') html("/"); if (page) { html_url_arg(page); html("/"); if (path) html_url_arg(path); } delim = "&"; } if (head && strcmp(head, ctx.repo->defbranch)) { html(delim); html("h="); html_url_arg(head); delim = "&"; } return fmt("%s", delim); } static void reporevlink(char *page, char *name, char *title, char *class, char *head, char *rev, char *path) { char *delim; delim = repolink(title, class, page, head, path);<style>pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="cm">/* configfile.c: parsing of config files</span> <span class="cm"> *</span> <span class="cm"> * Copyright (C) 2008 Lars Hjemli</span> <span class="cm"> *</span> <span class="cm"> * Licensed under GNU General Public License v2</span> <span class="cm"> * (see COPYING for full license text)</span> <span class="cm"> */</span> <span class="cp">#include</span><span class="w"> </span><span class="cpf"><ctype.h></span> <span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span> <span class="cp">#include</span><span class="w"> </span><span class="cpf">"configfile.h"</span> <span class="kt">int</span><span class="w"> </span><span class="nf">next_char</span><span class="p">(</span><span class="kt">FILE</span><span class="w"> </span><span class="o">*</span><span class="n">f</span><span class="p">)</span> <span class="p">{</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fgetc</span><span class="p">(</span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="o">==</span><span class="sc">'\r'</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fgetc</span><span class="p">(</span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="o">!=</span><span class="sc">'\n'</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">ungetc</span><span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sc">'\r'</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">c</span><span class="p">;</span> <span class="p">}</span> <span class="kt">void</span><span class="w"> </span><span class="nf">skip_line</span><span class="p">(</span><span class="kt">FILE</span><span class="w"> </span><span class="o">*</span><span class="n">f</span><span class="p">)</span> <span class="p">{</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">c</span><span class="p">;</span> <span class="w"> </span><span class="k">while</span><span class="p">((</span><span class="n">c</span><span class="o">=</span><span class="n">next_char</span><span class="p">(</span><span class="n">f</span><span class="p">))</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">c</span><span class="o">!=</span><span class="sc">'\n'</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">c</span><span class="o">!=</span><span class="n">EOF</span><span class="p">)</span> <span class="w"> </span><span class="p">;</span> <span class="p">}</span> <span class="kt">int</span><span class="w"> </span><span class="nf">read_config_line</span><span class="p">(</span><span class="kt">FILE</span><span class="w"> </span><span class="o">*</span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">line</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">bufsize</span><span class="p">)</span> <span class="p">{</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">isname</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span> <span class="w"> </span><span class="o">*</span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span> <span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">i</span><span class="o"><</span><span class="n">bufsize</span><span class="mi">-1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">next_char</span><span class="p">(</span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">isname</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="o">==</span><span class="sc">'#'</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="o">==</span><span class="sc">';'</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">skip_line</span><span class="p">(</span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="k">continue</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">isname</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">isspace</span><span class="p">(</span><span class="n">c</span><span class="p">))</span> <span class="w"> </span><span class="k">continue</span><span class="p">;</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="o">==</span><span class="sc">'='</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!*</span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">line</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span> <span class="w"> </span><span class="o">*</span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&</span><span class="n">line</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span> <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="o">==</span><span class="sc">'\n'</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">isname</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w