-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | cgit.c | 5 | ||||
-rw-r--r-- | html.c | 2 | ||||
-rw-r--r-- | ui-shared.c | 2 |
4 files changed, 7 insertions, 6 deletions
@@ -1,65 +1,65 @@ -CGIT_VERSION = v0.8.3.4 +CGIT_VERSION = v0.8.3.5 CGIT_SCRIPT_NAME = cgit.cgi CGIT_SCRIPT_PATH = /var/www/htdocs/cgit CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) CGIT_CONFIG = /etc/cgitrc CACHE_ROOT = /var/cache/cgit prefix = /usr libdir = $(prefix)/lib filterdir = $(libdir)/cgit/filters docdir = $(prefix)/share/doc/cgit htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = <openssl/sha.h> GIT_VER = 1.7.4 GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 INSTALL = install MAN5_TXT = $(wildcard *.5.txt) MAN_TXT = $(MAN5_TXT) DOC_MAN5 = $(patsubst %.txt,%,$(MAN5_TXT)) DOC_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) DOC_PDF = $(patsubst %.txt,%.pdf,$(MAN_TXT)) # Define NO_STRCASESTR if you don't have strcasestr. # # Define NO_OPENSSL to disable linking with OpenSSL and use bundled SHA1 # implementation (slower). # # Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). # # Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.) # do not support the 'size specifiers' introduced by C99, namely ll, hh, # j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t). # some C compilers supported these specifiers prior to C99 as an extension. # #-include config.mak # # Platform specific tweaks # uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') ifeq ($(uname_O),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease endif # # Let the user override the above settings. # -include cgit.conf # # Define a way to invoke make in subdirs quietly, shamelessly ripped # from git.git # QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir QUIET_SUBDIR1 = ifneq ($(findstring $(MAKEFLAGS),w),w) PRINT_DIR = --no-print-directory @@ -180,65 +180,65 @@ install: all $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH) $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png $(INSTALL) -m 0755 -d $(DESTDIR)$(filterdir) $(INSTALL) -m 0755 filters/* $(DESTDIR)$(filterdir) install-doc: install-man install-html install-pdf install-man: doc-man $(INSTALL) -m 0755 -d $(DESTDIR)$(mandir)/man5 $(INSTALL) -m 0644 $(DOC_MAN5) $(DESTDIR)$(mandir)/man5 install-html: doc-html $(INSTALL) -m 0755 -d $(DESTDIR)$(htmldir) $(INSTALL) -m 0644 $(DOC_HTML) $(DESTDIR)$(htmldir) install-pdf: doc-pdf $(INSTALL) -m 0755 -d $(DESTDIR)$(pdfdir) $(INSTALL) -m 0644 $(DOC_PDF) $(DESTDIR)$(pdfdir) uninstall: rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) rm -f $(CGIT_DATA_PATH)/cgit.css rm -f $(CGIT_DATA_PATH)/cgit.png uninstall-doc: uninstall-man uninstall-html uninstall-pdf uninstall-man: @for i in $(DOC_MAN5); do \ rm -fv $(DESTDIR)$(mandir)/man5/$$i; \ done uninstall-html: @for i in $(DOC_HTML); do \ rm -fv $(DESTDIR)$(htmldir)/$$i; \ done uninstall-pdf: @for i in $(DOC_PDF); do \ rm -fv $(DESTDIR)$(pdfdir)/$$i; \ done doc: doc-man doc-html doc-pdf doc-man: doc-man5 doc-man5: $(DOC_MAN5) doc-html: $(DOC_HTML) doc-pdf: $(DOC_PDF) %.5 : %.5.txt a2x -f manpage $< $(DOC_HTML): %.html : %.txt a2x -f xhtml --stylesheet=cgit-doc.css $< $(DOC_PDF): %.pdf : %.txt a2x -f pdf cgitrc.5.txt clean: clean-doc rm -f cgit VERSION *.o *.d clean-doc: rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo get-git: - curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git + curl $(GIT_URL) | tar -xjf - && rm -rf git && mv git-$(GIT_VER) git @@ -691,101 +691,102 @@ static void cgit_parse_args(int argc, const char **argv) ctx.qry.sha1 = xstrdup(argv[i]+7); ctx.qry.has_sha1 = 1; } if (!strncmp(argv[i], "--ofs=", 6)) { ctx.qry.ofs = atoi(argv[i]+6); } if (!strncmp(argv[i], "--scan-tree=", 12) || !strncmp(argv[i], "--scan-path=", 12)) { /* HACK: the global snapshot bitmask defines the * set of allowed snapshot formats, but the config * file hasn't been parsed yet so the mask is * currently 0. By setting all bits high before * scanning we make sure that any in-repo cgitrc * snapshot setting is respected by scan_tree(). * BTW: we assume that there'll never be more than * 255 different snapshot formats supported by cgit... */ ctx.cfg.snapshots = 0xFF; scan++; scan_tree(argv[i] + 12, repo_config); } } if (scan) { qsort(cgit_repolist.repos, cgit_repolist.count, sizeof(struct cgit_repo), cmp_repos); print_repolist(stdout, &cgit_repolist, 0); exit(0); } } static int calc_ttl() { if (!ctx.repo) return ctx.cfg.cache_root_ttl; if (!ctx.qry.page) return ctx.cfg.cache_repo_ttl; if (ctx.qry.has_symref) return ctx.cfg.cache_dynamic_ttl; if (ctx.qry.has_sha1) return ctx.cfg.cache_static_ttl; return ctx.cfg.cache_repo_ttl; } int main(int argc, const char **argv) { const char *path; char *qry; int err, ttl; prepare_context(&ctx); cgit_repolist.length = 0; cgit_repolist.count = 0; cgit_repolist.repos = NULL; cgit_parse_args(argc, argv); parse_configfile(expand_macros(ctx.env.cgit_config), config_cb); ctx.repo = NULL; http_parse_querystring(ctx.qry.raw, querystring_cb); /* If virtual-root isn't specified in cgitrc, lets pretend - * that virtual-root equals SCRIPT_NAME. + * that virtual-root equals SCRIPT_NAME, minus any possibly + * trailing slashes. */ if (!ctx.cfg.virtual_root) - ctx.cfg.virtual_root = ctx.cfg.script_name; + ctx.cfg.virtual_root = trim_end(ctx.cfg.script_name, '/'); /* If no url parameter is specified on the querystring, lets * use PATH_INFO as url. This allows cgit to work with virtual * urls without the need for rewriterules in the webserver (as * long as PATH_INFO is included in the cache lookup key). */ path = ctx.env.path_info; if (!ctx.qry.url && path) { if (path[0] == '/') path++; ctx.qry.url = xstrdup(path); if (ctx.qry.raw) { qry = ctx.qry.raw; ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); free(qry); } else ctx.qry.raw = xstrdup(ctx.qry.url); cgit_parse_url(ctx.qry.url); } ttl = calc_ttl(); ctx.page.expires += ttl*60; if (ctx.env.request_method && !strcmp(ctx.env.request_method, "HEAD")) ctx.cfg.nocache = 1; if (ctx.cfg.nocache) ctx.cfg.cache_size = 0; err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, ctx.qry.raw, ttl, process_request, &ctx); if (err) cgit_print_error(fmt("Error processing page: %s (%d)", strerror(err), err)); return err; } @@ -216,105 +216,105 @@ void html_link_open(const char *url, const char *title, const char *class) html("<a href='"); html_attr(url); if (title) { html("' title='"); html_attr(title); } if (class) { html("' class='"); html_attr(class); } html("'>"); } void html_link_close(void) { html("</a>"); } void html_fileperm(unsigned short mode) { htmlf("%c%c%c", (mode & 4 ? 'r' : '-'), (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-')); } int html_include(const char *filename) { FILE *f; char buf[4096]; size_t len; if (!(f = fopen(filename, "r"))) { fprintf(stderr, "[cgit] Failed to include file %s: %s (%d).\n", filename, strerror(errno), errno); return -1; } while((len = fread(buf, 1, 4096, f)) > 0) html_raw(buf, len); fclose(f); return 0; } int hextoint(char c) { if (c >= 'a' && c <= 'f') return 10 + c - 'a'; else if (c >= 'A' && c <= 'F') return 10 + c - 'A'; else if (c >= '0' && c <= '9') return c - '0'; else return -1; } char *convert_query_hexchar(char *txt) { int d1, d2, n; n = strlen(txt); if (n < 3) { *txt = '\0'; return txt-1; } d1 = hextoint(*(txt+1)); d2 = hextoint(*(txt+2)); if (d1<0 || d2<0) { - memmove(txt, txt+3, n-3); + memmove(txt, txt+3, n-2); return txt-1; } else { *txt = d1 * 16 + d2; memmove(txt+1, txt+3, n-2); return txt; } } int http_parse_querystring(const char *txt_, void (*fn)(const char *name, const char *value)) { char *t, *txt, *value = NULL, c; if (!txt_) return 0; t = txt = strdup(txt_); if (t == NULL) { printf("Out of memory\n"); exit(1); } while((c=*t) != '\0') { if (c=='=') { *t = '\0'; value = t+1; } else if (c=='+') { *t = ' '; } else if (c=='%') { t = convert_query_hexchar(t); } else if (c=='&') { *t = '\0'; (*fn)(txt, value); txt = t+1; value = NULL; } t++; } if (t!=txt) (*fn)(txt, value); return 0; } diff --git a/ui-shared.c b/ui-shared.c index 7efae7a..5aa9119 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -513,129 +513,129 @@ void cgit_print_date(time_t secs, const char *format, int local_time) if(local_time) time = localtime(&secs); else time = gmtime(&secs); strftime(buf, sizeof(buf)-1, format, time); html_txt(buf); } void cgit_print_age(time_t t, time_t max_relative, const char *format) { time_t now, secs; if (!t) return; time(&now); secs = now - t; if (secs > max_relative && max_relative >= 0) { cgit_print_date(t, format, ctx.cfg.local_time); return; } if (secs < TM_HOUR * 2) { htmlf("<span class='age-mins'>%.0f min.</span>", secs * 1.0 / TM_MIN); return; } if (secs < TM_DAY * 2) { htmlf("<span class='age-hours'>%.0f hours</span>", secs * 1.0 / TM_HOUR); return; } if (secs < TM_WEEK * 2) { htmlf("<span class='age-days'>%.0f days</span>", secs * 1.0 / TM_DAY); return; } if (secs < TM_MONTH * 2) { htmlf("<span class='age-weeks'>%.0f weeks</span>", secs * 1.0 / TM_WEEK); return; } if (secs < TM_YEAR * 2) { htmlf("<span class='age-months'>%.0f months</span>", secs * 1.0 / TM_MONTH); return; } htmlf("<span class='age-years'>%.0f years</span>", secs * 1.0 / TM_YEAR); } void cgit_print_http_headers(struct cgit_context *ctx) { if (ctx->env.no_http && !strcmp(ctx->env.no_http, "1")) return; if (ctx->page.status) htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg); if (ctx->page.mimetype && ctx->page.charset) htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, ctx->page.charset); else if (ctx->page.mimetype) htmlf("Content-Type: %s\n", ctx->page.mimetype); if (ctx->page.size) - htmlf("Content-Length: %ld\n", ctx->page.size); + htmlf("Content-Length: %zd\n", ctx->page.size); if (ctx->page.filename) htmlf("Content-Disposition: inline; filename=\"%s\"\n", ctx->page.filename); htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); htmlf("Expires: %s\n", http_date(ctx->page.expires)); if (ctx->page.etag) htmlf("ETag: \"%s\"\n", ctx->page.etag); html("\n"); if (ctx->env.request_method && !strcmp(ctx->env.request_method, "HEAD")) exit(0); } void cgit_print_docstart(struct cgit_context *ctx) { if (ctx->cfg.embedded) { if (ctx->cfg.header) html_include(ctx->cfg.header); return; } char *host = cgit_hosturl(); html(cgit_doctype); html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); html("<head>\n"); html("<title>"); html_txt(ctx->page.title); html("</title>\n"); htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); if (ctx->cfg.robots && *ctx->cfg.robots) htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); html("<link rel='stylesheet' type='text/css' href='"); html_attr(ctx->cfg.css); html("'/>\n"); if (ctx->cfg.favicon) { html("<link rel='shortcut icon' href='"); html_attr(ctx->cfg.favicon); html("'/>\n"); } if (host && ctx->repo) { html("<link rel='alternate' title='Atom feed' href='"); html(cgit_httpscheme()); html_attr(cgit_hosturl()); html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.vpath, fmt("h=%s", ctx->qry.head))); html("' type='application/atom+xml'/>\n"); } if (ctx->cfg.head_include) html_include(ctx->cfg.head_include); html("</head>\n"); html("<body>\n"); if (ctx->cfg.header) html_include(ctx->cfg.header); } void cgit_print_docend() { html("</div> <!-- class=content -->\n"); if (ctx.cfg.embedded) { html("</div> <!-- id=cgit -->\n"); if (ctx.cfg.footer) html_include(ctx.cfg.footer); return; } if (ctx.cfg.footer) |