cgit_repobasename: convert to allocated result

cgit_repobasename has one user also in ui-shared.c.  Make it static
and remove the declaration from cgit.h.

Instead of the gnarly return pointer to now deallocated stack,
compute the valid part of the string using the incoming pointer,
then just allocate the right amount and copy it in.  Drop the
const on the return type now it's allocated.

Cover the fact the input may be garbage by returning NULL if so.

Comment the function at the start that the result may be NULL or
must be freed now.

Convert the only user, cgit_snapshot_prefix(), to the same return
convention and also comment him at the start that the result may
be NULL or must be freed.  Also change the return type to char *.

Convert his only users, get_ref_from_filename() and
cgit_print_snapshot()in ui-snapshot.c, to deal with the new
result convention.  cgit_print_snapshot() already did an
xstrdup() on him anyway, just remove it and check for NULL.

The reason triggering all this was

../ui-shared.c: In function ‘cgit_repobasename’:
../ui-shared.c:135:2: warning: ‘strncpy’ specified bound 1024 equals destination size [-Wstringop-truncation]
  strncpy(rvbuf, reponame, sizeof(rvbuf));
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ comment from John Keeping.

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/ui-shared.c b/ui-shared.c
index a63dcb0..24fa9f7 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -127,35 +127,40 @@
 	return cgit_fileurl(reponame, pagename, NULL, query);
 }
 
-const char *cgit_repobasename(const char *reponame)
+/* result is NULL or must be freed */
+static char *cgit_repobasename(const char *reponame)
 {
-	/* I assume we don't need to store more than one repo basename */
-	static char rvbuf[1024];
-	int p;
-	const char *rv;
-	strncpy(rvbuf, reponame, sizeof(rvbuf));
-	if (rvbuf[sizeof(rvbuf)-1])
-		die("cgit_repobasename: truncated repository name '%s'", reponame);
-	p = strlen(rvbuf)-1;
-	/* strip trailing slashes */
-	while (p && rvbuf[p] == '/') rvbuf[p--] = 0;
-	/* strip trailing .git */
-	if (p >= 3 && starts_with(&rvbuf[p-3], ".git")) {
-		p -= 3; rvbuf[p--] = 0;
-	}
-	/* strip more trailing slashes if any */
-	while ( p && rvbuf[p] == '/') rvbuf[p--] = 0;
-	/* find last slash in the remaining string */
-	rv = strrchr(rvbuf,'/');
-	if (rv)
-		return ++rv;
-	return rvbuf;
+	int last = strlen(reponame) - 1, n;
+	char *rv;
+
+	if (last < 1)
+		return NULL;
+
+	while (last && reponame[last] == '/')
+		last--;
+
+	if (last >= 3 && !strncmp(&reponame[last - 3], ".git", 3))
+		last -= 3;
+
+	while (last && reponame[last] == '/')
+		last--;
+
+	n = last;
+	while (n && reponame[n] != '/')
+		n--;
+
+	rv = xmalloc(last - n + 2);
+	strncpy(rv, &reponame[n], last - n + 1);
+	rv[last - n + 1] = '\0';
+
+	return rv;
 }
 
-const char *cgit_snapshot_prefix(const struct cgit_repo *repo)
+/* result is NULL or must be freed */
+char *cgit_snapshot_prefix(const struct cgit_repo *repo)
 {
 	if (repo->snapshot_prefix)
-		return repo->snapshot_prefix;
+		return xstrdup(repo->snapshot_prefix);
 
 	return cgit_repobasename(repo->url);
 }