commit - f17dbdbfb4e1e00cf8a8371add4a43caafc8516e
commit + adaf63907ce7d1b5dc45b6b7405087879332247f
blob - f5f240b7d414b6737f10eb222651623aef0067e3
blob + 24a9352100d646dad06a2b1e5b107b6a99b471b8
--- gotwebd/config.c
+++ gotwebd/config.c
#include <util.h>
#include <errno.h>
#include <imsg.h>
+#include <sha1.h>
+#include <sha2.h>
#include "got_opentemp.h"
#include "got_reference.h"
+#include "got_object.h"
#include "gotwebd.h"
#include "log.h"
blob - 7aded7f0ba3070a6bf7233a97f5272a4baefc58b
blob + 89ead404546314fa3c7d49a1fe5e7f58d495a1c5
--- gotwebd/fcgi.c
+++ gotwebd/fcgi.c
#include <sys/types.h>
#include <sys/uio.h>
+#include <ctype.h>
#include <errno.h>
#include <event.h>
#include <imsg.h>
+#include <sha1.h>
+#include <sha2.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include "got_error.h"
#include "got_reference.h"
+#include "got_object.h"
#include "got_lib_poll.h"
uint8_t *record_body;
struct gotwebd_fcgi_params params = { 0 };
+ fcgi_init_querystring(¶ms.qs);
+
if (rec->record_len < sizeof(struct fcgi_record_header) ||
rec->record_len > sizeof(rec->record)) {
log_warnx("invalid fcgi record size");
}
}
+static const struct querystring_keys querystring_keys[] = {
+ { "action", ACTION },
+ { "commit", COMMIT },
+ { "file", RFILE },
+ { "folder", FOLDER },
+ { "headref", HEADREF },
+ { "index_page", INDEX_PAGE },
+ { "path", PATH },
+};
+
+static const struct action_keys action_keys[] = {
+ { "blame", BLAME },
+ { "blob", BLOB },
+ { "blobraw", BLOBRAW },
+ { "briefs", BRIEFS },
+ { "commits", COMMITS },
+ { "diff", DIFF },
+ { "error", ERR },
+ { "index", INDEX },
+ { "patch", PATCH },
+ { "summary", SUMMARY },
+ { "tag", TAG },
+ { "tags", TAGS },
+ { "tree", TREE },
+ { "rss", RSS },
+};
+
+
+void
+fcgi_init_querystring(struct querystring *qs)
+{
+ memset(qs, 0, sizeof(*qs));
+ qs->action = NO_ACTION;
+ qs->index_page = -1;
+}
+
+/*
+ * Adapted from usr.sbin/httpd/httpd.c url_decode.
+ */
+static const struct got_error *
+urldecode(char *url)
+{
+ char *p, *q;
+ char hex[3];
+ unsigned long x;
+
+ hex[2] = '\0';
+ p = q = url;
+
+ while (*p != '\0') {
+ switch (*p) {
+ case '%':
+ /* Encoding character is followed by two hex chars */
+ if (!isxdigit((unsigned char)p[1]) ||
+ !isxdigit((unsigned char)p[2]) ||
+ (p[1] == '0' && p[2] == '0'))
+ return got_error(GOT_ERR_BAD_QUERYSTRING);
+
+ hex[0] = p[1];
+ hex[1] = p[2];
+
+ /*
+ * We don't have to validate "hex" because it is
+ * guaranteed to include two hex chars followed by nul.
+ */
+ x = strtoul(hex, NULL, 16);
+ *q = (char)x;
+ p += 2;
+ break;
+ default:
+ *q = *p;
+ break;
+ }
+ p++;
+ q++;
+ }
+ *q = '\0';
+
+ return NULL;
+}
+
+static const struct got_error *
+assign_querystring(struct querystring *qs, char *key, char *value)
+{
+ const struct got_error *error = NULL;
+ const char *errstr;
+ int a_cnt, el_cnt;
+
+ error = urldecode(value);
+ if (error)
+ return error;
+
+ for (el_cnt = 0; el_cnt < nitems(querystring_keys); el_cnt++) {
+ if (strcmp(key, querystring_keys[el_cnt].name) != 0)
+ continue;
+
+ switch (querystring_keys[el_cnt].element) {
+ case ACTION:
+ for (a_cnt = 0; a_cnt < nitems(action_keys); a_cnt++) {
+ if (strcmp(value, action_keys[a_cnt].name) != 0)
+ continue;
+ qs->action = action_keys[a_cnt].action;
+ break;
+ }
+ if (a_cnt == nitems(action_keys))
+ qs->action = ERR;
+ break;
+ case COMMIT:
+ if (strlcpy(qs->commit, value, sizeof(qs->commit)) >=
+ sizeof(qs->commit)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "requested commit ID too long");
+ goto done;
+ }
+ break;
+ case RFILE:
+ if (strlcpy(qs->file, value, sizeof(qs->file)) >=
+ sizeof(qs->file)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "requested in-repository path too long");
+ goto done;
+ }
+ break;
+ case FOLDER:
+ if (strlcpy(qs->folder, value[0] ? value : "/",
+ sizeof(qs->folder)) >= sizeof(qs->folder)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "requested repository folder path "
+ "too long");
+ goto done;
+ }
+ break;
+ case HEADREF:
+ if (strlcpy(qs->headref, value, sizeof(qs->headref)) >=
+ sizeof(qs->headref)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "requested repository head ref too long");
+ goto done;
+ }
+ break;
+ case INDEX_PAGE:
+ if (*value == '\0')
+ break;
+ qs->index_page = strtonum(value, INT64_MIN,
+ INT64_MAX, &errstr);
+ if (errstr) {
+ error = got_error_from_errno3(__func__,
+ "strtonum", errstr);
+ goto done;
+ }
+ if (qs->index_page < 0)
+ qs->index_page = 0;
+ break;
+ case PATH:
+ if (strlcpy(qs->path, value, sizeof(qs->path)) >=
+ sizeof(qs->path)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "requested repository path too long");
+ goto done;
+ }
+ break;
+ }
+
+ /* entry found */
+ break;
+ }
+done:
+ return error;
+}
+
+static const struct got_error *
+parse_querystring(struct querystring *qs, char *qst)
+{
+ const struct got_error *error = NULL;
+ char *tok1 = NULL, *tok1_pair = NULL, *tok1_end = NULL;
+ char *tok2 = NULL, *tok2_pair = NULL, *tok2_end = NULL;
+
+ if (qst == NULL)
+ return error;
+
+ tok1 = strdup(qst);
+ if (tok1 == NULL)
+ return got_error_from_errno2(__func__, "strdup");
+
+ tok1_pair = tok1;
+ tok1_end = tok1;
+
+ while (tok1_pair != NULL) {
+ strsep(&tok1_end, "&");
+
+ tok2 = strdup(tok1_pair);
+ if (tok2 == NULL) {
+ free(tok1);
+ return got_error_from_errno2(__func__, "strdup");
+ }
+
+ tok2_pair = tok2;
+ tok2_end = tok2;
+
+ while (tok2_pair != NULL) {
+ strsep(&tok2_end, "=");
+ if (tok2_end) {
+ error = assign_querystring(qs, tok2_pair,
+ tok2_end);
+ if (error)
+ goto err;
+ }
+ tok2_pair = tok2_end;
+ }
+ free(tok2);
+ tok1_pair = tok1_end;
+ }
+ free(tok1);
+ return error;
+err:
+ free(tok2);
+ free(tok1);
+ return error;
+}
+
int
fcgi_parse_params(uint8_t *buf, uint16_t n, struct gotwebd_fcgi_params *params)
{
+ const struct got_error *error;
uint32_t name_len, val_len;
uint8_t *val;
val = buf + name_len;
- if (val_len < MAX_QUERYSTRING &&
- name_len == 12 &&
+ if (val_len < MAX_QUERYSTRING && name_len == 12 &&
strncmp(buf, "QUERY_STRING", 12) == 0) {
- /* TODO: parse querystring here */
- memcpy(params->querystring, val, val_len);
- params->querystring[val_len] = '\0';
+ char querystring[MAX_QUERYSTRING];
+
+ memcpy(querystring, val, val_len);
+ querystring[val_len] = '\0';
+
+ fcgi_init_querystring(¶ms->qs);
+
+ error = parse_querystring(¶ms->qs, querystring);
+ if (error) {
+ log_warnx("%s: %s", __func__, error->msg);
+ return -1;
+ }
}
if (val_len < MAX_DOCUMENT_URI &&
blob - 2846bbbddb83f63677ac8b3ef56540c5407ccb7f
blob + 18120ebaddfa19651ad40001d9a26efde8f40271
--- gotwebd/got_operations.c
+++ gotwebd/got_operations.c
struct got_object_id *id2 = NULL;
struct got_object_qid *parent_id;
struct transport *t = c->t;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
char *commit_msg = NULL, *commit_msg0;
TAILQ_FOREACH(re, refs, entry) {
struct repo_commit *repo_commit = NULL;
struct transport *t = c->t;
struct got_repository *repo = t->repo;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
char *file_path = NULL;
int chk_next = 0;
TAILQ_INIT(&refs);
- if (qs->file != NULL && *qs->file != '\0')
- if (asprintf(&file_path, "%s/%s", qs->folder ? qs->folder : "",
- qs->file) == -1)
+ if (qs->file[0]) {
+ if (asprintf(&file_path, "%s/%s",
+ qs->folder[0] ? qs->folder : "", qs->file) == -1)
return got_error_from_errno("asprintf");
+ }
- if (qs->commit) {
+ if (qs->commit[0]) {
error = got_repo_match_object_id_prefix(&id, qs->commit,
GOT_OBJ_TYPE_COMMIT, repo);
if (error)
if (error)
goto done;
- if (qs->file != NULL && *qs->file != '\0') {
+ if (qs->file[0]) {
error = got_commit_graph_open(&graph, file_path, 0);
if (error)
goto done;
struct server *srv = c->srv;
struct transport *t = c->t;
struct got_repository *repo = t->repo;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct repo_dir *repo_dir = t->repo_dir;
struct got_tag_object *tag = NULL;
char *repo_path = NULL, *id_str = NULL;
repo_dir->name) == -1)
return got_error_from_errno("asprintf");
- if (qs->commit == NULL && (qs->action == TAGS || qs->action == RSS)) {
+ if (qs->commit[0] == '\0' &&
+ (qs->action == TAGS || qs->action == RSS)) {
error = got_ref_open(&ref, repo, qs->headref, 0);
if (error)
goto done;
got_ref_close(ref);
if (error)
goto done;
- } else if (qs->commit == NULL && qs->action == TAG) {
+ } else if (qs->commit[0] == '\0' && qs->action == TAG) {
error = got_error_msg(GOT_ERR_EOF, "commit id missing");
goto done;
} else {
if (new_repo_tag->commit_id == NULL)
goto done;
- if (commit_found == 0 && qs->commit != NULL &&
+ if (commit_found == 0 && qs->commit[0] &&
strncmp(id_str, qs->commit, strlen(id_str)) != 0) {
if (commit) {
got_object_commit_close(commit);
struct transport *t = c->t;
struct got_commit_object *commit = NULL;
struct got_repository *repo = t->repo;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct repo_commit *rc = NULL;
struct got_object_id *tree_id = NULL, *commit_id = NULL;
struct got_reflist_head refs;
goto done;
error = got_object_id_by_path(&tree_id, repo, commit,
- qs->folder ? qs->folder : "/");
+ qs->folder[0] ? qs->folder : "/");
if (error)
goto done;
const struct got_error *error = NULL;
struct transport *t = c->t;
struct got_repository *repo = t->repo;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
struct got_object_id *obj_id = NULL, *commit_id = NULL;
struct got_commit_object *commit = NULL;
struct got_reflist_head refs;
blob - 0110849b3a6f7e927de2262f945532273047ca83
blob + a68f85d91a5e27ea18c3134c49e219999d434a19
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
#include <sys/stat.h>
#include <sys/types.h>
-#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <event.h>
#include "gotwebd.h"
#include "log.h"
#include "tmpl.h"
-
-static const struct querystring_keys querystring_keys[] = {
- { "action", ACTION },
- { "commit", COMMIT },
- { "file", RFILE },
- { "folder", FOLDER },
- { "headref", HEADREF },
- { "index_page", INDEX_PAGE },
- { "path", PATH },
-};
-
-static const struct action_keys action_keys[] = {
- { "blame", BLAME },
- { "blob", BLOB },
- { "blobraw", BLOBRAW },
- { "briefs", BRIEFS },
- { "commits", COMMITS },
- { "diff", DIFF },
- { "error", ERR },
- { "index", INDEX },
- { "patch", PATCH },
- { "summary", SUMMARY },
- { "tag", TAG },
- { "tags", TAGS },
- { "tree", TREE },
- { "rss", RSS },
-};
-static const struct got_error *gotweb_init_querystring(struct querystring **);
-static const struct got_error *gotweb_parse_querystring(struct querystring *,
- char *);
-static const struct got_error *gotweb_assign_querystring(struct querystring *,
- char *, char *);
static int gotweb_render_index(struct template *);
static const struct got_error *gotweb_load_got_path(struct repo_dir **,
const char *, struct request *);
static const struct got_error *gotweb_get_clone_url(char **, struct server *,
const char *, int);
-static void gotweb_free_querystring(struct querystring *);
static void gotweb_free_repo_dir(struct repo_dir *);
struct server *gotweb_get_server(const char *);
size_t len;
int r, binary = 0;
- /* parse our querystring */
- error = gotweb_init_querystring(&qs);
- if (error) {
- log_warnx("%s: %s", __func__, error->msg);
- goto err;
- }
+ /* querystring */
+ qs = &c->fcgi_params.qs;
c->t->qs = qs;
- error = gotweb_parse_querystring(qs, c->fcgi_params.querystring);
- if (error) {
- log_warnx("%s: %s", __func__, error->msg);
- goto err;
- }
/* Log the request. */
if (gotwebd_env->gotwebd_verbose > 0) {
struct gotwebd_fcgi_params *p = &c->fcgi_params;
char *server_name = NULL;
- char *querystring = NULL;
char *document_uri = NULL;
+ const char *action_name = NULL;
if (p->server_name[0] &&
stravis(&server_name, p->server_name, VIS_SAFE) == -1) {
log_warn("stravis");
server_name = NULL;
}
- if (p->querystring[0] &&
- stravis(&querystring, p->querystring, VIS_SAFE) == -1) {
- log_warn("stravis");
- querystring = NULL;
- }
+
if (p->document_uri[0] &&
stravis(&document_uri, p->document_uri, VIS_SAFE) == -1) {
log_warn("stravis");
document_uri = NULL;
}
- log_info("processing request: server='%s' query='%s' "
- "document_uri='%s'",
+ action_name = gotweb_action_name(qs->action);
+ log_info("processing request: server='%s' action='%s' "
+ "commit='%s', file='%s', folder='%s', headref='%s' "
+ "index_page=%d path='%s' document_uri='%s'",
server_name ? server_name : "",
- querystring ? querystring : "",
+ action_name ? action_name : "",
+ qs->commit,
+ qs->file,
+ qs->folder,
+ qs->headref,
+ qs->index_page,
+ qs->path,
document_uri ? document_uri : "");
free(server_name);
- free(querystring);
free(document_uri);
}
if (qs->action == BLAME || qs->action == BLOB ||
qs->action == BLOBRAW || qs->action == DIFF ||
qs->action == PATCH) {
- if (qs->commit == NULL) {
+ if (qs->commit[0] == '\0') {
error = got_error(GOT_ERR_BAD_QUERYSTRING);
goto err;
}
}
if (qs->action != INDEX) {
- if (qs->path == NULL) {
+ if (qs->path[0] == '\0') {
error = got_error(GOT_ERR_BAD_QUERYSTRING);
goto err;
}
}
if (qs->action == BLOBRAW || qs->action == BLOB) {
- if (qs->folder == NULL || qs->file == NULL) {
+ if (qs->folder[0] == '\0' || qs->file[0] == '\0') {
error = got_error(GOT_ERR_BAD_QUERYSTRING);
goto err;
}
switch (qs->action) {
case BLAME:
- if (qs->folder == NULL || qs->file == NULL) {
+ if (qs->folder[0] == '\0' || qs->file[0] == '\0') {
error = got_error(GOT_ERR_BAD_QUERYSTRING);
goto err;
}
struct gotweb_url url = {
.index_page = -1,
.action = BLOBRAW,
- .path = qs->path,
- .commit = qs->commit,
- .folder = qs->folder,
- .file = qs->file,
+ .path = qs->path[0] ? qs->path : NULL,
+ .commit = qs->commit[0] ? qs->commit : NULL,
+ .folder = qs->folder[0] ? qs->folder : NULL,
+ .file = qs->file[0] ? qs->file : NULL,
};
return gotweb_reply(c, 302, NULL, &url);
}
qs->action = SUMMARY;
commit = TAILQ_FIRST(&c->t->repo_commits);
- if (commit && qs->commit == NULL) {
- qs->commit = strdup(commit->commit_id);
- if (qs->commit == NULL) {
- error = got_error_from_errno("strdup");
- log_warn("%s: strdup", __func__);
+ if (commit && qs->commit[0] == '\0') {
+ if (strlcpy(qs->commit, commit->commit_id,
+ sizeof(qs->commit)) >= sizeof(qs->commit)) {
+ error = got_error_msg(GOT_ERR_NO_SPACE,
+ "commit ID too long");
+ log_warn("%s: %s", __func__, error->msg);
goto err;
}
}
return error;
}
-static const struct got_error *
-gotweb_init_querystring(struct querystring **qs)
-{
- const struct got_error *error = NULL;
-
- *qs = calloc(1, sizeof(**qs));
- if (*qs == NULL)
- return got_error_from_errno2(__func__, "calloc");
-
- (*qs)->headref = strdup("HEAD");
- if ((*qs)->headref == NULL) {
- free(*qs);
- *qs = NULL;
- return got_error_from_errno2(__func__, "strdup");
- }
-
- (*qs)->action = INDEX;
-
- return error;
-}
-
-static const struct got_error *
-gotweb_parse_querystring(struct querystring *qs, char *qst)
-{
- const struct got_error *error = NULL;
- char *tok1 = NULL, *tok1_pair = NULL, *tok1_end = NULL;
- char *tok2 = NULL, *tok2_pair = NULL, *tok2_end = NULL;
-
- if (qst == NULL)
- return error;
-
- tok1 = strdup(qst);
- if (tok1 == NULL)
- return got_error_from_errno2(__func__, "strdup");
-
- tok1_pair = tok1;
- tok1_end = tok1;
-
- while (tok1_pair != NULL) {
- strsep(&tok1_end, "&");
-
- tok2 = strdup(tok1_pair);
- if (tok2 == NULL) {
- free(tok1);
- return got_error_from_errno2(__func__, "strdup");
- }
-
- tok2_pair = tok2;
- tok2_end = tok2;
-
- while (tok2_pair != NULL) {
- strsep(&tok2_end, "=");
- if (tok2_end) {
- error = gotweb_assign_querystring(qs, tok2_pair,
- tok2_end);
- if (error)
- goto err;
- }
- tok2_pair = tok2_end;
- }
- free(tok2);
- tok1_pair = tok1_end;
- }
- free(tok1);
- return error;
-err:
- free(tok2);
- free(tok1);
- return error;
-}
-
-/*
- * Adapted from usr.sbin/httpd/httpd.c url_decode.
- */
-static const struct got_error *
-gotweb_urldecode(char *url)
-{
- char *p, *q;
- char hex[3];
- unsigned long x;
-
- hex[2] = '\0';
- p = q = url;
-
- while (*p != '\0') {
- switch (*p) {
- case '%':
- /* Encoding character is followed by two hex chars */
- if (!isxdigit((unsigned char)p[1]) ||
- !isxdigit((unsigned char)p[2]) ||
- (p[1] == '0' && p[2] == '0'))
- return got_error(GOT_ERR_BAD_QUERYSTRING);
-
- hex[0] = p[1];
- hex[1] = p[2];
-
- /*
- * We don't have to validate "hex" because it is
- * guaranteed to include two hex chars followed by nul.
- */
- x = strtoul(hex, NULL, 16);
- *q = (char)x;
- p += 2;
- break;
- default:
- *q = *p;
- break;
- }
- p++;
- q++;
- }
- *q = '\0';
-
- return NULL;
-}
-
-static const struct got_error *
-gotweb_assign_querystring(struct querystring *qs, char *key, char *value)
-{
- const struct got_error *error = NULL;
- const char *errstr;
- int a_cnt, el_cnt;
-
- error = gotweb_urldecode(value);
- if (error)
- return error;
-
- for (el_cnt = 0; el_cnt < nitems(querystring_keys); el_cnt++) {
- if (strcmp(key, querystring_keys[el_cnt].name) != 0)
- continue;
-
- switch (querystring_keys[el_cnt].element) {
- case ACTION:
- for (a_cnt = 0; a_cnt < nitems(action_keys); a_cnt++) {
- if (strcmp(value, action_keys[a_cnt].name) != 0)
- continue;
- qs->action = action_keys[a_cnt].action;
- break;
- }
- if (a_cnt == nitems(action_keys))
- qs->action = ERR;
- break;
- case COMMIT:
- qs->commit = strdup(value);
- if (qs->commit == NULL) {
- error = got_error_from_errno2(__func__,
- "strdup");
- goto done;
- }
- break;
- case RFILE:
- qs->file = strdup(value);
- if (qs->file == NULL) {
- error = got_error_from_errno2(__func__,
- "strdup");
- goto done;
- }
- break;
- case FOLDER:
- qs->folder = strdup(value);
- if (qs->folder == NULL) {
- error = got_error_from_errno2(__func__,
- "strdup");
- goto done;
- }
- break;
- case HEADREF:
- free(qs->headref);
- qs->headref = strdup(value);
- if (qs->headref == NULL) {
- error = got_error_from_errno2(__func__,
- "strdup");
- goto done;
- }
- break;
- case INDEX_PAGE:
- if (*value == '\0')
- break;
- qs->index_page = strtonum(value, INT64_MIN,
- INT64_MAX, &errstr);
- if (errstr) {
- error = got_error_from_errno3(__func__,
- "strtonum", errstr);
- goto done;
- }
- if (qs->index_page < 0)
- qs->index_page = 0;
- break;
- case PATH:
- qs->path = strdup(value);
- if (qs->path == NULL) {
- error = got_error_from_errno2(__func__,
- "strdup");
- goto done;
- }
- break;
- }
-
- /* entry found */
- break;
- }
-done:
- return error;
-}
-
void
gotweb_free_repo_tag(struct repo_tag *rt)
{
}
static void
-gotweb_free_querystring(struct querystring *qs)
-{
- if (qs != NULL) {
- free(qs->commit);
- free(qs->file);
- free(qs->folder);
- free(qs->headref);
- free(qs->path);
- }
- free(qs);
-}
-
-static void
gotweb_free_repo_dir(struct repo_dir *repo_dir)
{
if (repo_dir != NULL) {
gotweb_free_repo_tag(rt);
}
gotweb_free_repo_dir(t->repo_dir);
- gotweb_free_querystring(t->qs);
+ t->qs = NULL;
free(t->more_id);
free(t->tags_more_id);
if (t->blob)
struct gotweb_url *next, int *have_next)
{
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct server *srv = c->srv;
*have_prev = *have_next = 0;
struct request *c = tp->tp_arg;
struct server *srv = c->srv;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct repo_dir *repo_dir = NULL;
struct dirent **sd_dent = t->repos;
unsigned int d_i, d_disp = 0;
gotweb_action_name(int action)
{
switch (action) {
+ case NO_ACTION:
+ return "no action";
case BLAME:
return "blame";
case BLOB:
blob - 17338707c2666ca04c1d07ca753f94cd50762191
blob + 5f72ef9e31fdd912c972f55367db8538e012b9b9
--- gotwebd/gotwebd.c
+++ gotwebd/gotwebd.c
#include <fcntl.h>
#include <imsg.h>
#include <pwd.h>
+#include <sha1.h>
+#include <sha2.h>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>
#include "got_opentemp.h"
#include "got_reference.h"
+#include "got_object.h"
#include "gotwebd.h"
#include "log.h"
blob - 02bc544637cc043a756a9a812d12548947cd9442
blob + 264aea1b3238702f4213e6d79fcfb8d45ebb2f41
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
struct got_reflist_head refs;
struct got_repository *repo;
struct repo_dir *repo_dir;
- struct querystring *qs;
+ const struct querystring *qs;
char *more_id;
char *tags_more_id;
unsigned int repos_total;
uint32_t request_id;
uint8_t record[FCGI_RECORD_SIZE];
size_t record_len;
+};
+
+enum query_actions {
+ NO_ACTION = 0,
+ BLAME,
+ BLOB,
+ BLOBRAW,
+ BRIEFS,
+ COMMITS,
+ DIFF,
+ ERR,
+ INDEX,
+ PATCH,
+ SUMMARY,
+ TAG,
+ TAGS,
+ TREE,
+ RSS,
+};
+
+struct querystring {
+ enum query_actions action;
+ char commit[GOT_OBJECT_ID_HEX_MAXLEN];
+ char file[NAME_MAX];
+ char folder[PATH_MAX];
+ char headref[MAX_DOCUMENT_URI];
+ int index_page;
+ char path[PATH_MAX];
};
struct gotwebd_fcgi_params {
uint32_t request_id;
- char querystring[MAX_QUERYSTRING];
+ struct querystring qs;
char document_uri[MAX_DOCUMENT_URI];
char server_name[MAX_SERVER_NAME];
int https;
const char *path;
};
-struct querystring {
- uint8_t action;
- char *commit;
- char *file;
- char *folder;
- char *headref;
- int index_page;
- char *path;
-};
-
struct querystring_keys {
const char *name;
int element;
HEADREF,
INDEX_PAGE,
PATH,
-};
-
-enum query_actions {
- BLAME,
- BLOB,
- BLOBRAW,
- BRIEFS,
- COMMITS,
- DIFF,
- ERR,
- INDEX,
- PATCH,
- SUMMARY,
- TAG,
- TAGS,
- TREE,
- RSS,
};
extern struct gotwebd *gotwebd_env;
int cmdline_symset(char *);
/* fcgi.c */
+void fcgi_init_querystring(struct querystring *);
void fcgi_cleanup_request(struct request *);
void fcgi_create_end_record(struct request *);
int fcgi_write(void *, const void *, size_t);
blob - c7e1ac5b684f3f72cb60e8a5260089c8262b08a9
blob + 9ce2f4f4149824c1fbfbbe7bb7aea41082f89a13
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
{{ define breadcumbs(struct template *tp) }}
{!
struct request *c = tp->tp_arg;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
struct gotweb_url url;
const char *folder = qs->folder;
const char *action = "tree";
memset(&url, 0, sizeof(url));
url.index_page = -1;
url.action = TREE;
- url.path = qs->path;
- url.commit = qs->commit;
+ url.path = qs->path[0] ? qs->path : NULL;
+ url.commit = qs->commit[0] ? qs->commit : NULL;
if (qs->action != TREE && qs->action != BLOB) {
action = gotweb_action_name(qs->action);
url.action = qs->action;
}
- if (folder && *folder != '\0') {
+ if (*folder != '\0') {
while (*folder == '/')
folder++;
dir = strdup(folder);
{{ end }}
{{ end }}
- {{ if qs->file }}
+ {{ if qs->file[0] }}
{{ qs->file }}
{{ end}}
{!
struct request *c = tp->tp_arg;
struct server *srv = c->srv;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
struct gotweb_url u_path;
const char *prfx = c->fcgi_params.document_uri;
const char *css = srv->custom_css;
<a href="?index_page={{ printf "%d", qs->index_page }}">
{{ srv->site_link }}
</a>
- {{ if qs->path }}
- {! u_path.path = qs->path; !}
+ {{ if qs->path[0] }}
+ {! u_path.path = qs->path[0] ? qs->path : NULL; !}
{{ " / " }}
<a href="{{ render gotweb_render_url(tp->tp_arg, &u_path)}}">
{{ qs->path }}
{!
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
struct repo_commit *rc;
struct repo_dir *repo_dir = t->repo_dir;
struct gotweb_url diff_url, patch_url, tree_url;
{!
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct gotweb_url more = {
.action = action,
.index_page = -1,
- .path = qs->path,
+ .path = qs->path[0] ? qs->path : NULL,
.commit = t->more_id,
.headref = qs->headref,
- .folder = qs->folder,
- .file = qs->file,
+ .folder = qs->folder[0] ? qs->folder : NULL,
+ .file = qs->file[0] ? qs->file : NULL,
};
if (action == TAGS)
{!
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct got_blob_object *blob = t->blob;
struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits);
struct gotweb_url briefs_url, blame_url, raw_url;
memset(&briefs_url, 0, sizeof(briefs_url));
briefs_url.index_page = -1,
briefs_url.action = BRIEFS,
- briefs_url.path = qs->path,
- briefs_url.commit = qs->commit,
- briefs_url.folder = qs->folder,
- briefs_url.file = qs->file,
+ briefs_url.path = qs->path[0] ? qs->path : NULL,
+ briefs_url.commit = qs->commit[0] ? qs->commit : NULL,
+ briefs_url.folder = qs->folder[0] ? qs->folder : NULL,
+ briefs_url.file = qs->file[0] ? qs->file : NULL,
memcpy(&blame_url, &briefs_url, sizeof(blame_url));
blame_url.action = BLAME;
const struct got_error *error;
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
struct gotweb_url url;
char *readme = NULL;
int binary;
{{ if readme }}
{!
error = got_open_blob_for_output(&t->blob, &t->fd, &binary, c,
- qs->folder, readme, qs->commit);
+ qs->folder[0] ? qs->folder : NULL, readme,
+ qs->commit[0] ? qs->commit : NULL);
if (error) {
free(readme);
return (-1);
memset(&url, 0, sizeof(url));
url.index_page = -1;
url.action = BLOB;
- url.path = t->qs->path;
+ url.path = t->qs->path[0] ? t->qs->path : NULL;
url.file = readme;
- url.folder = t->qs->folder ? t->qs->folder : "";
- url.commit = t->qs->commit;
+ url.folder = t->qs->folder[0] ? t->qs->folder : "";
+ url.commit = t->qs->commit[0] ? t->qs->commit : NULL;
!}
{{ if !binary }}
<h2>
{!
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits);
const char *modestr = "";
const char *name;
struct gotweb_url url = {
.index_page = -1,
.commit = rc->commit_id,
- .path = qs->path,
+ .path = qs->path[0] ? qs->path : NULL,
};
name = got_tree_entry_get_name(te);
mode = got_tree_entry_get_mode(te);
- folder = qs->folder ? qs->folder : "";
+ folder = qs->folder[0] ? qs->folder : "";
if (S_ISDIR(mode)) {
if (asprintf(&dir, "%s/%s", folder, name) == -1)
return (-1);
{!
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
FILE *fp = t->fp;
struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits);
char *line = NULL;
struct gotweb_url patch_url, tree_url = {
.action = TREE,
.index_page = -1,
- .path = qs->path,
+ .path = qs->path[0] ? qs->path : NULL,
.commit = rc->commit_id,
};
{!
const struct got_error *err;
struct request *c = tp->tp_arg;
- struct querystring *qs = c->t->qs;
+ const struct querystring *qs = c->t->qs;
const char *refname;
time_t age;
struct gotweb_url url = {
.action = SUMMARY,
.index_page = -1,
- .path = qs->path,
+ .path = qs->path[0] ? qs->path : NULL,
};
refname = got_ref_get_name(re->ref);
const struct got_error *err;
struct request *c = tp->tp_arg;
struct transport *t = c->t;
- struct querystring *qs = t->qs;
+ const struct querystring *qs = t->qs;
struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits);
struct gotweb_url briefs_url, blob_url, raw_url;
memset(&briefs_url, 0, sizeof(briefs_url));
briefs_url.index_page = -1,
briefs_url.action = BRIEFS,
- briefs_url.path = qs->path,
- briefs_url.commit = qs->commit,
- briefs_url.folder = qs->folder,
- briefs_url.file = qs->file,
+ briefs_url.path = qs->path[0] ? qs->path : NULL;
+ briefs_url.commit = qs->commit[0] ? qs->commit : NULL,
+ briefs_url.folder = qs->folder[0] ? qs->folder : NULL,
+ briefs_url.file = qs->file[0] ? qs->file : NULL,
memcpy(&blob_url, &briefs_url, sizeof(blob_url));
blob_url.action = BLOB;
blob - a985c4c448a29a5e34d9a497c1736397cd5ed2af
blob + f6da39132c94a229b98735aa2e9a44a4d415076d
--- gotwebd/parse.y
+++ gotwebd/parse.y
#include <imsg.h>
#include <limits.h>
#include <netdb.h>
+#include <sha1.h>
+#include <sha2.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "got_reference.h"
+#include "got_object.h"
#include "gotwebd.h"
#include "log.h"
blob - 588e89ebf1f5bc154b7f43bcc788380f6768cbbe
blob + 8fea3fb221fe335452f3036c4b770801d118b199
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
#include <netdb.h>
#include <poll.h>
#include <pwd.h>
+#include <sha1.h>
+#include <sha2.h>
#include <siphash.h>
#include <stddef.h>
#include <stdio.h>
#include <util.h>
#include "got_reference.h"
+#include "got_object.h"
#include "gotwebd.h"
#include "log.h"
process_request(struct request *c)
{
struct gotwebd *env = gotwebd_env;
+ struct querystring *qs = &c->fcgi_params.qs;
struct imsgev *iev_gotweb;
int ret, i;
struct request ic;
+
+ /* Fill in defaults for unspecified parameters where needed. */
+ if (qs->action == NO_ACTION)
+ qs->action = INDEX;
+ if (qs->index_page == -1)
+ qs->index_page = 0;
+ if (qs->headref[0] == '\0') {
+ if (strlcpy(qs->headref, GOT_REF_HEAD, sizeof(qs->headref)) >=
+ sizeof(qs->headref)) {
+ log_warnx("head reference buffer too small");
+ return -1;
+ }
+ }
memcpy(&ic, c, sizeof(ic));
p = &c->fcgi_params;
- if (params.querystring[0] != '\0' &&
- strlcpy(p->querystring, params.querystring,
- sizeof(p->querystring)) >= sizeof(p->querystring)) {
- log_warnx("querystring too long");
+ if (params.qs.action != NO_ACTION)
+ p->qs.action = params.qs.action;
+
+ if (params.qs.commit[0] &&
+ strlcpy(p->qs.commit, params.qs.commit,
+ sizeof(p->qs.commit)) >= sizeof(p->qs.commit)) {
+ log_warnx("commit ID too long");
+ goto fail;
+ }
+
+ if (params.qs.file[0] &&
+ strlcpy(p->qs.file, params.qs.file,
+ sizeof(p->qs.file)) >= sizeof(p->qs.file)) {
+ log_warnx("file path too long");
goto fail;
}
+ if (params.qs.folder[0] &&
+ strlcpy(p->qs.folder, params.qs.folder,
+ sizeof(p->qs.folder)) >= sizeof(p->qs.folder)) {
+ log_warnx("folder path too long");
+ goto fail;
+ }
+
+ if (params.qs.headref[0] &&
+ strlcpy(p->qs.headref, params.qs.headref,
+ sizeof(p->qs.headref)) >= sizeof(p->qs.headref)) {
+ log_warnx("headref too long");
+ goto fail;
+ }
+
+ if (params.qs.index_page != -1)
+ p->qs.index_page = params.qs.index_page;
+
+ if (params.qs.path[0] &&
+ strlcpy(p->qs.path, params.qs.path,
+ sizeof(p->qs.path)) >= sizeof(p->qs.path)) {
+ log_warnx("path path too long");
+ goto fail;
+ }
+
if (params.document_uri[0] != '\0' &&
strlcpy(p->document_uri, params.document_uri,
sizeof(p->document_uri)) >= sizeof(p->document_uri)) {
return;
}
+ fcgi_init_querystring(&c->fcgi_params.qs);
c->buf = buf;
c->fd = s;
c->sock = sock;