/* 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) */ #define USE_THE_REPOSITORY_VARIABLE #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); void cgit_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 = strdup_first_line(value); else if (!strcmp(name, "clone-url")) repo->clone_url = strdup_first_line(value); else if (!strcmp(name, "desc")) repo->desc = strdup_first_line(value); else if (!strcmp(name, "owner")) repo->owner = strdup_first_line(value); else if (!strcmp(name, "homepage")) repo->homepage = strdup_first_line(value); else if (!strcmp(name, "defbranch")) repo->defbranch = strdup_first_line(value); else if (!strcmp(name, "extra-head-content")) repo->extra_head_content = strdup_first_line(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-follow-links")) repo->enable_follow_links = 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= strdup_first_line(value); else if (skip_prefix(name, "module-link.", &path)) { item = string_list_append(&repo->submodules, strdup_first_line(path)); item->util = strdup_first_line(value); } else if (!strcmp(name, "section")) repo->section = strdup_first_line(value); else if (!strcmp(name, "snapshot-prefix")) repo->snapshot_prefix = strdup_first_line(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, strdup_first_line(value)); } else if (!strcmp(name, "logo") && value != NULL) repo->logo = strdup_first_line(value); else if (!strcmp(name, "logo-link") && value != NULL) repo->logo_link = strdup_first_line(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 = strdup_first_line(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)) cgit_repo_config(ctx.repo, arg, value); else if (!strcmp(name, "readme")) string_list_append(&ctx.cfg.readme, strdup_first_line(value)); else if (!strcmp(name, "root-title")) ctx.cfg.root_title = strdup_first_line(value); else if (!strcmp(name, "root-desc")) ctx.cfg.root_desc = strdup_first_line(value); else if (!strcmp(name, "root-readme")) ctx.cfg.root_readme = strdup_first_line(value); else if (!strcmp(name, "css")) string_list_append(&ctx.cfg.css, strdup_first_line(value)); else if (!strcmp(name, "js")) string_list_append(&ctx.cfg.js, strdup_first_line(value)); else if (!strcmp(name, "favicon")) ctx.cfg.favicon = strdup_first_line(value); else if (!strcmp(name, "footer")) ctx.cfg.footer = strdup_first_line(value); else if (!strcmp(name, "head-include")) ctx.cfg.head_include = strdup_first_line(value); else if (!strcmp(name, "header")) ctx.cfg.header = strdup_first_line(value); else if (!strcmp(name, "logo")) ctx.cfg.logo = strdup_first_line(value); else if (!strcmp(name, "logo-link")) ctx.cfg.logo_link = strdup_first_line(value); else if (!strcmp(name, "module-link")) ctx.cfg.module_link = strdup_first_line(value); else if (!strcmp(name, "strict-export")) ctx.cfg.strict_export = strdup_first_line(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 = strdup_first_line(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 = strdup_first_line(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); else scan_tree(expand_macros(value)); 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 = strdup_first_line(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 = strdup_first_line(value); else if (!strcmp(name, "mimetype-file")) ctx.cfg.mimetype_file = strdup_first_line(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 = strdup_first_line(value); else if (!strcmp(name, "clone-prefix")) ctx.cfg.clone_prefix = strdup_first_line(value); else if (!strcmp(name, "clone-url")) ctx.cfg.clone_url = strdup_first_line(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 struct reference *ref, void *cb_data){ struct refmatch *info; info = (struct refmatch *)cb_data; if (!strcmp(ref->name, info->req_ref)) info->match = 1; if (!info->first_ref) info->first_ref = xstrdup(ref->name); 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; refs_for_each_branch_ref(get_main_ref_store(the_repository), 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 = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, &oid, NULL); if (!ref || !skip_prefix(ref, "refs/heads/", &refname)) return "master";Lines 1–500 of 1118. Load more
/* 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) */ #define USE_THE_REPOSITORY_VARIABLE #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); void cgit_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 = strdup_first_line(value); else if (!strcmp(name, "clone-url")) repo->clone_url = strdup_first_line(value); else if (!strcmp(name, "desc")) repo->desc = strdup_first_line(value); else if (!strcmp(name, "owner")) repo->owner = strdup_first_line(value); else if (!strcmp(name, "homepage")) repo->homepage = strdup_first_line(value); else if (!strcmp(name, "defbranch")) repo->defbranch = strdup_first_line(value); else if (!strcmp(name, "extra-head-content")) repo->extra_head_content = strdup_first_line(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-follow-links")) repo->enable_follow_links = 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= strdup_first_line(value); else if (skip_prefix(name, "module-link.", &path)) { item = string_list_append(&repo->submodules, strdup_first_line(path)); item->util = strdup_first_line(value); } else if (!strcmp(name, "section")) repo->section = strdup_first_line(value); else if (!strcmp(name, "snapshot-prefix")) repo->snapshot_prefix = strdup_first_line(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, strdup_first_line(value)); } else if (!strcmp(name, "logo") && value != NULL) repo->logo = strdup_first_line(value); else if (!strcmp(name, "logo-link") && value != NULL) repo->logo_link = strdup_first_line(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 = strdup_first_line(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)) cgit_repo_config(ctx.repo, arg, value); else if (!strcmp(name, "readme")) string_list_append(&ctx.cfg.readme, strdup_first_line(value)); else if (!strcmp(name, "root-title")) ctx.cfg.root_title = strdup_first_line(value); else if (!strcmp(name, "root-desc")) ctx.cfg.root_desc = strdup_first_line(value); else if (!strcmp(name, "root-readme")) ctx.cfg.root_readme = strdup_first_line(value); else if (!strcmp(name, "css")) string_list_append(&ctx.cfg.css, strdup_first_line(value)); else if (!strcmp(name, "js")) string_list_append(&ctx.cfg.js, strdup_first_line(value)); else if (!strcmp(name, "favicon")) ctx.cfg.favicon = strdup_first_line(value); else if (!strcmp(name, "footer")) ctx.cfg.footer = strdup_first_line(value); else if (!strcmp(name, "head-include")) ctx.cfg.head_include = strdup_first_line(value); else if (!strcmp(name, "header")) ctx.cfg.header = strdup_first_line(value); else if (!strcmp(name, "logo")) ctx.cfg.logo = strdup_first_line(value); else if (!strcmp(name, "logo-link")) ctx.cfg.logo_link = strdup_first_line(value); else if (!strcmp(name, "module-link")) ctx.cfg.module_link = strdup_first_line(value); else if (!strcmp(name, "strict-export")) ctx.cfg.strict_export = strdup_first_line(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 = strdup_first_line(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 = strdup_first_line(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); else scan_tree(expand_macros(value)); 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 = strdup_first_line(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 = strdup_first_line(value); else if (!strcmp(name, "mimetype-file")) ctx.cfg.mimetype_file = strdup_first_line(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 = strdup_first_line(value); else if (!strcmp(name, "clone-prefix")) ctx.cfg.clone_prefix = strdup_first_line(value); else if (!strcmp(name, "clone-url")) ctx.cfg.clone_url = strdup_first_line(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 struct reference *ref, void *cb_data) { struct refmatch *info; info = (struct refmatch *)cb_data; if (!strcmp(ref->name, info->req_ref)) info->match = 1; if (!info->first_ref) info->first_ref = xstrdup(ref->name); 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; refs_for_each_branch_ref(get_main_ref_store(the_repository), 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 = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, &oid, NULL); if (!ref || !skip_prefix(ref, "refs/heads/", &refname)) return "master";