summaryrefslogtreecommitdiffabout
path: root/ui-shared.c
Unidiff
Diffstat (limited to 'ui-shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-shared.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/ui-shared.c b/ui-shared.c
index cc1ab8b..2eff79d 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -1,105 +1,106 @@
1/* ui-shared.c: common web output functions 1/* ui-shared.c: common web output functions
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h"
10 11
11const char cgit_doctype[] = 12const char cgit_doctype[] =
12"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" 13"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
13" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; 14" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
14 15
15static char *http_date(time_t t) 16static char *http_date(time_t t)
16{ 17{
17 static char day[][4] = 18 static char day[][4] =
18 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 19 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
19 static char month[][4] = 20 static char month[][4] =
20 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 21 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
21 "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; 22 "Jul", "Aug", "Sep", "Oct", "Now", "Dec"};
22 struct tm *tm = gmtime(&t); 23 struct tm *tm = gmtime(&t);
23 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], 24 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
24 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, 25 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year,
25 tm->tm_hour, tm->tm_min, tm->tm_sec); 26 tm->tm_hour, tm->tm_min, tm->tm_sec);
26} 27}
27 28
28static long ttl_seconds(long ttl) 29static long ttl_seconds(long ttl)
29{ 30{
30 if (ttl<0) 31 if (ttl<0)
31 return 60 * 60 * 24 * 365; 32 return 60 * 60 * 24 * 365;
32 else 33 else
33 return ttl * 60; 34 return ttl * 60;
34} 35}
35 36
36void cgit_print_error(char *msg) 37void cgit_print_error(char *msg)
37{ 38{
38 html("<div class='error'>"); 39 html("<div class='error'>");
39 html_txt(msg); 40 html_txt(msg);
40 html("</div>\n"); 41 html("</div>\n");
41} 42}
42 43
43char *cgit_rooturl() 44char *cgit_rooturl()
44{ 45{
45 if (ctx.cfg.virtual_root) 46 if (ctx.cfg.virtual_root)
46 return fmt("%s/", ctx.cfg.virtual_root); 47 return fmt("%s/", ctx.cfg.virtual_root);
47 else 48 else
48 return ctx.cfg.script_name; 49 return ctx.cfg.script_name;
49} 50}
50 51
51char *cgit_repourl(const char *reponame) 52char *cgit_repourl(const char *reponame)
52{ 53{
53 if (ctx.cfg.virtual_root) { 54 if (ctx.cfg.virtual_root) {
54 return fmt("%s/%s/", ctx.cfg.virtual_root, reponame); 55 return fmt("%s/%s/", ctx.cfg.virtual_root, reponame);
55 } else { 56 } else {
56 return fmt("?r=%s", reponame); 57 return fmt("?r=%s", reponame);
57 } 58 }
58} 59}
59 60
60char *cgit_fileurl(const char *reponame, const char *pagename, 61char *cgit_fileurl(const char *reponame, const char *pagename,
61 const char *filename, const char *query) 62 const char *filename, const char *query)
62{ 63{
63 char *tmp; 64 char *tmp;
64 char *delim; 65 char *delim;
65 66
66 if (ctx.cfg.virtual_root) { 67 if (ctx.cfg.virtual_root) {
67 tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame, 68 tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame,
68 pagename, (filename ? filename:"")); 69 pagename, (filename ? filename:""));
69 delim = "?"; 70 delim = "?";
70 } else { 71 } else {
71 tmp = fmt("?url=%s/%s/%s", reponame, pagename, 72 tmp = fmt("?url=%s/%s/%s", reponame, pagename,
72 (filename ? filename : "")); 73 (filename ? filename : ""));
73 delim = "&"; 74 delim = "&";
74 } 75 }
75 if (query) 76 if (query)
76 tmp = fmt("%s%s%s", tmp, delim, query); 77 tmp = fmt("%s%s%s", tmp, delim, query);
77 return tmp; 78 return tmp;
78} 79}
79 80
80char *cgit_pageurl(const char *reponame, const char *pagename, 81char *cgit_pageurl(const char *reponame, const char *pagename,
81 const char *query) 82 const char *query)
82{ 83{
83 return cgit_fileurl(reponame,pagename,0,query); 84 return cgit_fileurl(reponame,pagename,0,query);
84} 85}
85 86
86const char *cgit_repobasename(const char *reponame) 87const char *cgit_repobasename(const char *reponame)
87{ 88{
88 /* I assume we don't need to store more than one repo basename */ 89 /* I assume we don't need to store more than one repo basename */
89 static char rvbuf[1024]; 90 static char rvbuf[1024];
90 int p; 91 int p;
91 const char *rv; 92 const char *rv;
92 strncpy(rvbuf,reponame,sizeof(rvbuf)); 93 strncpy(rvbuf,reponame,sizeof(rvbuf));
93 if(rvbuf[sizeof(rvbuf)-1]) 94 if(rvbuf[sizeof(rvbuf)-1])
94 die("cgit_repobasename: truncated repository name '%s'", reponame); 95 die("cgit_repobasename: truncated repository name '%s'", reponame);
95 p = strlen(rvbuf)-1; 96 p = strlen(rvbuf)-1;
96 /* strip trailing slashes */ 97 /* strip trailing slashes */
97 while(p && rvbuf[p]=='/') rvbuf[p--]=0; 98 while(p && rvbuf[p]=='/') rvbuf[p--]=0;
98 /* strip trailing .git */ 99 /* strip trailing .git */
99 if(p>=3 && !strncmp(&rvbuf[p-3],".git",4)) { 100 if(p>=3 && !strncmp(&rvbuf[p-3],".git",4)) {
100 p -= 3; rvbuf[p--] = 0; 101 p -= 3; rvbuf[p--] = 0;
101 } 102 }
102 /* strip more trailing slashes if any */ 103 /* strip more trailing slashes if any */
103 while( p && rvbuf[p]=='/') rvbuf[p--]=0; 104 while( p && rvbuf[p]=='/') rvbuf[p--]=0;
104 /* find last slash in the remaining string */ 105 /* find last slash in the remaining string */
105 rv = strrchr(rvbuf,'/'); 106 rv = strrchr(rvbuf,'/');
@@ -474,97 +475,112 @@ void cgit_print_pageheader(char *title, int show_search)
474 html("<tr><td class='sidebar'>\n<a href='"); 475 html("<tr><td class='sidebar'>\n<a href='");
475 html_attr(cgit_rooturl()); 476 html_attr(cgit_rooturl());
476 htmlf("'><img src='%s' alt='cgit'/></a>\n", 477 htmlf("'><img src='%s' alt='cgit'/></a>\n",
477 ctx.cfg.logo); 478 ctx.cfg.logo);
478 html("</td></tr>\n<tr><td class='sidebar'>\n"); 479 html("</td></tr>\n<tr><td class='sidebar'>\n");
479 if (ctx.repo) { 480 if (ctx.repo) {
480 html("<h1 class='first'>"); 481 html("<h1 class='first'>");
481 html_txt(strrpart(ctx.repo->name, 20)); 482 html_txt(strrpart(ctx.repo->name, 20));
482 html("</h1>\n"); 483 html("</h1>\n");
483 html_txt(ctx.repo->desc); 484 html_txt(ctx.repo->desc);
484 if (ctx.repo->owner) { 485 if (ctx.repo->owner) {
485 html("<h1>owner</h1>\n"); 486 html("<h1>owner</h1>\n");
486 html_txt(ctx.repo->owner); 487 html_txt(ctx.repo->owner);
487 } 488 }
488 html("<h1>navigate</h1>\n"); 489 html("<h1>navigate</h1>\n");
489 reporevlink(NULL, "summary", NULL, "menu", ctx.qry.head, 490 reporevlink(NULL, "summary", NULL, "menu", ctx.qry.head,
490 NULL, NULL); 491 NULL, NULL);
491 cgit_log_link("log", NULL, "menu", ctx.qry.head, NULL, NULL, 492 cgit_log_link("log", NULL, "menu", ctx.qry.head, NULL, NULL,
492 0, NULL, NULL); 493 0, NULL, NULL);
493 cgit_tree_link("tree", NULL, "menu", ctx.qry.head, 494 cgit_tree_link("tree", NULL, "menu", ctx.qry.head,
494 ctx.qry.sha1, NULL); 495 ctx.qry.sha1, NULL);
495 cgit_commit_link("commit", NULL, "menu", ctx.qry.head, 496 cgit_commit_link("commit", NULL, "menu", ctx.qry.head,
496 ctx.qry.sha1); 497 ctx.qry.sha1);
497 cgit_diff_link("diff", NULL, "menu", ctx.qry.head, 498 cgit_diff_link("diff", NULL, "menu", ctx.qry.head,
498 ctx.qry.sha1, ctx.qry.sha2, NULL); 499 ctx.qry.sha1, ctx.qry.sha2, NULL);
499 cgit_patch_link("patch", NULL, "menu", ctx.qry.head, 500 cgit_patch_link("patch", NULL, "menu", ctx.qry.head,
500 ctx.qry.sha1); 501 ctx.qry.sha1);
501 502
502 for_each_ref(print_archive_ref, &header); 503 for_each_ref(print_archive_ref, &header);
503 504
504 if (ctx.repo->clone_url || ctx.cfg.clone_prefix) { 505 if (ctx.repo->clone_url || ctx.cfg.clone_prefix) {
505 html("<h1>clone</h1>\n"); 506 html("<h1>clone</h1>\n");
506 if (ctx.repo->clone_url) 507 if (ctx.repo->clone_url)
507 url = ctx.repo->clone_url; 508 url = ctx.repo->clone_url;
508 else 509 else
509 url = fmt("%s%s", ctx.cfg.clone_prefix, 510 url = fmt("%s%s", ctx.cfg.clone_prefix,
510 ctx.repo->url); 511 ctx.repo->url);
511 html("<a class='menu' href='"); 512 html("<a class='menu' href='");
512 html_attr(url); 513 html_attr(url);
513 html("' title='"); 514 html("' title='");
514 html_attr(url); 515 html_attr(url);
515 html("'>\n"); 516 html("'>\n");
516 html_txt(strrpart(url, 20)); 517 html_txt(strrpart(url, 20));
517 html("</a>\n"); 518 html("</a>\n");
518 } 519 }
519 520
520 html("<h1>branch</h1>\n"); 521 html("<h1>branch</h1>\n");
521 html("<form method='get' action=''>\n"); 522 html("<form method='get' action=''>\n");
522 add_hidden_formfields(0, 1, ctx.qry.page); 523 add_hidden_formfields(0, 1, ctx.qry.page);
523 // html("<table summary='branch selector' class='grid'><tr><td id='branch-dropdown-cell'>"); 524 // html("<table summary='branch selector' class='grid'><tr><td id='branch-dropdown-cell'>");
524 html("<select name='h' onchange='this.form.submit();'>\n"); 525 html("<select name='h' onchange='this.form.submit();'>\n");
525 for_each_branch_ref(print_branch_option, ctx.qry.head); 526 for_each_branch_ref(print_branch_option, ctx.qry.head);
526 html("</select>\n"); 527 html("</select>\n");
527 // html("</td><td>"); 528 // html("</td><td>");
528 html("<noscript><input type='submit' id='switch-btn' value='switch'/></noscript>\n"); 529 html("<noscript><input type='submit' id='switch-btn' value='switch'/></noscript>\n");
529 // html("</td></tr></table>"); 530 // html("</td></tr></table>");
530 html("</form>\n"); 531 html("</form>\n");
531 532
532 html("<h1>search</h1>\n"); 533 html("<h1>search</h1>\n");
533 html("<form method='get' action='"); 534 html("<form method='get' action='");
534 if (ctx.cfg.virtual_root) 535 if (ctx.cfg.virtual_root)
535 html_attr(cgit_fileurl(ctx.qry.repo, "log", 536 html_attr(cgit_fileurl(ctx.qry.repo, "log",
536 ctx.qry.path, NULL)); 537 ctx.qry.path, NULL));
537 html("'>\n"); 538 html("'>\n");
538 add_hidden_formfields(1, 0, "log"); 539 add_hidden_formfields(1, 0, "log");
539 html("<select name='qt'>\n"); 540 html("<select name='qt'>\n");
540 html_option("grep", "log msg", ctx.qry.grep); 541 html_option("grep", "log msg", ctx.qry.grep);
541 html_option("author", "author", ctx.qry.grep); 542 html_option("author", "author", ctx.qry.grep);
542 html_option("committer", "committer", ctx.qry.grep); 543 html_option("committer", "committer", ctx.qry.grep);
543 html("</select>\n"); 544 html("</select>\n");
544 html("<input class='txt' type='text' name='q' value='"); 545 html("<input class='txt' type='text' name='q' value='");
545 html_attr(ctx.qry.search); 546 html_attr(ctx.qry.search);
546 html("'/>\n"); 547 html("'/>\n");
547 html("</form>\n"); 548 html("</form>\n");
548 } else { 549 } else {
549 if (!ctx.cfg.index_info || html_include(ctx.cfg.index_info)) 550 if (!ctx.cfg.index_info || html_include(ctx.cfg.index_info))
550 html(default_info); 551 html(default_info);
551 } 552 }
552 553
553 html("</td></tr></table></td>\n"); 554 html("</td></tr></table></td>\n");
554 555
555 html("<td id='content'>\n"); 556 html("<td id='content'>\n");
556} 557}
557 558
558 559
559void cgit_print_snapshot_start(const char *mimetype, const char *filename, 560void cgit_print_snapshot_start(const char *mimetype, const char *filename,
560 struct cacheitem *item) 561 struct cacheitem *item)
561{ 562{
562 htmlf("Content-Type: %s\n", mimetype); 563 htmlf("Content-Type: %s\n", mimetype);
563 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); 564 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename);
564 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 565 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
565 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 566 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
566 ttl_seconds(item->ttl))); 567 ttl_seconds(item->ttl)));
567 html("\n"); 568 html("\n");
568} 569}
569 570
571void cgit_print_filemode(unsigned short mode)
572{
573 if (S_ISDIR(mode))
574 html("d");
575 else if (S_ISLNK(mode))
576 html("l");
577 else if (S_ISGITLINK(mode))
578 html("m");
579 else
580 html("-");
581 html_fileperm(mode >> 6);
582 html_fileperm(mode >> 3);
583 html_fileperm(mode);
584}
585
570/* vim:set sw=8: */ 586/* vim:set sw=8: */