summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile15
-rw-r--r--cgit.c9
-rw-r--r--cgit.css5
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt15
-rwxr-xr-xfilters/syntax-highlighting.sh29
-rw-r--r--shared.c17
-rw-r--r--ui-repolist.c2
-rw-r--r--ui-shared.c11
-rw-r--r--ui-shared.h1
-rw-r--r--ui-tag.c24
-rw-r--r--ui-tree.c6
12 files changed, 94 insertions, 41 deletions
diff --git a/Makefile b/Makefile
index cb7875e..f8a4d47 100644
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,9 @@ INSTALL = install
 
 # 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).
 #
 
@@ -68,7 +71,7 @@ endif
 	$(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $<
 
 
-EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto
+EXTLIBS = git/libgit.a git/xdiff/lib.a -lz
 OBJECTS =
 OBJECTS += cache.o
 OBJECTS += cgit.o
@@ -124,6 +127,12 @@ endif
 ifdef NO_STRCASESTR
 	CFLAGS += -DNO_STRCASESTR
 endif
+ifdef NO_OPENSSL
+	CFLAGS += -DNO_OPENSSL
+	GIT_OPTIONS += NO_OPENSSL=1
+else
+	EXTLIBS += -lcrypto
+endif
 
 cgit: $(OBJECTS) libgit
 	$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
@@ -133,8 +142,8 @@ cgit.o: VERSION
 -include $(OBJECTS:.o=.d)
 
 libgit:
-	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 libgit.a
-	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 xdiff/lib.a
+	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a
+	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a
 
 test: all
 	$(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all
diff --git a/cgit.c b/cgit.c
index ff678fb..4f68a4b 100644
--- a/cgit.c
+++ b/cgit.c
@@ -68,9 +68,9 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
 		repo->section = xstrdup(value);
 	else if (!strcmp(name, "readme") && value != NULL) {
 		if (*value == '/')
-			ctx.repo->readme = xstrdup(value);
+			repo->readme = xstrdup(value);
 		else
-			ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
+			repo->readme = xstrdup(fmt("%s/%s", repo->path, value));
 	} else if (ctx.cfg.enable_filter_overrides) {
 		if (!strcmp(name, "about-filter"))
 			repo->about_filter = new_filter(value, 0);
@@ -165,6 +165,8 @@ void config_cb(const char *name, const char *value)
 		ctx.cfg.max_msg_len = atoi(value);
 	else if (!strcmp(name, "max-repodesc-length"))
 		ctx.cfg.max_repodesc_len = atoi(value);
+	else if (!strcmp(name, "max-blob-size"))
+		ctx.cfg.max_blob_size = atoi(value);
 	else if (!strcmp(name, "max-repo-count"))
 		ctx.cfg.max_repo_count = atoi(value);
 	else if (!strcmp(name, "max-commit-count"))
@@ -211,6 +213,8 @@ static void querystring_cb(const char *name, const char *value)
 	} else if (!strcmp(name, "p")) {
 		ctx.qry.page = xstrdup(value);
 	} else if (!strcmp(name, "url")) {
+		if (*value == '/')
+			value++;
 		ctx.qry.url = xstrdup(value);
 		cgit_parse_url(value);
 	} else if (!strcmp(name, "qt")) {
@@ -272,6 +276,7 @@ static void prepare_context(struct cgit_context *ctx)
 	ctx->cfg.max_lock_attempts = 5;
 	ctx->cfg.max_msg_len = 80;
 	ctx->cfg.max_repodesc_len = 80;
+	ctx->cfg.max_blob_size = 0;
 	ctx->cfg.max_stats = 0;
 	ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
 	ctx->cfg.renamelimit = -1;
diff --git a/cgit.css b/cgit.css
index 9e6d2a4..0cb894a 100644
--- a/cgit.css
+++ b/cgit.css
@@ -162,6 +162,11 @@ table.list td a {
 	color: black;
 }
 
+table.list td a.ls-dir {
+	font-weight: bold;
+	color: #00f;
+}
+
 table.list td a:hover {
 	color: #00f;
 }
diff --git a/cgit.h b/cgit.h
index b7b0adb..5941ec0 100644
--- a/cgit.h
+++ b/cgit.h
@@ -186,6 +186,7 @@ struct cgit_config {
 	int max_lock_attempts;
 	int max_msg_len;
 	int max_repodesc_len;
+	int max_blob_size;
 	int max_stats;
 	int nocache;
 	int noplainemail;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 252d546..70e4c78 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -1,3 +1,6 @@
+:man source:   cgit
+:man manual:   cgit
+
 CGITRC(5)
 ========
 
@@ -174,6 +177,10 @@ max-repodesc-length::
 	Specifies the maximum number of repo description characters to display
 	on the repository index page. Default value: "80".
 
+max-blob-size::
+	Specifies the maximum size of a blob to display HTML for in KBytes.
+	Default value: "0" (limit disabled).
+
 max-stats::
 	Set the default maximum statistics period. Valid values are "week",
 	"month", "quarter" and "year". If unspecified, statistics are
@@ -425,8 +432,8 @@ mimetype.svg=image/svg+xml
 
 ##
 ## List of repositories.
-## PS: Any repositories listed when repo.group is unset will not be
-##     displayed under a group heading
+## PS: Any repositories listed when section is unset will not be
+##     displayed under a section heading
 ## PPS: This list could be kept in a different file (e.g. '/etc/cgitrepos')
 ##      and included like this:
 ##        include=/etc/cgitrepos
@@ -448,7 +455,7 @@ repo.readme=info/web/about.html
 
 
 # The next repositories will be displayed under the 'extras' heading
-repo.group=extras
+section=extras
 
 
 repo.url=baz
@@ -461,7 +468,7 @@ repo.desc=the wizard of foo
 
 
 # Add some mirrored repositories
-repo.group=mirrors
+section=mirrors
 
 
 repo.url=git
diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh
index 999ad0c..6b1c576 100755
--- a/filters/syntax-highlighting.sh
+++ b/filters/syntax-highlighting.sh
@@ -3,6 +3,10 @@
 # tree-view by refering to this file with the source-filter or repo.source-
 # filter options in cgitrc.
 #
+# This script requires a shell supporting the ${var##pattern} syntax.
+# It is supported by at least dash and bash, however busybox environments
+# might have to use an external call to sed instead.
+#
 # Note: the highlight command (http://www.andre-simon.de/) uses css for syntax
 # highlighting, so you'll probably want something like the following included
 # in your css file (generated by highlight 2.4.8 and adapted for cgit):
@@ -20,20 +24,11 @@
 # table.blob .kwc  { color:#000000; font-weight:bold; }
 # table.blob .kwd  { color:#010181; }
 
-case "$1" in
-	*.c)
-		highlight -f -I -X -S c
-		;;
-	*.h)
-		highlight -f -I -X -S c
-		;;
-	*.sh)
-		highlight -f -I -X -S sh
-		;;
-	*.css)
-		highlight -f -I -X -S css
-		;;
-	*)
-		highlight -f -I -X -S txt
-		;;
-esac
+# store filename and extension in local vars
+BASENAME="$1"
+EXTENSION="${BASENAME##*.}"
+
+# map Makefile and Makefile.* to .mk
+[ "${BASENAME%%.*}" == "Makefile" ] && EXTENSION=mk
+
+exec highlight --force -f -I -X -S $EXTENSION 2>/dev/null
diff --git a/shared.c b/shared.c
index d7b2d5a..9362d21 100644
--- a/shared.c
+++ b/shared.c
@@ -400,18 +400,25 @@ int cgit_close_filter(struct cgit_filter *filter)
  */
 int readfile(const char *path, char **buf, size_t *size)
 {
-	int fd;
+	int fd, e;
 	struct stat st;
 
 	fd = open(path, O_RDONLY);
 	if (fd == -1)
 		return errno;
-	if (fstat(fd, &st))
-		return errno;
-	if (!S_ISREG(st.st_mode))
+	if (fstat(fd, &st)) {
+		e = errno;
+		close(fd);
+		return e;
+	}
+	if (!S_ISREG(st.st_mode)) {
+		close(fd);
 		return EISDIR;
+	}
 	*buf = xmalloc(st.st_size + 1);
 	*size = read_in_full(fd, *buf, st.st_size);
+	e = errno;
 	(*buf)[*size] = '\0';
-	return (*size == st.st_size ? 0 : errno);
+	close(fd);
+	return (*size == st.st_size ? 0 : e);
 }
diff --git a/ui-repolist.c b/ui-repolist.c
index 3ef2e99..0a0b6ca 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -94,7 +94,7 @@ int is_in_url(struct cgit_repo *repo)
 
 void print_sort_header(const char *title, const char *sort)
 {
-	htmlf("<th class='left'><a href='./?s=%s", sort);
+	htmlf("<th class='left'><a href='%s?s=%s", cgit_rooturl(), sort);
 	if (ctx.qry.search) {
 		html("&q=");
 		html_url_arg(ctx.qry.search);
diff --git a/ui-shared.c b/ui-shared.c
index de55eff..08ea003 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -20,7 +20,7 @@ static char *http_date(time_t t)
 		{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
 	static char month[][4] =
 		{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		 "Jul", "Aug", "Sep", "Oct", "Now", "Dec"};
+		 "Jul", "Aug", "Sep", "Oct", "Nov", "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,
@@ -782,13 +782,18 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
 			       const char *hex, int snapshots)
 {
 	const struct cgit_snapshot_format* f;
+	char *prefix;
     	char *filename;
+	unsigned char sha1[20];
 
+	if (get_sha1(fmt("refs/tags/%s", hex), sha1) == 0 &&
+	    (hex[0] == 'v' || hex[0] == 'V') && isdigit(hex[1]))
+		hex++;
+	prefix = xstrdup(fmt("%s-%s", cgit_repobasename(repo), hex));
 	for (f = cgit_snapshot_formats; f->suffix; f++) {
 		if (!(snapshots & f->bit))
 			continue;
-		filename = fmt("%s-%s%s", cgit_repobasename(repo), hex,
-			       f->suffix);
+		filename = fmt("%s%s", prefix, f->suffix);
 		cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
 		html("<br/>");
 	}
diff --git a/ui-shared.h b/ui-shared.h
index 166246d..9ebc1f9 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -3,6 +3,7 @@
 
 extern char *cgit_httpscheme();
 extern char *cgit_hosturl();
+extern char *cgit_rooturl();
 extern char *cgit_repourl(const char *reponame);
 extern char *cgit_fileurl(const char *reponame, const char *pagename,
 			  const char *filename, const char *query);
diff --git a/ui-tag.c b/ui-tag.c
index c2d72af..39e4cb8 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -30,6 +30,14 @@ static void print_tag_content(char *buf)
 	}
 }
 
+void print_download_links(char *revname)
+{
+	html("<tr><th>download</th><td class='sha1'>");
+	cgit_print_snapshot_links(ctx.qry.repo, ctx.qry.head,
+				  revname, ctx.repo->snapshots);
+	html("</td></tr>");
+}
+
 void cgit_print_tag(char *revname)
 {
 	unsigned char sha1[20];
@@ -56,16 +64,16 @@ void cgit_print_tag(char *revname)
 			return;
 		}
 		html("<table class='commit-info'>\n");
-		htmlf("<tr><td>Tag name</td><td>");
+		htmlf("<tr><td>tag name</td><td>");
 		html_txt(revname);
 		htmlf(" (%s)</td></tr>\n", sha1_to_hex(sha1));
 		if (info->tagger_date > 0) {
-			html("<tr><td>Tag date</td><td>");
+			html("<tr><td>tag date</td><td>");
 			cgit_print_date(info->tagger_date, FMT_LONGDATE, ctx.cfg.local_time);
 			html("</td></tr>\n");
 		}
 		if (info->tagger) {
-			html("<tr><td>Tagged by</td><td>");
+			html("<tr><td>tagged by</td><td>");
 			html_txt(info->tagger);
 			if (info->tagger_email && !ctx.cfg.noplainemail) {
 				html(" ");
@@ -73,19 +81,23 @@ void cgit_print_tag(char *revname)
 			}
 			html("</td></tr>\n");
 		}
-		html("<tr><td>Tagged object</td><td>");
+		html("<tr><td>tagged object</td><td class='sha1'>");
 		cgit_object_link(tag->tagged);
 		html("</td></tr>\n");
+		if (ctx.repo->snapshots)
+			print_download_links(revname);
 		html("</table>\n");
 		print_tag_content(info->msg);
 	} else {
 		html("<table class='commit-info'>\n");
-		htmlf("<tr><td>Tag name</td><td>");
+		htmlf("<tr><td>tag name</td><td>");
 		html_txt(revname);
 		html("</td></tr>\n");
-		html("<tr><td>Tagged object</td><td>");
+		html("<tr><td>Tagged object</td><td class='sha1'>");
 		cgit_object_link(obj);
 		html("</td></tr>\n");
+		if (ctx.repo->snapshots)
+			print_download_links(revname);
 		html("</table>\n");
         }
 	return;
diff --git a/ui-tree.c b/ui-tree.c
index f53ab64..f281937 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -107,6 +107,12 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
 		        curr_rev, path);
 	htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
 
+	if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
+		htmlf("<div class='error'>blob size (%dKB) exceeds display size limit (%dKB).</div>",
+				size / 1024, ctx.cfg.max_blob_size);
+		return;
+	}
+
 	if (buffer_is_binary(buf, size))
 		print_binary_buffer(buf, size);
 	else