summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--cgit.c6
-rw-r--r--cgit.h3
-rw-r--r--ui-atom.c6
-rw-r--r--ui-blob.c8
-rw-r--r--ui-plain.c4
-rw-r--r--ui-shared.c22
-rw-r--r--ui-shared.h1
7 files changed, 46 insertions, 4 deletions
diff --git a/cgit.c b/cgit.c
index 2afc598..513ea12 100644
--- a/cgit.c
+++ b/cgit.c
@@ -199,24 +199,25 @@ static void prepare_context(struct cgit_context *ctx)
199 ctx->cfg.root_title = "Git repository browser"; 199 ctx->cfg.root_title = "Git repository browser";
200 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 200 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
201 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 201 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
202 ctx->cfg.summary_branches = 10; 202 ctx->cfg.summary_branches = 10;
203 ctx->cfg.summary_log = 10; 203 ctx->cfg.summary_log = 10;
204 ctx->cfg.summary_tags = 10; 204 ctx->cfg.summary_tags = 10;
205 ctx->page.mimetype = "text/html"; 205 ctx->page.mimetype = "text/html";
206 ctx->page.charset = PAGE_ENCODING; 206 ctx->page.charset = PAGE_ENCODING;
207 ctx->page.filename = NULL; 207 ctx->page.filename = NULL;
208 ctx->page.size = 0; 208 ctx->page.size = 0;
209 ctx->page.modified = time(NULL); 209 ctx->page.modified = time(NULL);
210 ctx->page.expires = ctx->page.modified; 210 ctx->page.expires = ctx->page.modified;
211 ctx->page.etag = NULL;
211} 212}
212 213
213struct refmatch { 214struct refmatch {
214 char *req_ref; 215 char *req_ref;
215 char *first_ref; 216 char *first_ref;
216 int match; 217 int match;
217}; 218};
218 219
219int find_current_ref(const char *refname, const unsigned char *sha1, 220int find_current_ref(const char *refname, const unsigned char *sha1,
220 int flags, void *cb_data) 221 int flags, void *cb_data)
221{ 222{
222 struct refmatch *info; 223 struct refmatch *info;
@@ -278,24 +279,26 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
278 if (!ctx->qry.head) { 279 if (!ctx->qry.head) {
279 cgit_print_http_headers(ctx); 280 cgit_print_http_headers(ctx);
280 cgit_print_docstart(ctx); 281 cgit_print_docstart(ctx);
281 cgit_print_pageheader(ctx); 282 cgit_print_pageheader(ctx);
282 cgit_print_error("Repository seems to be empty"); 283 cgit_print_error("Repository seems to be empty");
283 cgit_print_docend(); 284 cgit_print_docend();
284 return 1; 285 return 1;
285 } 286 }
286 287
287 if (get_sha1(ctx->qry.head, sha1)) { 288 if (get_sha1(ctx->qry.head, sha1)) {
288 tmp = xstrdup(ctx->qry.head); 289 tmp = xstrdup(ctx->qry.head);
289 ctx->qry.head = ctx->repo->defbranch; 290 ctx->qry.head = ctx->repo->defbranch;
291 ctx->page.status = 404;
292 ctx->page.statusmsg = "not found";
290 cgit_print_http_headers(ctx); 293 cgit_print_http_headers(ctx);
291 cgit_print_docstart(ctx); 294 cgit_print_docstart(ctx);
292 cgit_print_pageheader(ctx); 295 cgit_print_pageheader(ctx);
293 cgit_print_error(fmt("Invalid branch: %s", tmp)); 296 cgit_print_error(fmt("Invalid branch: %s", tmp));
294 cgit_print_docend(); 297 cgit_print_docend();
295 return 1; 298 return 1;
296 } 299 }
297 return 0; 300 return 0;
298} 301}
299 302
300static void process_request(void *cbdata) 303static void process_request(void *cbdata)
301{ 304{
@@ -422,24 +425,25 @@ static int calc_ttl()
422 if (ctx.qry.has_symref) 425 if (ctx.qry.has_symref)
423 return ctx.cfg.cache_dynamic_ttl; 426 return ctx.cfg.cache_dynamic_ttl;
424 427
425 if (ctx.qry.has_sha1) 428 if (ctx.qry.has_sha1)
426 return ctx.cfg.cache_static_ttl; 429 return ctx.cfg.cache_static_ttl;
427 430
428 return ctx.cfg.cache_repo_ttl; 431 return ctx.cfg.cache_repo_ttl;
429} 432}
430 433
431int main(int argc, const char **argv) 434int main(int argc, const char **argv)
432{ 435{
433 const char *cgit_config_env = getenv("CGIT_CONFIG"); 436 const char *cgit_config_env = getenv("CGIT_CONFIG");
437 const char *method = getenv("REQUEST_METHOD");
434 const char *path; 438 const char *path;
435 char *qry; 439 char *qry;
436 int err, ttl; 440 int err, ttl;
437 441
438 prepare_context(&ctx); 442 prepare_context(&ctx);
439 cgit_repolist.length = 0; 443 cgit_repolist.length = 0;
440 cgit_repolist.count = 0; 444 cgit_repolist.count = 0;
441 cgit_repolist.repos = NULL; 445 cgit_repolist.repos = NULL;
442 446
443 if (getenv("SCRIPT_NAME")) 447 if (getenv("SCRIPT_NAME"))
444 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); 448 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME"));
445 if (getenv("QUERY_STRING")) 449 if (getenv("QUERY_STRING"))
@@ -468,21 +472,23 @@ int main(int argc, const char **argv)
468 ctx.qry.url = xstrdup(path); 472 ctx.qry.url = xstrdup(path);
469 if (ctx.qry.raw) { 473 if (ctx.qry.raw) {
470 qry = ctx.qry.raw; 474 qry = ctx.qry.raw;
471 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); 475 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry));
472 free(qry); 476 free(qry);
473 } else 477 } else
474 ctx.qry.raw = ctx.qry.url; 478 ctx.qry.raw = ctx.qry.url;
475 cgit_parse_url(ctx.qry.url); 479 cgit_parse_url(ctx.qry.url);
476 } 480 }
477 481
478 ttl = calc_ttl(); 482 ttl = calc_ttl();
479 ctx.page.expires += ttl*60; 483 ctx.page.expires += ttl*60;
484 if (method && !strcmp(method, "HEAD"))
485 ctx.cfg.nocache = 1;
480 if (ctx.cfg.nocache) 486 if (ctx.cfg.nocache)
481 ctx.cfg.cache_size = 0; 487 ctx.cfg.cache_size = 0;
482 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, 488 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
483 ctx.qry.raw, ttl, process_request, &ctx); 489 ctx.qry.raw, ttl, process_request, &ctx);
484 if (err) 490 if (err)
485 cgit_print_error(fmt("Error processing page: %s (%d)", 491 cgit_print_error(fmt("Error processing page: %s (%d)",
486 strerror(err), err)); 492 strerror(err), err));
487 return err; 493 return err;
488} 494}
diff --git a/cgit.h b/cgit.h
index aed826a..78b30ba 100644
--- a/cgit.h
+++ b/cgit.h
@@ -172,25 +172,28 @@ struct cgit_config {
172 int summary_branches; 172 int summary_branches;
173 int summary_log; 173 int summary_log;
174 int summary_tags; 174 int summary_tags;
175}; 175};
176 176
177struct cgit_page { 177struct cgit_page {
178 time_t modified; 178 time_t modified;
179 time_t expires; 179 time_t expires;
180 size_t size; 180 size_t size;
181 char *mimetype; 181 char *mimetype;
182 char *charset; 182 char *charset;
183 char *filename; 183 char *filename;
184 char *etag;
184 char *title; 185 char *title;
186 int status;
187 char *statusmsg;
185}; 188};
186 189
187struct cgit_context { 190struct cgit_context {
188 struct cgit_query qry; 191 struct cgit_query qry;
189 struct cgit_config cfg; 192 struct cgit_config cfg;
190 struct cgit_repo *repo; 193 struct cgit_repo *repo;
191 struct cgit_page page; 194 struct cgit_page page;
192}; 195};
193 196
194struct cgit_snapshot_format { 197struct cgit_snapshot_format {
195 const char *suffix; 198 const char *suffix;
196 const char *mimetype; 199 const char *mimetype;
diff --git a/ui-atom.c b/ui-atom.c
index a6ea3ee..e5c31d9 100644
--- a/ui-atom.c
+++ b/ui-atom.c
@@ -43,25 +43,26 @@ void add_entry(struct commit *commit, char *host)
43 if (t2) 43 if (t2)
44 *t2 = '\0'; 44 *t2 = '\0';
45 html("<email>"); 45 html("<email>");
46 html_txt(t); 46 html_txt(t);
47 html("</email>\n"); 47 html("</email>\n");
48 free(mail); 48 free(mail);
49 } 49 }
50 html("</author>\n"); 50 html("</author>\n");
51 html("<published>"); 51 html("<published>");
52 cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time); 52 cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time);
53 html("</published>\n"); 53 html("</published>\n");
54 if (host) { 54 if (host) {
55 html("<link rel='alternate' type='text/html' href='http://"); 55 html("<link rel='alternate' type='text/html' href='");
56 html(cgit_httpscheme());
56 html_attr(host); 57 html_attr(host);
57 html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL)); 58 html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL));
58 if (ctx.cfg.virtual_root) 59 if (ctx.cfg.virtual_root)
59 delim = '?'; 60 delim = '?';
60 htmlf("%cid=%s", delim, hex); 61 htmlf("%cid=%s", delim, hex);
61 html("'/>\n"); 62 html("'/>\n");
62 } 63 }
63 htmlf("<id>%s</id>\n", hex); 64 htmlf("<id>%s</id>\n", hex);
64 html("<content type='text'>\n"); 65 html("<content type='text'>\n");
65 html_txt(info->msg); 66 html_txt(info->msg);
66 html("</content>\n"); 67 html("</content>\n");
67 html("<content type='xhtml'>\n"); 68 html("<content type='xhtml'>\n");
@@ -104,25 +105,26 @@ void cgit_print_atom(char *tip, char *path, int max_count)
104 host = cgit_hosturl(); 105 host = cgit_hosturl();
105 ctx.page.mimetype = "text/xml"; 106 ctx.page.mimetype = "text/xml";
106 ctx.page.charset = "utf-8"; 107 ctx.page.charset = "utf-8";
107 cgit_print_http_headers(&ctx); 108 cgit_print_http_headers(&ctx);
108 html("<feed xmlns='http://www.w3.org/2005/Atom'>\n"); 109 html("<feed xmlns='http://www.w3.org/2005/Atom'>\n");
109 html("<title>"); 110 html("<title>");
110 html_txt(ctx.repo->name); 111 html_txt(ctx.repo->name);
111 html("</title>\n"); 112 html("</title>\n");
112 html("<subtitle>"); 113 html("<subtitle>");
113 html_txt(ctx.repo->desc); 114 html_txt(ctx.repo->desc);
114 html("</subtitle>\n"); 115 html("</subtitle>\n");
115 if (host) { 116 if (host) {
116 html("<link rel='alternate' type='text/html' href='http://"); 117 html("<link rel='alternate' type='text/html' href='");
118 html(cgit_httpscheme());
117 html_attr(host); 119 html_attr(host);
118 html_attr(cgit_repourl(ctx.repo->url)); 120 html_attr(cgit_repourl(ctx.repo->url));
119 html("'/>\n"); 121 html("'/>\n");
120 } 122 }
121 while ((commit = get_revision(&rev)) != NULL) { 123 while ((commit = get_revision(&rev)) != NULL) {
122 add_entry(commit, host); 124 add_entry(commit, host);
123 free(commit->buffer); 125 free(commit->buffer);
124 commit->buffer = NULL; 126 commit->buffer = NULL;
125 free_commit_list(commit->parents); 127 free_commit_list(commit->parents);
126 commit->parents = NULL; 128 commit->parents = NULL;
127 } 129 }
128 html("</feed>\n"); 130 html("</feed>\n");
diff --git a/ui-blob.c b/ui-blob.c
index 3cda03d..2ccd31d 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -18,25 +18,25 @@ static int walk_tree(const unsigned char *sha1, const char *base,int baselen,
18 if(strncmp(base,match_path,baselen) 18 if(strncmp(base,match_path,baselen)
19 || strcmp(match_path+baselen,pathname) ) 19 || strcmp(match_path+baselen,pathname) )
20 return READ_TREE_RECURSIVE; 20 return READ_TREE_RECURSIVE;
21 memmove(matched_sha1,sha1,20); 21 memmove(matched_sha1,sha1,20);
22 return 0; 22 return 0;
23} 23}
24 24
25void cgit_print_blob(const char *hex, char *path, const char *head) 25void cgit_print_blob(const char *hex, char *path, const char *head)
26{ 26{
27 27
28 unsigned char sha1[20]; 28 unsigned char sha1[20];
29 enum object_type type; 29 enum object_type type;
30 unsigned char *buf; 30 char *buf;
31 unsigned long size; 31 unsigned long size;
32 struct commit *commit; 32 struct commit *commit;
33 const char *paths[] = {path, NULL}; 33 const char *paths[] = {path, NULL};
34 34
35 if (hex) { 35 if (hex) {
36 if (get_sha1_hex(hex, sha1)){ 36 if (get_sha1_hex(hex, sha1)){
37 cgit_print_error(fmt("Bad hex value: %s", hex)); 37 cgit_print_error(fmt("Bad hex value: %s", hex));
38 return; 38 return;
39 } 39 }
40 } else { 40 } else {
41 if (get_sha1(head,sha1)) { 41 if (get_sha1(head,sha1)) {
42 cgit_print_error(fmt("Bad ref: %s", head)); 42 cgit_print_error(fmt("Bad ref: %s", head));
@@ -58,16 +58,22 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
58 cgit_print_error(fmt("Bad object name: %s", hex)); 58 cgit_print_error(fmt("Bad object name: %s", hex));
59 return; 59 return;
60 } 60 }
61 61
62 buf = read_sha1_file(sha1, &type, &size); 62 buf = read_sha1_file(sha1, &type, &size);
63 if (!buf) { 63 if (!buf) {
64 cgit_print_error(fmt("Error reading object %s", hex)); 64 cgit_print_error(fmt("Error reading object %s", hex));
65 return; 65 return;
66 } 66 }
67 67
68 buf[size] = '\0'; 68 buf[size] = '\0';
69 ctx.page.mimetype = ctx.qry.mimetype; 69 ctx.page.mimetype = ctx.qry.mimetype;
70 if (!ctx.page.mimetype) {
71 if (buffer_is_binary(buf, size))
72 ctx.page.mimetype = "application/octet-stream";
73 else
74 ctx.page.mimetype = "text/plain";
75 }
70 ctx.page.filename = path; 76 ctx.page.filename = path;
71 cgit_print_http_headers(&ctx); 77 cgit_print_http_headers(&ctx);
72 write(htmlfd, buf, size); 78 write(htmlfd, buf, size);
73} 79}
diff --git a/ui-plain.c b/ui-plain.c
index 5addd9e..93a3a05 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -22,27 +22,31 @@ static void print_object(const unsigned char *sha1, const char *path)
22 22
23 type = sha1_object_info(sha1, &size); 23 type = sha1_object_info(sha1, &size);
24 if (type == OBJ_BAD) { 24 if (type == OBJ_BAD) {
25 html_status(404, "Not found", 0); 25 html_status(404, "Not found", 0);
26 return; 26 return;
27 } 27 }
28 28
29 buf = read_sha1_file(sha1, &type, &size); 29 buf = read_sha1_file(sha1, &type, &size);
30 if (!buf) { 30 if (!buf) {
31 html_status(404, "Not found", 0); 31 html_status(404, "Not found", 0);
32 return; 32 return;
33 } 33 }
34 if (buffer_is_binary(buf, size))
35 ctx.page.mimetype = "application/octet-stream";
36 else
34 ctx.page.mimetype = "text/plain"; 37 ctx.page.mimetype = "text/plain";
35 ctx.page.filename = fmt("%s", path); 38 ctx.page.filename = fmt("%s", path);
36 ctx.page.size = size; 39 ctx.page.size = size;
40 ctx.page.etag = sha1_to_hex(sha1);
37 cgit_print_http_headers(&ctx); 41 cgit_print_http_headers(&ctx);
38 html_raw(buf, size); 42 html_raw(buf, size);
39 match = 1; 43 match = 1;
40} 44}
41 45
42static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 46static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
43 const char *pathname, unsigned mode, int stage, 47 const char *pathname, unsigned mode, int stage,
44 void *cbdata) 48 void *cbdata)
45{ 49{
46 if (S_ISDIR(mode)) 50 if (S_ISDIR(mode))
47 return READ_TREE_RECURSIVE; 51 return READ_TREE_RECURSIVE;
48 52
diff --git a/ui-shared.c b/ui-shared.c
index fea2c40..66d5b82 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -25,24 +25,35 @@ static char *http_date(time_t t)
25 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], 25 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
26 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, 26 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year,
27 tm->tm_hour, tm->tm_min, tm->tm_sec); 27 tm->tm_hour, tm->tm_min, tm->tm_sec);
28} 28}
29 29
30void cgit_print_error(char *msg) 30void cgit_print_error(char *msg)
31{ 31{
32 html("<div class='error'>"); 32 html("<div class='error'>");
33 html_txt(msg); 33 html_txt(msg);
34 html("</div>\n"); 34 html("</div>\n");
35} 35}
36 36
37char *cgit_httpscheme()
38{
39 char *https;
40
41 https = getenv("HTTPS");
42 if (https != NULL && strcmp(https, "on") == 0)
43 return "https://";
44 else
45 return "http://";
46}
47
37char *cgit_hosturl() 48char *cgit_hosturl()
38{ 49{
39 char *host, *port; 50 char *host, *port;
40 51
41 host = getenv("HTTP_HOST"); 52 host = getenv("HTTP_HOST");
42 if (host) { 53 if (host) {
43 host = xstrdup(host); 54 host = xstrdup(host);
44 } else { 55 } else {
45 host = getenv("SERVER_NAME"); 56 host = getenv("SERVER_NAME");
46 if (!host) 57 if (!host)
47 return NULL; 58 return NULL;
48 port = getenv("SERVER_PORT"); 59 port = getenv("SERVER_PORT");
@@ -447,61 +458,70 @@ void cgit_print_age(time_t t, time_t max_relative, char *format)
447 } 458 }
448 if (secs < TM_YEAR * 2) { 459 if (secs < TM_YEAR * 2) {
449 htmlf("<span class='age-months'>%.0f months</span>", 460 htmlf("<span class='age-months'>%.0f months</span>",
450 secs * 1.0 / TM_MONTH); 461 secs * 1.0 / TM_MONTH);
451 return; 462 return;
452 } 463 }
453 htmlf("<span class='age-years'>%.0f years</span>", 464 htmlf("<span class='age-years'>%.0f years</span>",
454 secs * 1.0 / TM_YEAR); 465 secs * 1.0 / TM_YEAR);
455} 466}
456 467
457void cgit_print_http_headers(struct cgit_context *ctx) 468void cgit_print_http_headers(struct cgit_context *ctx)
458{ 469{
470 const char *method = getenv("REQUEST_METHOD");
471
472 if (ctx->page.status)
473 htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg);
459 if (ctx->page.mimetype && ctx->page.charset) 474 if (ctx->page.mimetype && ctx->page.charset)
460 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, 475 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype,
461 ctx->page.charset); 476 ctx->page.charset);
462 else if (ctx->page.mimetype) 477 else if (ctx->page.mimetype)
463 htmlf("Content-Type: %s\n", ctx->page.mimetype); 478 htmlf("Content-Type: %s\n", ctx->page.mimetype);
464 if (ctx->page.size) 479 if (ctx->page.size)
465 htmlf("Content-Length: %ld\n", ctx->page.size); 480 htmlf("Content-Length: %ld\n", ctx->page.size);
466 if (ctx->page.filename) 481 if (ctx->page.filename)
467 htmlf("Content-Disposition: inline; filename=\"%s\"\n", 482 htmlf("Content-Disposition: inline; filename=\"%s\"\n",
468 ctx->page.filename); 483 ctx->page.filename);
469 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); 484 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified));
470 htmlf("Expires: %s\n", http_date(ctx->page.expires)); 485 htmlf("Expires: %s\n", http_date(ctx->page.expires));
486 if (ctx->page.etag)
487 htmlf("ETag: \"%s\"\n", ctx->page.etag);
471 html("\n"); 488 html("\n");
489 if (method && !strcmp(method, "HEAD"))
490 exit(0);
472} 491}
473 492
474void cgit_print_docstart(struct cgit_context *ctx) 493void cgit_print_docstart(struct cgit_context *ctx)
475{ 494{
476 char *host = cgit_hosturl(); 495 char *host = cgit_hosturl();
477 html(cgit_doctype); 496 html(cgit_doctype);
478 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); 497 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n");
479 html("<head>\n"); 498 html("<head>\n");
480 html("<title>"); 499 html("<title>");
481 html_txt(ctx->page.title); 500 html_txt(ctx->page.title);
482 html("</title>\n"); 501 html("</title>\n");
483 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); 502 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version);
484 if (ctx->cfg.robots && *ctx->cfg.robots) 503 if (ctx->cfg.robots && *ctx->cfg.robots)
485 htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); 504 htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots);
486 html("<link rel='stylesheet' type='text/css' href='"); 505 html("<link rel='stylesheet' type='text/css' href='");
487 html_attr(ctx->cfg.css); 506 html_attr(ctx->cfg.css);
488 html("'/>\n"); 507 html("'/>\n");
489 if (ctx->cfg.favicon) { 508 if (ctx->cfg.favicon) {
490 html("<link rel='shortcut icon' href='"); 509 html("<link rel='shortcut icon' href='");
491 html_attr(ctx->cfg.favicon); 510 html_attr(ctx->cfg.favicon);
492 html("'/>\n"); 511 html("'/>\n");
493 } 512 }
494 if (host && ctx->repo) { 513 if (host && ctx->repo) {
495 html("<link rel='alternate' title='Atom feed' href='http://"); 514 html("<link rel='alternate' title='Atom feed' href='");
515 html(cgit_httpscheme());
496 html_attr(cgit_hosturl()); 516 html_attr(cgit_hosturl());
497 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, 517 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path,
498 fmt("h=%s", ctx->qry.head))); 518 fmt("h=%s", ctx->qry.head)));
499 html("' type='application/atom+xml'/>\n"); 519 html("' type='application/atom+xml'/>\n");
500 } 520 }
501 if (ctx->cfg.head_include) 521 if (ctx->cfg.head_include)
502 html_include(ctx->cfg.head_include); 522 html_include(ctx->cfg.head_include);
503 html("</head>\n"); 523 html("</head>\n");
504 html("<body>\n"); 524 html("<body>\n");
505 if (ctx->cfg.header) 525 if (ctx->cfg.header)
506 html_include(ctx->cfg.header); 526 html_include(ctx->cfg.header);
507} 527}
diff --git a/ui-shared.h b/ui-shared.h
index 5a3821f..bff4826 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -1,15 +1,16 @@
1#ifndef UI_SHARED_H 1#ifndef UI_SHARED_H
2#define UI_SHARED_H 2#define UI_SHARED_H
3 3
4extern char *cgit_httpscheme();
4extern char *cgit_hosturl(); 5extern char *cgit_hosturl();
5extern char *cgit_repourl(const char *reponame); 6extern char *cgit_repourl(const char *reponame);
6extern char *cgit_fileurl(const char *reponame, const char *pagename, 7extern char *cgit_fileurl(const char *reponame, const char *pagename,
7 const char *filename, const char *query); 8 const char *filename, const char *query);
8extern char *cgit_pageurl(const char *reponame, const char *pagename, 9extern char *cgit_pageurl(const char *reponame, const char *pagename,
9 const char *query); 10 const char *query);
10 11
11extern void cgit_index_link(char *name, char *title, char *class, 12extern void cgit_index_link(char *name, char *title, char *class,
12 char *pattern, int ofs); 13 char *pattern, int ofs);
13extern void cgit_summary_link(char *name, char *title, char *class, char *head); 14extern void cgit_summary_link(char *name, char *title, char *class, char *head);
14extern void cgit_tag_link(char *name, char *title, char *class, char *head, 15extern void cgit_tag_link(char *name, char *title, char *class, char *head,
15 char *rev); 16 char *rev);