Andy Greenconfig: add jsaee39b48 years agoHistory
1117 lines · 34.6 KB · C
RawDownload
/* cgit.c: cgi for the git scm * * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> * * Licensed under GNU General Public License v2 *   (see COPYING for full license text) */ #include "cgit.h"#include "cache.h"#include "cmd.h"#include "configfile.h"#include "html.h"#include "ui-shared.h"#include "ui-stats.h"#include "ui-blob.h"#include "ui-summary.h"#include "scan-tree.h" const char *cgit_version = CGIT_VERSION; __attribute__((constructor))static void constructor_environment(){	/* Do not look in /etc/ for gitconfig and gitattributes. */	setenv("GIT_CONFIG_NOSYSTEM", "1", 1);	setenv("GIT_ATTR_NOSYSTEM", "1", 1);	unsetenv("HOME");	unsetenv("XDG_CONFIG_HOME");} static void add_mimetype(const char *name, const char *value){	struct string_list_item *item; 	item = string_list_insert(&ctx.cfg.mimetypes, name);	item->util = xstrdup(value);} static void process_cached_repolist(const char *path); static void repo_config(struct cgit_repo *repo, const char *name, const char *value){	const char *path;	struct string_list_item *item; 	if (!strcmp(name, "name"))		repo->name = xstrdup(value);	else if (!strcmp(name, "clone-url"))		repo->clone_url = xstrdup(value);	else if (!strcmp(name, "desc"))		repo->desc = xstrdup(value);	else if (!strcmp(name, "owner"))		repo->owner = xstrdup(value);	else if (!strcmp(name, "homepage"))		repo->homepage = xstrdup(value);	else if (!strcmp(name, "defbranch"))		repo->defbranch = xstrdup(value);	else if (!strcmp(name, "extra-head-content"))		repo->extra_head_content = xstrdup(value);	else if (!strcmp(name, "snapshots"))		repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value);	else if (!strcmp(name, "enable-blame"))		repo->enable_blame = atoi(value);	else if (!strcmp(name, "enable-commit-graph"))		repo->enable_commit_graph = atoi(value);	else if (!strcmp(name, "enable-log-filecount"))		repo->enable_log_filecount = atoi(value);	else if (!strcmp(name, "enable-log-linecount"))		repo->enable_log_linecount = atoi(value);	else if (!strcmp(name, "enable-remote-branches"))		repo->enable_remote_branches = atoi(value);	else if (!strcmp(name, "enable-subject-links"))		repo->enable_subject_links = atoi(value);	else if (!strcmp(name, "enable-html-serving"))		repo->enable_html_serving = atoi(value);	else if (!strcmp(name, "branch-sort")) {		if (!strcmp(value, "age"))			repo->branch_sort = 1;		if (!strcmp(value, "name"))			repo->branch_sort = 0;	} else if (!strcmp(name, "commit-sort")) {		if (!strcmp(value, "date"))			repo->commit_sort = 1;		if (!strcmp(value, "topo"))			repo->commit_sort = 2;	} else if (!strcmp(name, "max-stats"))		repo->max_stats = cgit_find_stats_period(value, NULL);	else if (!strcmp(name, "module-link"))		repo->module_link= xstrdup(value);	else if (skip_prefix(name, "module-link.", &path)) {		item = string_list_append(&repo->submodules, xstrdup(path));		item->util = xstrdup(value);	} else if (!strcmp(name, "section"))		repo->section = xstrdup(value);	else if (!strcmp(name, "snapshot-prefix"))		repo->snapshot_prefix = xstrdup(value);	else if (!strcmp(name, "readme") && value != NULL) {		if (repo->readme.items == ctx.cfg.readme.items)			memset(&repo->readme, 0, sizeof(repo->readme));		string_list_append(&repo->readme, xstrdup(value));	} else if (!strcmp(name, "logo") && value != NULL)		repo->logo = xstrdup(value);	else if (!strcmp(name, "logo-link") && value != NULL)		repo->logo_link = xstrdup(value);	else if (!strcmp(name, "hide"))		repo->hide = atoi(value);	else if (!strcmp(name, "ignore"))		repo->ignore = atoi(value);	else if (ctx.cfg.enable_filter_overrides) {		if (!strcmp(name, "about-filter"))			repo->about_filter = cgit_new_filter(value, ABOUT);		else if (!strcmp(name, "commit-filter"))			repo->commit_filter = cgit_new_filter(value, COMMIT);		else if (!strcmp(name, "source-filter"))			repo->source_filter = cgit_new_filter(value, SOURCE);		else if (!strcmp(name, "email-filter"))			repo->email_filter = cgit_new_filter(value, EMAIL);		else if (!strcmp(name, "owner-filter"))			repo->owner_filter = cgit_new_filter(value, OWNER);	}} static void config_cb(const char *name, const char *value){	const char *arg; 	if (!strcmp(name, "section"))		ctx.cfg.section = xstrdup(value);	else if (!strcmp(name, "repo.url"))		ctx.repo = cgit_add_repo(value);	else if (ctx.repo && !strcmp(name, "repo.path"))		ctx.repo->path = trim_end(value, '/');	else if (ctx.repo && skip_prefix(name, "repo.", &arg))		repo_config(ctx.repo, arg, value);	else if (!strcmp(name, "readme"))		string_list_append(&ctx.cfg.readme, xstrdup(value));	else if (!strcmp(name, "root-title"))		ctx.cfg.root_title = xstrdup(value);	else if (!strcmp(name, "root-desc"))		ctx.cfg.root_desc = xstrdup(value);	else if (!strcmp(name, "root-readme"))		ctx.cfg.root_readme = xstrdup(value);	else if (!strcmp(name, "css"))		string_list_append(&ctx.cfg.css, xstrdup(value));	else if (!strcmp(name, "js"))		string_list_append(&ctx.cfg.js, xstrdup(value));	else if (!strcmp(name, "favicon"))		ctx.cfg.favicon = xstrdup(value);	else if (!strcmp(name, "footer"))		ctx.cfg.footer = xstrdup(value);	else if (!strcmp(name, "head-include"))		ctx.cfg.head_include = xstrdup(value);	else if (!strcmp(name, "header"))		ctx.cfg.header = xstrdup(value);	else if (!strcmp(name, "logo"))		ctx.cfg.logo = xstrdup(value);	else if (!strcmp(name, "logo-link"))		ctx.cfg.logo_link = xstrdup(value);	else if (!strcmp(name, "module-link"))		ctx.cfg.module_link = xstrdup(value);	else if (!strcmp(name, "strict-export"))		ctx.cfg.strict_export = xstrdup(value);	else if (!strcmp(name, "virtual-root"))		ctx.cfg.virtual_root = ensure_end(value, '/');	else if (!strcmp(name, "noplainemail"))		ctx.cfg.noplainemail = atoi(value);	else if (!strcmp(name, "noheader"))		ctx.cfg.noheader = atoi(value);	else if (!strcmp(name, "snapshots"))		ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);	else if (!strcmp(name, "enable-filter-overrides"))		ctx.cfg.enable_filter_overrides = atoi(value);	else if (!strcmp(name, "enable-follow-links"))		ctx.cfg.enable_follow_links = atoi(value);	else if (!strcmp(name, "enable-http-clone"))		ctx.cfg.enable_http_clone = atoi(value);	else if (!strcmp(name, "enable-index-links"))		ctx.cfg.enable_index_links = atoi(value);	else if (!strcmp(name, "enable-index-owner"))		ctx.cfg.enable_index_owner = atoi(value);	else if (!strcmp(name, "enable-blame"))		ctx.cfg.enable_blame = atoi(value);	else if (!strcmp(name, "enable-commit-graph"))		ctx.cfg.enable_commit_graph = atoi(value);	else if (!strcmp(name, "enable-log-filecount"))		ctx.cfg.enable_log_filecount = atoi(value);	else if (!strcmp(name, "enable-log-linecount"))		ctx.cfg.enable_log_linecount = atoi(value);	else if (!strcmp(name, "enable-remote-branches"))		ctx.cfg.enable_remote_branches = atoi(value);	else if (!strcmp(name, "enable-subject-links"))		ctx.cfg.enable_subject_links = atoi(value);	else if (!strcmp(name, "enable-html-serving"))		ctx.cfg.enable_html_serving = atoi(value);	else if (!strcmp(name, "enable-tree-linenumbers"))		ctx.cfg.enable_tree_linenumbers = atoi(value);	else if (!strcmp(name, "enable-git-config"))		ctx.cfg.enable_git_config = atoi(value);	else if (!strcmp(name, "max-stats"))		ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);	else if (!strcmp(name, "cache-size"))		ctx.cfg.cache_size = atoi(value);	else if (!strcmp(name, "cache-root"))		ctx.cfg.cache_root = xstrdup(expand_macros(value));	else if (!strcmp(name, "cache-root-ttl"))		ctx.cfg.cache_root_ttl = atoi(value);	else if (!strcmp(name, "cache-repo-ttl"))		ctx.cfg.cache_repo_ttl = atoi(value);	else if (!strcmp(name, "cache-scanrc-ttl"))		ctx.cfg.cache_scanrc_ttl = atoi(value);	else if (!strcmp(name, "cache-static-ttl"))		ctx.cfg.cache_static_ttl = atoi(value);	else if (!strcmp(name, "cache-dynamic-ttl"))		ctx.cfg.cache_dynamic_ttl = atoi(value);	else if (!strcmp(name, "cache-about-ttl"))		ctx.cfg.cache_about_ttl = atoi(value);	else if (!strcmp(name, "cache-snapshot-ttl"))		ctx.cfg.cache_snapshot_ttl = atoi(value);	else if (!strcmp(name, "case-sensitive-sort"))		ctx.cfg.case_sensitive_sort = atoi(value);	else if (!strcmp(name, "about-filter"))		ctx.cfg.about_filter = cgit_new_filter(value, ABOUT);	else if (!strcmp(name, "commit-filter"))		ctx.cfg.commit_filter = cgit_new_filter(value, COMMIT);	else if (!strcmp(name, "email-filter"))		ctx.cfg.email_filter = cgit_new_filter(value, EMAIL);	else if (!strcmp(name, "owner-filter"))		ctx.cfg.owner_filter = cgit_new_filter(value, OWNER);	else if (!strcmp(name, "auth-filter"))		ctx.cfg.auth_filter = cgit_new_filter(value, AUTH);	else if (!strcmp(name, "embedded"))		ctx.cfg.embedded = atoi(value);	else if (!strcmp(name, "max-atom-items"))		ctx.cfg.max_atom_items = atoi(value);	else if (!strcmp(name, "max-message-length"))		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);		if (ctx.cfg.max_repo_count <= 0)			ctx.cfg.max_repo_count = INT_MAX;	} else if (!strcmp(name, "max-commit-count"))		ctx.cfg.max_commit_count = atoi(value);	else if (!strcmp(name, "project-list"))		ctx.cfg.project_list = xstrdup(expand_macros(value));	else if (!strcmp(name, "scan-path"))		if (ctx.cfg.cache_size)			process_cached_repolist(expand_macros(value));		else if (ctx.cfg.project_list)			scan_projects(expand_macros(value),				      ctx.cfg.project_list, repo_config);		else			scan_tree(expand_macros(value), repo_config);	else if (!strcmp(name, "scan-hidden-path"))		ctx.cfg.scan_hidden_path = atoi(value);	else if (!strcmp(name, "section-from-path"))		ctx.cfg.section_from_path = atoi(value);	else if (!strcmp(name, "repository-sort"))		ctx.cfg.repository_sort = xstrdup(value);	else if (!strcmp(name, "section-sort"))		ctx.cfg.section_sort = atoi(value);	else if (!strcmp(name, "source-filter"))		ctx.cfg.source_filter = cgit_new_filter(value, SOURCE);	else if (!strcmp(name, "summary-log"))		ctx.cfg.summary_log = atoi(value);	else if (!strcmp(name, "summary-branches"))		ctx.cfg.summary_branches = atoi(value);	else if (!strcmp(name, "summary-tags"))		ctx.cfg.summary_tags = atoi(value);	else if (!strcmp(name, "side-by-side-diffs"))		ctx.cfg.difftype = atoi(value) ? DIFF_SSDIFF : DIFF_UNIFIED;	else if (!strcmp(name, "agefile"))		ctx.cfg.agefile = xstrdup(value);	else if (!strcmp(name, "mimetype-file"))		ctx.cfg.mimetype_file = xstrdup(value);	else if (!strcmp(name, "renamelimit"))		ctx.cfg.renamelimit = atoi(value);	else if (!strcmp(name, "remove-suffix"))		ctx.cfg.remove_suffix = atoi(value);	else if (!strcmp(name, "robots"))		ctx.cfg.robots = xstrdup(value);	else if (!strcmp(name, "clone-prefix"))		ctx.cfg.clone_prefix = xstrdup(value);	else if (!strcmp(name, "clone-url"))		ctx.cfg.clone_url = xstrdup(value);	else if (!strcmp(name, "local-time"))		ctx.cfg.local_time = atoi(value);	else if (!strcmp(name, "commit-sort")) {		if (!strcmp(value, "date"))			ctx.cfg.commit_sort = 1;		if (!strcmp(value, "topo"))			ctx.cfg.commit_sort = 2;	} else if (!strcmp(name, "branch-sort")) {		if (!strcmp(value, "age"))			ctx.cfg.branch_sort = 1;		if (!strcmp(value, "name"))			ctx.cfg.branch_sort = 0;	} else if (skip_prefix(name, "mimetype.", &arg))		add_mimetype(arg, value);	else if (!strcmp(name, "include"))		parse_configfile(expand_macros(value), config_cb);} static void querystring_cb(const char *name, const char *value){	if (!value)		value = ""; 	if (!strcmp(name,"r")) {		ctx.qry.repo = xstrdup(value);		ctx.repo = cgit_get_repoinfo(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")) {		ctx.qry.grep = xstrdup(value);	} else if (!strcmp(name, "q")) {		ctx.qry.search = xstrdup(value);	} else if (!strcmp(name, "h")) {		ctx.qry.head = xstrdup(value);		ctx.qry.has_symref = 1;	} else if (!strcmp(name, "id")) {		ctx.qry.oid = xstrdup(value);		ctx.qry.has_oid = 1;	} else if (!strcmp(name, "id2")) {		ctx.qry.oid2 = xstrdup(value);		ctx.qry.has_oid = 1;	} else if (!strcmp(name, "ofs")) {		ctx.qry.ofs = atoi(value);	} else if (!strcmp(name, "path")) {		ctx.qry.path = trim_end(value, '/');	} else if (!strcmp(name, "name")) {		ctx.qry.name = xstrdup(value);	} else if (!strcmp(name, "s")) {		ctx.qry.sort = xstrdup(value);	} else if (!strcmp(name, "showmsg")) {		ctx.qry.showmsg = atoi(value);	} else if (!strcmp(name, "period")) {		ctx.qry.period = xstrdup(value);	} else if (!strcmp(name, "dt")) {		ctx.qry.difftype = atoi(value);		ctx.qry.has_difftype = 1;	} else if (!strcmp(name, "ss")) {		/* No longer generated, but there may be links out there. */		ctx.qry.difftype = atoi(value) ? DIFF_SSDIFF : DIFF_UNIFIED;		ctx.qry.has_difftype = 1;	} else if (!strcmp(name, "all")) {		ctx.qry.show_all = atoi(value);	} else if (!strcmp(name, "context")) {		ctx.qry.context = atoi(value);	} else if (!strcmp(name, "ignorews")) {		ctx.qry.ignorews = atoi(value);	} else if (!strcmp(name, "follow")) {		ctx.qry.follow = atoi(value);	}} static void prepare_context(void){	memset(&ctx, 0, sizeof(ctx));	ctx.cfg.agefile = "info/web/last-modified";	ctx.cfg.cache_size = 0;	ctx.cfg.cache_max_create_time = 5;	ctx.cfg.cache_root = CGIT_CACHE_ROOT;	ctx.cfg.cache_about_ttl = 15;	ctx.cfg.cache_snapshot_ttl = 5;	ctx.cfg.cache_repo_ttl = 5;	ctx.cfg.cache_root_ttl = 5;	ctx.cfg.cache_scanrc_ttl = 15;	ctx.cfg.cache_dynamic_ttl = 5;	ctx.cfg.cache_static_ttl = -1;	ctx.cfg.case_sensitive_sort = 1;	ctx.cfg.branch_sort = 0;	ctx.cfg.commit_sort = 0;	ctx.cfg.logo = "/cgit.png";	ctx.cfg.favicon = "/favicon.ico";	ctx.cfg.local_time = 0;	ctx.cfg.enable_http_clone = 1;	ctx.cfg.enable_index_owner = 1;	ctx.cfg.enable_tree_linenumbers = 1;	ctx.cfg.enable_git_config = 0;	ctx.cfg.max_repo_count = 50;	ctx.cfg.max_commit_count = 50;	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.project_list = NULL;	ctx.cfg.renamelimit = -1;	ctx.cfg.remove_suffix = 0;	ctx.cfg.robots = "index, nofollow";	ctx.cfg.root_title = "Git repository browser";	ctx.cfg.root_desc = "a fast webinterface for the git dscm";	ctx.cfg.scan_hidden_path = 0;	ctx.cfg.script_name = CGIT_SCRIPT_NAME;	ctx.cfg.section = "";	ctx.cfg.repository_sort = "name";	ctx.cfg.section_sort = 1;	ctx.cfg.summary_branches = 10;	ctx.cfg.summary_log = 10;	ctx.cfg.summary_tags = 10;	ctx.cfg.max_atom_items = 10;	ctx.cfg.difftype = DIFF_UNIFIED;	ctx.env.cgit_config = getenv("CGIT_CONFIG");	ctx.env.http_host = getenv("HTTP_HOST");	ctx.env.https = getenv("HTTPS");	ctx.env.no_http = getenv("NO_HTTP");	ctx.env.path_info = getenv("PATH_INFO");	ctx.env.query_string = getenv("QUERY_STRING");	ctx.env.request_method = getenv("REQUEST_METHOD");	ctx.env.script_name = getenv("SCRIPT_NAME");	ctx.env.server_name = getenv("SERVER_NAME");	ctx.env.server_port = getenv("SERVER_PORT");	ctx.env.http_cookie = getenv("HTTP_COOKIE");	ctx.env.http_referer = getenv("HTTP_REFERER");	ctx.env.content_length = getenv("CONTENT_LENGTH") ? strtoul(getenv("CONTENT_LENGTH"), NULL, 10) : 0;	ctx.env.authenticated = 0;	ctx.page.mimetype = "text/html";	ctx.page.charset = PAGE_ENCODING;	ctx.page.filename = NULL;	ctx.page.size = 0;	ctx.page.modified = time(NULL);	ctx.page.expires = ctx.page.modified;	ctx.page.etag = NULL;	string_list_init_dup(&ctx.cfg.mimetypes);	if (ctx.env.script_name)		ctx.cfg.script_name = xstrdup(ctx.env.script_name);	if (ctx.env.query_string)		ctx.qry.raw = xstrdup(ctx.env.query_string);	if (!ctx.env.cgit_config)		ctx.env.cgit_config = CGIT_CONFIG;} struct refmatch {	char *req_ref;	char *first_ref;	int match;}; static int find_current_ref(const char *refname, const struct object_id *oid,			    int flags, void *cb_data){	struct refmatch *info; 	info = (struct refmatch *)cb_data;	if (!strcmp(refname, info->req_ref))		info->match = 1;	if (!info->first_ref)		info->first_ref = xstrdup(refname);	return info->match;} static void free_refmatch_inner(struct refmatch *info){	if (info->first_ref)		free(info->first_ref);} static char *find_default_branch(struct cgit_repo *repo){	struct refmatch info;	char *ref; 	info.req_ref = repo->defbranch;	info.first_ref = NULL;	info.match = 0;	for_each_branch_ref(find_current_ref, &info);	if (info.match)		ref = info.req_ref;	else		ref = info.first_ref;	if (ref)		ref = xstrdup(ref);	free_refmatch_inner(&info); 	return ref;} static char *guess_defbranch(void){	const char *ref, *refname;	struct object_id oid; 	ref = resolve_ref_unsafe("HEAD", 0, &oid, NULL);	if (!ref || !skip_prefix(ref, "refs/heads/", &refname))		return "master";	return xstrdup(refname);} /* The caller must free filename and ref after calling this. */static inline void parse_readme(const char *readme, char **filename, char **ref, struct cgit_repo *repo)

Lines 1–500 of 1117.