static void get_info_refs(char *arg) { const char *service_name = get_parameter("service"); struct strbuf buf = STRBUF_INIT; hdr_nocache(); if (service_name) { const char *argv[] = {NULL /* service name */, "--stateless-rpc", "--advertise-refs", ".", NULL}; struct rpc_service *svc = select_service(service_name); strbuf_addf(&buf, "application/x-git-%s-advertisement", svc->name); hdr_str(content_type, buf.buf); end_headers(); packet_write(1, "# service=git-%s\n", svc->name); packet_flush(1); argv[0] = svc->name; run_service(argv); } else { select_getanyfile(); for_each_namespaced_ref(show_text_ref, &buf); send_strbuf("text/plain", &buf); } strbuf_release(&buf); }
static void get_info_packs(char *arg) { size_t objdirlen = strlen(get_object_directory()); struct strbuf buf = STRBUF_INIT; struct packed_git *p; size_t cnt = 0; select_getanyfile(); prepare_packed_git(); for (p = packed_git; p; p = p->next) { if (p->pack_local) cnt++; } strbuf_grow(&buf, cnt * 53 + 2); for (p = packed_git; p; p = p->next) { if (p->pack_local) strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6); } strbuf_addch(&buf, '\n'); hdr_nocache(); send_strbuf("text/plain; charset=utf-8", &buf); strbuf_release(&buf); }
static NORETURN void die_webcgi(const char *err, va_list params) { if (dead <= 1) { vreportf("fatal: ", err, params); http_status(500, "Internal Server Error"); hdr_nocache(); end_headers(); } exit(0); /* we successfully reported a failure ;-) */ }
static NORETURN void forbidden(const char *err, ...) { va_list params; http_status(403, "Forbidden"); hdr_nocache(); end_headers(); va_start(params, err); if (err && *err) vfprintf(stderr, err, params); va_end(params); exit(0); }
static NORETURN void not_found(const char *err, ...) { va_list params; http_status(404, "Not Found"); hdr_nocache(); end_headers(); va_start(params, err); if (err && *err) vfprintf(stderr, err, params); va_end(params); exit(0); }
static int bad_request(struct strbuf *hdr, const struct service_cmd *c) { const char *proto = getenv("SERVER_PROTOCOL"); if (proto && !strcmp(proto, "HTTP/1.1")) { http_status(hdr, 405, "Method Not Allowed"); hdr_str(hdr, "Allow", !strcmp(c->method, "GET") ? "GET, HEAD" : c->method); } else http_status(hdr, 400, "Bad Request"); hdr_nocache(hdr); end_headers(hdr); return 0; }
static NORETURN void die_webcgi(const char *err, va_list params) { static int dead; if (!dead) { char buffer[1000]; dead = 1; vsnprintf(buffer, sizeof(buffer), err, params); fprintf(stderr, "fatal: %s\n", buffer); http_status(500, "Internal Server Error"); hdr_nocache(); end_headers(); } exit(0); /* we successfully reported a failure ;-) */ }
static void check_content_type(const char *accepted_type) { const char *actual_type = getenv("CONTENT_TYPE"); if (!actual_type) actual_type = ""; if (strcmp(actual_type, accepted_type)) { http_status(415, "Unsupported Media Type"); hdr_nocache(); end_headers(); format_write(1, "Expected POST with Content-Type '%s'," " but received '%s' instead.\n", accepted_type, actual_type); exit(0); } }
static void service_rpc(char *service_name) { const char *argv[] = {NULL, "--stateless-rpc", ".", NULL}; struct rpc_service *svc = select_service(service_name); struct strbuf buf = STRBUF_INIT; strbuf_reset(&buf); strbuf_addf(&buf, "application/x-git-%s-request", svc->name); check_content_type(buf.buf); hdr_nocache(); strbuf_reset(&buf); strbuf_addf(&buf, "application/x-git-%s-result", svc->name); hdr_str(content_type, buf.buf); end_headers(); argv[0] = svc->name; run_service(argv); strbuf_release(&buf); }
int main(int argc, char **argv) { char *method = getenv("REQUEST_METHOD"); char *dir; struct service_cmd *cmd = NULL; char *cmd_arg = NULL; int i; git_setup_gettext(); git_extract_argv0_path(argv[0]); set_die_routine(die_webcgi); if (!method) die("No REQUEST_METHOD from server"); if (!strcmp(method, "HEAD")) method = "GET"; dir = getdir(); for (i = 0; i < ARRAY_SIZE(services); i++) { struct service_cmd *c = &services[i]; regex_t re; regmatch_t out[1]; if (regcomp(&re, c->pattern, REG_EXTENDED)) die("Bogus regex in service table: %s", c->pattern); if (!regexec(&re, dir, 1, out, 0)) { size_t n; if (strcmp(method, c->method)) { const char *proto = getenv("SERVER_PROTOCOL"); if (proto && !strcmp(proto, "HTTP/1.1")) { http_status(405, "Method Not Allowed"); hdr_str("Allow", !strcmp(c->method, "GET") ? "GET, HEAD" : c->method); } else http_status(400, "Bad Request"); hdr_nocache(); end_headers(); return 0; } cmd = c; n = out[0].rm_eo - out[0].rm_so; cmd_arg = xmemdupz(dir + out[0].rm_so + 1, n - 1); dir[out[0].rm_so] = 0; break; } regfree(&re); } if (!cmd) not_found("Request not supported: '%s'", dir); setup_path(); if (!enter_repo(dir, 0)) not_found("Not a git repository: '%s'", dir); if (!getenv("GIT_HTTP_EXPORT_ALL") && access("git-daemon-export-ok", F_OK) ) not_found("Repository not exported: '%s'", dir); git_config(http_config, NULL); cmd->imp(cmd_arg); return 0; }
static void get_text_file(char *name) { select_getanyfile(); hdr_nocache(); send_local_file("text/plain", name); }
static void get_text_file(struct strbuf *hdr, char *name) { select_getanyfile(hdr); hdr_nocache(hdr); send_local_file(hdr, "text/plain", name); }