-rw-r--r-- | ui-shared.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/ui-shared.c b/ui-shared.c index 37c60b2..4818e70 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
@@ -197,128 +197,134 @@ static char *repolink(char *title, char *class, char *page, char *head, | |||
197 | if (class) { | 197 | if (class) { |
198 | html(" class='"); | 198 | html(" class='"); |
199 | html_attr(class); | 199 | html_attr(class); |
200 | html("'"); | 200 | html("'"); |
201 | } | 201 | } |
202 | html(" href='"); | 202 | html(" href='"); |
203 | if (ctx.cfg.virtual_root) { | 203 | if (ctx.cfg.virtual_root) { |
204 | html_attr(ctx.cfg.virtual_root); | 204 | html_attr(ctx.cfg.virtual_root); |
205 | if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') | 205 | if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') |
206 | html("/"); | 206 | html("/"); |
207 | html_attr(ctx.repo->url); | 207 | html_attr(ctx.repo->url); |
208 | if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') | 208 | if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') |
209 | html("/"); | 209 | html("/"); |
210 | if (page) { | 210 | if (page) { |
211 | html(page); | 211 | html(page); |
212 | html("/"); | 212 | html("/"); |
213 | if (path) | 213 | if (path) |
214 | html_attr(path); | 214 | html_attr(path); |
215 | } | 215 | } |
216 | } else { | 216 | } else { |
217 | html(ctx.cfg.script_name); | 217 | html(ctx.cfg.script_name); |
218 | html("?url="); | 218 | html("?url="); |
219 | html_attr(ctx.repo->url); | 219 | html_attr(ctx.repo->url); |
220 | if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') | 220 | if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') |
221 | html("/"); | 221 | html("/"); |
222 | if (page) { | 222 | if (page) { |
223 | html(page); | 223 | html(page); |
224 | html("/"); | 224 | html("/"); |
225 | if (path) | 225 | if (path) |
226 | html_attr(path); | 226 | html_attr(path); |
227 | } | 227 | } |
228 | delim = "&"; | 228 | delim = "&"; |
229 | } | 229 | } |
230 | if (head && strcmp(head, ctx.repo->defbranch)) { | 230 | if (head && strcmp(head, ctx.repo->defbranch)) { |
231 | html(delim); | 231 | html(delim); |
232 | html("h="); | 232 | html("h="); |
233 | html_attr(head); | 233 | html_attr(head); |
234 | delim = "&"; | 234 | delim = "&"; |
235 | } | 235 | } |
236 | return fmt("%s", delim); | 236 | return fmt("%s", delim); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void reporevlink(char *page, char *name, char *title, char *class, | 239 | static void reporevlink(char *page, char *name, char *title, char *class, |
240 | char *head, char *rev, char *path) | 240 | char *head, char *rev, char *path) |
241 | { | 241 | { |
242 | char *delim; | 242 | char *delim; |
243 | 243 | ||
244 | delim = repolink(title, class, page, head, path); | 244 | delim = repolink(title, class, page, head, path); |
245 | if (rev && strcmp(rev, ctx.qry.head)) { | 245 | if (rev && strcmp(rev, ctx.qry.head)) { |
246 | html(delim); | 246 | html(delim); |
247 | html("id="); | 247 | html("id="); |
248 | html_attr(rev); | 248 | html_attr(rev); |
249 | } | 249 | } |
250 | html("'>"); | 250 | html("'>"); |
251 | html_txt(name); | 251 | html_txt(name); |
252 | html("</a>"); | 252 | html("</a>"); |
253 | } | 253 | } |
254 | 254 | ||
255 | void cgit_tree_link(char *name, char *title, char *class, char *head, | 255 | void cgit_tree_link(char *name, char *title, char *class, char *head, |
256 | char *rev, char *path) | 256 | char *rev, char *path) |
257 | { | 257 | { |
258 | reporevlink("tree", name, title, class, head, rev, path); | 258 | reporevlink("tree", name, title, class, head, rev, path); |
259 | } | 259 | } |
260 | 260 | ||
261 | void cgit_plain_link(char *name, char *title, char *class, char *head, | ||
262 | char *rev, char *path) | ||
263 | { | ||
264 | reporevlink("plain", name, title, class, head, rev, path); | ||
265 | } | ||
266 | |||
261 | void cgit_log_link(char *name, char *title, char *class, char *head, | 267 | void cgit_log_link(char *name, char *title, char *class, char *head, |
262 | char *rev, char *path, int ofs, char *grep, char *pattern) | 268 | char *rev, char *path, int ofs, char *grep, char *pattern) |
263 | { | 269 | { |
264 | char *delim; | 270 | char *delim; |
265 | 271 | ||
266 | delim = repolink(title, class, "log", head, path); | 272 | delim = repolink(title, class, "log", head, path); |
267 | if (rev && strcmp(rev, ctx.qry.head)) { | 273 | if (rev && strcmp(rev, ctx.qry.head)) { |
268 | html(delim); | 274 | html(delim); |
269 | html("id="); | 275 | html("id="); |
270 | html_attr(rev); | 276 | html_attr(rev); |
271 | delim = "&"; | 277 | delim = "&"; |
272 | } | 278 | } |
273 | if (grep && pattern) { | 279 | if (grep && pattern) { |
274 | html(delim); | 280 | html(delim); |
275 | html("qt="); | 281 | html("qt="); |
276 | html_attr(grep); | 282 | html_attr(grep); |
277 | delim = "&"; | 283 | delim = "&"; |
278 | html(delim); | 284 | html(delim); |
279 | html("q="); | 285 | html("q="); |
280 | html_attr(pattern); | 286 | html_attr(pattern); |
281 | } | 287 | } |
282 | if (ofs > 0) { | 288 | if (ofs > 0) { |
283 | html(delim); | 289 | html(delim); |
284 | html("ofs="); | 290 | html("ofs="); |
285 | htmlf("%d", ofs); | 291 | htmlf("%d", ofs); |
286 | } | 292 | } |
287 | html("'>"); | 293 | html("'>"); |
288 | html_txt(name); | 294 | html_txt(name); |
289 | html("</a>"); | 295 | html("</a>"); |
290 | } | 296 | } |
291 | 297 | ||
292 | void cgit_commit_link(char *name, char *title, char *class, char *head, | 298 | void cgit_commit_link(char *name, char *title, char *class, char *head, |
293 | char *rev) | 299 | char *rev) |
294 | { | 300 | { |
295 | if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { | 301 | if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { |
296 | name[ctx.cfg.max_msg_len] = '\0'; | 302 | name[ctx.cfg.max_msg_len] = '\0'; |
297 | name[ctx.cfg.max_msg_len - 1] = '.'; | 303 | name[ctx.cfg.max_msg_len - 1] = '.'; |
298 | name[ctx.cfg.max_msg_len - 2] = '.'; | 304 | name[ctx.cfg.max_msg_len - 2] = '.'; |
299 | name[ctx.cfg.max_msg_len - 3] = '.'; | 305 | name[ctx.cfg.max_msg_len - 3] = '.'; |
300 | } | 306 | } |
301 | reporevlink("commit", name, title, class, head, rev, NULL); | 307 | reporevlink("commit", name, title, class, head, rev, NULL); |
302 | } | 308 | } |
303 | 309 | ||
304 | void cgit_refs_link(char *name, char *title, char *class, char *head, | 310 | void cgit_refs_link(char *name, char *title, char *class, char *head, |
305 | char *rev, char *path) | 311 | char *rev, char *path) |
306 | { | 312 | { |
307 | reporevlink("refs", name, title, class, head, rev, path); | 313 | reporevlink("refs", name, title, class, head, rev, path); |
308 | } | 314 | } |
309 | 315 | ||
310 | void cgit_snapshot_link(char *name, char *title, char *class, char *head, | 316 | void cgit_snapshot_link(char *name, char *title, char *class, char *head, |
311 | char *rev, char *archivename) | 317 | char *rev, char *archivename) |
312 | { | 318 | { |
313 | reporevlink("snapshot", name, title, class, head, rev, archivename); | 319 | reporevlink("snapshot", name, title, class, head, rev, archivename); |
314 | } | 320 | } |
315 | 321 | ||
316 | void cgit_diff_link(char *name, char *title, char *class, char *head, | 322 | void cgit_diff_link(char *name, char *title, char *class, char *head, |
317 | char *new_rev, char *old_rev, char *path) | 323 | char *new_rev, char *old_rev, char *path) |
318 | { | 324 | { |
319 | char *delim; | 325 | char *delim; |
320 | 326 | ||
321 | delim = repolink(title, class, "diff", head, path); | 327 | delim = repolink(title, class, "diff", head, path); |
322 | if (new_rev && strcmp(new_rev, ctx.qry.head)) { | 328 | if (new_rev && strcmp(new_rev, ctx.qry.head)) { |
323 | html(delim); | 329 | html(delim); |
324 | html("id="); | 330 | html("id="); |
@@ -372,128 +378,130 @@ void cgit_print_date(time_t secs, char *format, int local_time) | |||
372 | { | 378 | { |
373 | char buf[64]; | 379 | char buf[64]; |
374 | struct tm *time; | 380 | struct tm *time; |
375 | 381 | ||
376 | if (!secs) | 382 | if (!secs) |
377 | return; | 383 | return; |
378 | if(local_time) | 384 | if(local_time) |
379 | time = localtime(&secs); | 385 | time = localtime(&secs); |
380 | else | 386 | else |
381 | time = gmtime(&secs); | 387 | time = gmtime(&secs); |
382 | strftime(buf, sizeof(buf)-1, format, time); | 388 | strftime(buf, sizeof(buf)-1, format, time); |
383 | html_txt(buf); | 389 | html_txt(buf); |
384 | } | 390 | } |
385 | 391 | ||
386 | void cgit_print_age(time_t t, time_t max_relative, char *format) | 392 | void cgit_print_age(time_t t, time_t max_relative, char *format) |
387 | { | 393 | { |
388 | time_t now, secs; | 394 | time_t now, secs; |
389 | 395 | ||
390 | if (!t) | 396 | if (!t) |
391 | return; | 397 | return; |
392 | time(&now); | 398 | time(&now); |
393 | secs = now - t; | 399 | secs = now - t; |
394 | 400 | ||
395 | if (secs > max_relative && max_relative >= 0) { | 401 | if (secs > max_relative && max_relative >= 0) { |
396 | cgit_print_date(t, format, ctx.cfg.local_time); | 402 | cgit_print_date(t, format, ctx.cfg.local_time); |
397 | return; | 403 | return; |
398 | } | 404 | } |
399 | 405 | ||
400 | if (secs < TM_HOUR * 2) { | 406 | if (secs < TM_HOUR * 2) { |
401 | htmlf("<span class='age-mins'>%.0f min.</span>", | 407 | htmlf("<span class='age-mins'>%.0f min.</span>", |
402 | secs * 1.0 / TM_MIN); | 408 | secs * 1.0 / TM_MIN); |
403 | return; | 409 | return; |
404 | } | 410 | } |
405 | if (secs < TM_DAY * 2) { | 411 | if (secs < TM_DAY * 2) { |
406 | htmlf("<span class='age-hours'>%.0f hours</span>", | 412 | htmlf("<span class='age-hours'>%.0f hours</span>", |
407 | secs * 1.0 / TM_HOUR); | 413 | secs * 1.0 / TM_HOUR); |
408 | return; | 414 | return; |
409 | } | 415 | } |
410 | if (secs < TM_WEEK * 2) { | 416 | if (secs < TM_WEEK * 2) { |
411 | htmlf("<span class='age-days'>%.0f days</span>", | 417 | htmlf("<span class='age-days'>%.0f days</span>", |
412 | secs * 1.0 / TM_DAY); | 418 | secs * 1.0 / TM_DAY); |
413 | return; | 419 | return; |
414 | } | 420 | } |
415 | if (secs < TM_MONTH * 2) { | 421 | if (secs < TM_MONTH * 2) { |
416 | htmlf("<span class='age-weeks'>%.0f weeks</span>", | 422 | htmlf("<span class='age-weeks'>%.0f weeks</span>", |
417 | secs * 1.0 / TM_WEEK); | 423 | secs * 1.0 / TM_WEEK); |
418 | return; | 424 | return; |
419 | } | 425 | } |
420 | if (secs < TM_YEAR * 2) { | 426 | if (secs < TM_YEAR * 2) { |
421 | htmlf("<span class='age-months'>%.0f months</span>", | 427 | htmlf("<span class='age-months'>%.0f months</span>", |
422 | secs * 1.0 / TM_MONTH); | 428 | secs * 1.0 / TM_MONTH); |
423 | return; | 429 | return; |
424 | } | 430 | } |
425 | htmlf("<span class='age-years'>%.0f years</span>", | 431 | htmlf("<span class='age-years'>%.0f years</span>", |
426 | secs * 1.0 / TM_YEAR); | 432 | secs * 1.0 / TM_YEAR); |
427 | } | 433 | } |
428 | 434 | ||
429 | void cgit_print_http_headers(struct cgit_context *ctx) | 435 | void cgit_print_http_headers(struct cgit_context *ctx) |
430 | { | 436 | { |
431 | if (ctx->page.mimetype && ctx->page.charset) | 437 | if (ctx->page.mimetype && ctx->page.charset) |
432 | htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, | 438 | htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, |
433 | ctx->page.charset); | 439 | ctx->page.charset); |
434 | else if (ctx->page.mimetype) | 440 | else if (ctx->page.mimetype) |
435 | htmlf("Content-Type: %s\n", ctx->page.mimetype); | 441 | htmlf("Content-Type: %s\n", ctx->page.mimetype); |
442 | if (ctx->page.size) | ||
443 | htmlf("Content-Length: %ld\n", ctx->page.size); | ||
436 | if (ctx->page.filename) | 444 | if (ctx->page.filename) |
437 | htmlf("Content-Disposition: inline; filename=\"%s\"\n", | 445 | htmlf("Content-Disposition: inline; filename=\"%s\"\n", |
438 | ctx->page.filename); | 446 | ctx->page.filename); |
439 | htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); | 447 | htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); |
440 | htmlf("Expires: %s\n", http_date(ctx->page.expires)); | 448 | htmlf("Expires: %s\n", http_date(ctx->page.expires)); |
441 | html("\n"); | 449 | html("\n"); |
442 | } | 450 | } |
443 | 451 | ||
444 | void cgit_print_docstart(struct cgit_context *ctx) | 452 | void cgit_print_docstart(struct cgit_context *ctx) |
445 | { | 453 | { |
446 | char *host = cgit_hosturl(); | 454 | char *host = cgit_hosturl(); |
447 | html(cgit_doctype); | 455 | html(cgit_doctype); |
448 | html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); | 456 | html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); |
449 | html("<head>\n"); | 457 | html("<head>\n"); |
450 | html("<title>"); | 458 | html("<title>"); |
451 | html_txt(ctx->page.title); | 459 | html_txt(ctx->page.title); |
452 | html("</title>\n"); | 460 | html("</title>\n"); |
453 | htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); | 461 | htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); |
454 | if (ctx->cfg.robots && *ctx->cfg.robots) | 462 | if (ctx->cfg.robots && *ctx->cfg.robots) |
455 | htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); | 463 | htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); |
456 | html("<link rel='stylesheet' type='text/css' href='"); | 464 | html("<link rel='stylesheet' type='text/css' href='"); |
457 | html_attr(ctx->cfg.css); | 465 | html_attr(ctx->cfg.css); |
458 | html("'/>\n"); | 466 | html("'/>\n"); |
459 | if (ctx->cfg.favicon) { | 467 | if (ctx->cfg.favicon) { |
460 | html("<link rel='shortcut icon' href='"); | 468 | html("<link rel='shortcut icon' href='"); |
461 | html_attr(ctx->cfg.favicon); | 469 | html_attr(ctx->cfg.favicon); |
462 | html("'/>\n"); | 470 | html("'/>\n"); |
463 | } | 471 | } |
464 | if (host && ctx->repo) { | 472 | if (host && ctx->repo) { |
465 | html("<link rel='alternate' title='Atom feed' href='http://"); | 473 | html("<link rel='alternate' title='Atom feed' href='http://"); |
466 | html_attr(cgit_hosturl()); | 474 | html_attr(cgit_hosturl()); |
467 | html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, | 475 | html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, |
468 | fmt("h=%s", ctx->qry.head))); | 476 | fmt("h=%s", ctx->qry.head))); |
469 | html("' type='application/atom+xml'/>"); | 477 | html("' type='application/atom+xml'/>"); |
470 | } | 478 | } |
471 | html("</head>\n"); | 479 | html("</head>\n"); |
472 | html("<body>\n"); | 480 | html("<body>\n"); |
473 | } | 481 | } |
474 | 482 | ||
475 | void cgit_print_docend() | 483 | void cgit_print_docend() |
476 | { | 484 | { |
477 | html("</div>"); | 485 | html("</div>"); |
478 | if (ctx.cfg.footer) | 486 | if (ctx.cfg.footer) |
479 | html_include(ctx.cfg.footer); | 487 | html_include(ctx.cfg.footer); |
480 | else { | 488 | else { |
481 | html("<div class='footer'>generated "); | 489 | html("<div class='footer'>generated "); |
482 | cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); | 490 | cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); |
483 | htmlf(" by cgit %s", cgit_version); | 491 | htmlf(" by cgit %s", cgit_version); |
484 | html("</div>\n"); | 492 | html("</div>\n"); |
485 | } | 493 | } |
486 | html("</body>\n</html>\n"); | 494 | html("</body>\n</html>\n"); |
487 | } | 495 | } |
488 | 496 | ||
489 | int print_branch_option(const char *refname, const unsigned char *sha1, | 497 | int print_branch_option(const char *refname, const unsigned char *sha1, |
490 | int flags, void *cb_data) | 498 | int flags, void *cb_data) |
491 | { | 499 | { |
492 | char *name = (char *)refname; | 500 | char *name = (char *)refname; |
493 | html_option(name, name, ctx.qry.head); | 501 | html_option(name, name, ctx.qry.head); |
494 | return 0; | 502 | return 0; |
495 | } | 503 | } |
496 | 504 | ||
497 | int print_archive_ref(const char *refname, const unsigned char *sha1, | 505 | int print_archive_ref(const char *refname, const unsigned char *sha1, |
498 | int flags, void *cb_data) | 506 | int flags, void *cb_data) |
499 | { | 507 | { |