cGit-UI for Git Repositories

cGit-UI – is a web interface for Git Repositories. cGit CGI script is writen in C and therefore it's fast enough

3 Commits   0 Branches   1 Tag
05d292b2 (kx 2023-03-24 03:51:10 +0300    1) 
05d292b2 (kx 2023-03-24 03:51:10 +0300    2) #ifdef HAVE_CONFIG_H
05d292b2 (kx 2023-03-24 03:51:10 +0300    3) #include <config.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300    4) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300    5) 
05d292b2 (kx 2023-03-24 03:51:10 +0300    6) #include <stdlib.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300    7) #include <stdio.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300    8) #include <sys/sysinfo.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300    9) #include <sys/types.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   10) #ifdef HAVE_INTTYPES_H
05d292b2 (kx 2023-03-24 03:51:10 +0300   11) #include <inttypes.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   12) #else
05d292b2 (kx 2023-03-24 03:51:10 +0300   13) #include <stdint.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   14) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300   15) #include <stddef.h>   /* offsetof(3)   */
05d292b2 (kx 2023-03-24 03:51:10 +0300   16) #include <dirent.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   17) #include <sys/stat.h> /* chmod(2)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300   18) #include <sys/file.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   19) #include <sys/mman.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   20) #include <fcntl.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   21) #include <limits.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   22) #include <string.h>   /* strdup(3)     */
05d292b2 (kx 2023-03-24 03:51:10 +0300   23) #include <strings.h>  /* strcasecmp(3) */
05d292b2 (kx 2023-03-24 03:51:10 +0300   24) #include <libgen.h>   /* basename(3)   */
05d292b2 (kx 2023-03-24 03:51:10 +0300   25) #include <ctype.h>    /* tolower(3)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300   26) #include <errno.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   27) #include <time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   28) #include <sys/time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   29) #include <pwd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   30) #include <grp.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   31) #include <stdarg.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   32) #include <locale.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   33) #include <unistd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   34) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   35) #include <git2.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   36) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   37) #include <nls.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   38) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   39) #include <defs.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   40) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   41) #include <fatal.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   42) #include <http.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   43) #include <html.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   44) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   45) #include <dlist.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   46) #include <strbuf.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   47) #include <repolist.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   48) #include <wrapper.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   49) #include <system.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   50) #include <date.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   51) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   52) #include <ctx.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   53) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   54) #include <git-shared.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   55) #include <ui-shared.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   56) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   57) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   58) /* Allocate memory in .bss segment: */
05d292b2 (kx 2023-03-24 03:51:10 +0300   59) static struct __context mctx;
05d292b2 (kx 2023-03-24 03:51:10 +0300   60) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   61) /* Share address of __context: */
05d292b2 (kx 2023-03-24 03:51:10 +0300   62) struct __context *pmctx = &mctx;
05d292b2 (kx 2023-03-24 03:51:10 +0300   63) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   64) void __mctx_init( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300   65) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   66)   pmctx->_cur_brk = (void *)&((pmctx->_mem)[0]);
05d292b2 (kx 2023-03-24 03:51:10 +0300   67) }
05d292b2 (kx 2023-03-24 03:51:10 +0300   68) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   69) static int
05d292b2 (kx 2023-03-24 03:51:10 +0300   70) __brk( void *end_d )
05d292b2 (kx 2023-03-24 03:51:10 +0300   71) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   72)   void *ptr = __mem;
05d292b2 (kx 2023-03-24 03:51:10 +0300   73) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   74)   if( (unsigned char *)end_d < (unsigned char *)ptr ||
05d292b2 (kx 2023-03-24 03:51:10 +0300   75)       (unsigned char *)end_d > (unsigned char *)ptr + CONTEXT_MEM_SIZE )
05d292b2 (kx 2023-03-24 03:51:10 +0300   76)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300   77)     errno = ENOMEM;
05d292b2 (kx 2023-03-24 03:51:10 +0300   78)     return( -1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300   79)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300   80) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   81)  /*
05d292b2 (kx 2023-03-24 03:51:10 +0300   82)    __cur_brk = (unsigned char *)end_d;
05d292b2 (kx 2023-03-24 03:51:10 +0300   83) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   84)    Функция  __brk()  лишь проверяет границы
05d292b2 (kx 2023-03-24 03:51:10 +0300   85)    области памяти, значение __cur_brk выставляется
05d292b2 (kx 2023-03-24 03:51:10 +0300   86)    в __sbrk() .
05d292b2 (kx 2023-03-24 03:51:10 +0300   87)   *************************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300   88) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   89)   return( 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300   90) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   91) } /* End of __brk() */
05d292b2 (kx 2023-03-24 03:51:10 +0300   92) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   93) void *
05d292b2 (kx 2023-03-24 03:51:10 +0300   94) __sbrk( int incr )
05d292b2 (kx 2023-03-24 03:51:10 +0300   95) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   96)   void         *ptr = __cur_brk;
05d292b2 (kx 2023-03-24 03:51:10 +0300   97)   register int  rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300   98) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   99)   if( incr == 0 ) return( ptr );
05d292b2 (kx 2023-03-24 03:51:10 +0300  100) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  101)   rc = __brk( ptr + incr );
05d292b2 (kx 2023-03-24 03:51:10 +0300  102)   if( rc == -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  103)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  104)     /* errno is set into __brk() */
05d292b2 (kx 2023-03-24 03:51:10 +0300  105)     return( (void *)0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  106)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  107) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  108)   __cur_brk = ((unsigned char *)ptr) + (int)incr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  109) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  110)   return( ptr );
05d292b2 (kx 2023-03-24 03:51:10 +0300  111) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  112) } /* End of __sbrk() */
05d292b2 (kx 2023-03-24 03:51:10 +0300  113) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  114) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  115) struct cgit_context ctx;
05d292b2 (kx 2023-03-24 03:51:10 +0300  116) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  117) const char *ptype_repolist   = "repolist";
05d292b2 (kx 2023-03-24 03:51:10 +0300  118) const char *ptype_repo       = "repo";
05d292b2 (kx 2023-03-24 03:51:10 +0300  119) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  120) void cgit_prepare_context( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  121) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  122)   memset( &ctx, 0, sizeof(ctx) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  123) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  124)   ctx.env.http_host = getenv("HTTP_HOST");
05d292b2 (kx 2023-03-24 03:51:10 +0300  125)   ctx.env.https = getenv("HTTPS");
05d292b2 (kx 2023-03-24 03:51:10 +0300  126)   ctx.env.no_http = getenv("NO_HTTP");
05d292b2 (kx 2023-03-24 03:51:10 +0300  127)   ctx.env.path_info = getenv("PATH_INFO");
05d292b2 (kx 2023-03-24 03:51:10 +0300  128)   ctx.env.query_string = getenv("QUERY_STRING");
05d292b2 (kx 2023-03-24 03:51:10 +0300  129)   ctx.env.request_uri = getenv("REQUEST_URI");
05d292b2 (kx 2023-03-24 03:51:10 +0300  130) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  131)   if( ctx.env.request_uri == NULL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  132)     ctx.env.request_uri = "/";
05d292b2 (kx 2023-03-24 03:51:10 +0300  133) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  134)   ctx.env.request_scheme = getenv("REQUEST_SCHEME");
05d292b2 (kx 2023-03-24 03:51:10 +0300  135)   ctx.env.request_method = getenv("REQUEST_METHOD");
05d292b2 (kx 2023-03-24 03:51:10 +0300  136)   ctx.env.script_name = getenv("SCRIPT_NAME");
05d292b2 (kx 2023-03-24 03:51:10 +0300  137)   ctx.env.server_name = getenv("SERVER_NAME");
05d292b2 (kx 2023-03-24 03:51:10 +0300  138)   ctx.env.server_port = getenv("SERVER_PORT");
05d292b2 (kx 2023-03-24 03:51:10 +0300  139)   ctx.env.http_cookie = getenv("HTTP_COOKIE");
05d292b2 (kx 2023-03-24 03:51:10 +0300  140)   ctx.env.content_lenght = getenv("CONTENT_LENGTH") ? strtoul(getenv("CONTENT_LENGTH"), NULL, 10) : 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  141)   ctx.env.http_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  142)   ctx.env.authenticated = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  143) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  144)   ctx.query.ofs = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  145)   ctx.query.rev = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300  146)   ctx.query.revision = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  147)   ctx.query.operation = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  148)   ctx.query.search = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  149) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  150)   ctx.page.mimetype = "text/html";
05d292b2 (kx 2023-03-24 03:51:10 +0300  151)   ctx.page.charset = "UTF-8";
05d292b2 (kx 2023-03-24 03:51:10 +0300  152)   ctx.page.size = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  153)   ctx.page.modified = time(NULL);
05d292b2 (kx 2023-03-24 03:51:10 +0300  154)   ctx.page.expires = ctx.page.modified + 5 * 60;
05d292b2 (kx 2023-03-24 03:51:10 +0300  155)   ctx.page.status = 200;
05d292b2 (kx 2023-03-24 03:51:10 +0300  156)   ctx.page.status_message = "OK";
05d292b2 (kx 2023-03-24 03:51:10 +0300  157)   ctx.page.header = "/.cgit/html/header.html";
05d292b2 (kx 2023-03-24 03:51:10 +0300  158)   ctx.page.footer = "/.cgit/html/footer.html";
05d292b2 (kx 2023-03-24 03:51:10 +0300  159) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  160)   ctx.vars.css = "/.cgit/css/cgit.css";
05d292b2 (kx 2023-03-24 03:51:10 +0300  161)   ctx.vars.owner = "Andrey V.Kosteltsev";
05d292b2 (kx 2023-03-24 03:51:10 +0300  162)   ctx.vars.author = "Andrey V.Kosteltsev";
05d292b2 (kx 2023-03-24 03:51:10 +0300  163)   ctx.vars.description = "Git repositories hosted at Solar System, Earth";
05d292b2 (kx 2023-03-24 03:51:10 +0300  164)   ctx.vars.keywords = "cGit repositories";
05d292b2 (kx 2023-03-24 03:51:10 +0300  165)   ctx.vars.title = "Git Repositories";
05d292b2 (kx 2023-03-24 03:51:10 +0300  166)   ctx.vars.favicon_path = "/.cgit/pixmaps/favicon";
05d292b2 (kx 2023-03-24 03:51:10 +0300  167)   ctx.vars.syntax_highlight_css = "_cgit.css";
05d292b2 (kx 2023-03-24 03:51:10 +0300  168)   ctx.vars.logo = "/.cgit/pixmaps/cgit-banner-280x280.png";
05d292b2 (kx 2023-03-24 03:51:10 +0300  169)   ctx.vars.logo_alt = "Example.org";
05d292b2 (kx 2023-03-24 03:51:10 +0300  170)   ctx.vars.logo_link = "https://example.org";
05d292b2 (kx 2023-03-24 03:51:10 +0300  171)   ctx.vars.home_page = "https://example.org";
05d292b2 (kx 2023-03-24 03:51:10 +0300  172)   ctx.vars.snapshots = "tar.xz";
05d292b2 (kx 2023-03-24 03:51:10 +0300  173)   ctx.vars.status_line = "Git Repositories";
05d292b2 (kx 2023-03-24 03:51:10 +0300  174)   ctx.vars.main_menu_logo = "/.cgit/pixmaps/logo/git-logo-white-256x256.svg";
05d292b2 (kx 2023-03-24 03:51:10 +0300  175)   ctx.vars.main_menu_item = "<a href='/'>Index</a>";
05d292b2 (kx 2023-03-24 03:51:10 +0300  176)   ctx.vars.left_menu_items = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300  177)   ctx.vars.popup_menu_items = "<div class='item'><span class='icon las la-home'></span><a href='https://example.org/' target='_blank'>Home page</a></div>";
05d292b2 (kx 2023-03-24 03:51:10 +0300  178)   ctx.vars.right_menu_items = "<div class='item'><a href='https://example.org/' target='_blank'>Home page</a></div>";
05d292b2 (kx 2023-03-24 03:51:10 +0300  179)   ctx.vars.copyright_notice = "By using any website materials you agree to indicate source.";
05d292b2 (kx 2023-03-24 03:51:10 +0300  180)   ctx.vars.copyright = "&#169; 2022 Andrey V.Kosteltsev. All Rights Reserved.";
05d292b2 (kx 2023-03-24 03:51:10 +0300  181)   ctx.vars.page_type = ptype_repolist;
05d292b2 (kx 2023-03-24 03:51:10 +0300  182)   ctx.vars.page_size = "200";
05d292b2 (kx 2023-03-24 03:51:10 +0300  183)   ctx.vars.num_of_repos = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300  184) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  185)   ctx.repo.name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  186)   ctx.repo.info = CGIT_INFO_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  187)   ctx.repo.git_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  188)   ctx.repo.repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  189)   ctx.repo.relative_path = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  190)   ctx.repo.relative_info = CGIT_INFO_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  191)   ctx.repo.relative_html = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  192)   ctx.repo.relative_href = "/";
05d292b2 (kx 2023-03-24 03:51:10 +0300  193)   ctx.repo.search_placeholder = "repository...";
05d292b2 (kx 2023-03-24 03:51:10 +0300  194)   ctx.repo.trunk = "master";
05d292b2 (kx 2023-03-24 03:51:10 +0300  195)   ctx.repo.clone_prefix = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  196)   ctx.repo.clone_ro_prefix = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  197)   ctx.repo.nbranches = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  198)   ctx.repo.ncommits = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  199)   ctx.repo.ntags = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  200) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  201)   ctx.promo.analytic_links   = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  202)   ctx.promo.analytic_scripts = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  203)   ctx.promo.donate           = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  204)   ctx.promo.donate_css       = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  205)   ctx.promo.donate_html      = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  206)   ctx.promo.donate_js        = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  207)   ctx.promo.donate_header    = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  208)   ctx.promo.donate_purpose   = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  209) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  210)   ctx.vers.git   = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  211)   ctx.vers.nginx = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  212)   ctx.vers.cgit  = PROGRAM_VERSION;
05d292b2 (kx 2023-03-24 03:51:10 +0300  213) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  214) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  215) void cgit_prepare_template_variables( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  216) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  217)   envtab_install( &strbuf_envtab, "css", ctx.vars.css, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  218)   envtab_install( &strbuf_envtab, "owner", ctx.vars.owner, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  219)   envtab_install( &strbuf_envtab, "author", ctx.vars.author, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  220)   envtab_install( &strbuf_envtab, "description", ctx.vars.description, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  221)   envtab_install( &strbuf_envtab, "keywords", ctx.vars.keywords, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  222)   envtab_install( &strbuf_envtab, "title", ctx.vars.title, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  223)   envtab_install( &strbuf_envtab, "favicon-path", ctx.vars.favicon_path, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  224)   envtab_install( &strbuf_envtab, "syntax-highlight-css", ctx.vars.syntax_highlight_css, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  225)   envtab_install( &strbuf_envtab, "logo", ctx.vars.logo, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  226)   envtab_install( &strbuf_envtab, "logo-alt", ctx.vars.logo_alt, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  227)   envtab_install( &strbuf_envtab, "logo-link", ctx.vars.logo_link, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  228)   envtab_install( &strbuf_envtab, "home-page", ctx.vars.home_page, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  229)   envtab_install( &strbuf_envtab, "snapshots", ctx.vars.snapshots, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  230)   envtab_install( &strbuf_envtab, "status-line", ctx.vars.status_line, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  231)   envtab_install( &strbuf_envtab, "main-menu-logo", ctx.vars.main_menu_logo, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  232)   envtab_install( &strbuf_envtab, "main-menu-item", ctx.vars.main_menu_item, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  233)   envtab_install( &strbuf_envtab, "left-menu-items", ctx.vars.left_menu_items, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  234)   envtab_install( &strbuf_envtab, "popup-menu-items", ctx.vars.popup_menu_items, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  235)   envtab_install( &strbuf_envtab, "right-menu-items", ctx.vars.right_menu_items, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  236) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  237)   envtab_install( &strbuf_envtab, "relative-html", ctx.repo.relative_html, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  238)   envtab_install( &strbuf_envtab, "search-placeholder", ctx.repo.search_placeholder, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  239) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  240)   envtab_install( &strbuf_envtab, "analytic-links", ctx.promo.analytic_links, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  241)   envtab_install( &strbuf_envtab, "analytic-scripts", ctx.promo.analytic_scripts, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  242)   envtab_install( &strbuf_envtab, "donate-css", ctx.promo.donate_css, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  243)   envtab_install( &strbuf_envtab, "donate-html", ctx.promo.donate_html, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  244)   envtab_install( &strbuf_envtab, "donate-js", ctx.promo.donate_js, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  245)   envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  246)   envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  247) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  248)   envtab_install( &strbuf_envtab, "git-version", ctx.vers.git, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  249)   envtab_install( &strbuf_envtab, "nginx-version", ctx.vers.nginx, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  250)   envtab_install( &strbuf_envtab, "cgit-version", ctx.vers.cgit, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  251) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  252)   envtab_install( &strbuf_envtab, "copyright-notice", ctx.vars.copyright_notice, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  253)   envtab_install( &strbuf_envtab, "copyright", ctx.vars.copyright, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  254) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  255)   envtab_install( &strbuf_envtab, "page-type", ctx.vars.page_type, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  256)   envtab_install( &strbuf_envtab, "page-size", ctx.vars.page_size, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  257)   envtab_install( &strbuf_envtab, "num-of-repos", ctx.vars.num_of_repos, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  258) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  259) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  260) void cgit_release_template_variables( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  261) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  262)   envtab_release( &strbuf_envtab );
05d292b2 (kx 2023-03-24 03:51:10 +0300  263) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  264) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  265) static void get_selfdir( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  266) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  267)   char    path[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300  268)   ssize_t len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  269) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  270)   bzero( (void *)path, PATH_MAX );
05d292b2 (kx 2023-03-24 03:51:10 +0300  271) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  272)   len = readlink( "/proc/self/exe", &path[0], (size_t)PATH_MAX );
05d292b2 (kx 2023-03-24 03:51:10 +0300  273)   if( len > 0 && len < PATH_MAX )
05d292b2 (kx 2023-03-24 03:51:10 +0300  274)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  275)     char *selfdir = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  276) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  277)     selfdir = (char *)__sbrk( (int)len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  278)     strcpy( selfdir, (const char *)dirname( (char *)&path[0] ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  279)     ctx.env.http_root = selfdir;
05d292b2 (kx 2023-03-24 03:51:10 +0300  280)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  281)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300  282)     fatal_html( "cannot get selfdir" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  283) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  284) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  285) static size_t read_http_root_raw_file( struct strbuf *sb, const char *fname )
05d292b2 (kx 2023-03-24 03:51:10 +0300  286) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  287)   char    path[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300  288)   int     fd = -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  289)   size_t  len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  290) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  291)   if( !sb || !fname || !*fname ) return len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  292) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  293)   bzero( (void *)path, PATH_MAX );
05d292b2 (kx 2023-03-24 03:51:10 +0300  294)   strcpy( (char *)&path[0], ctx.env.http_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  295)   if( *fname != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  296)     strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  297) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  298)   strcat( (char *)&path[0], fname );
05d292b2 (kx 2023-03-24 03:51:10 +0300  299) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  300)   if( (fd = open( (const char *)&path[0], O_RDONLY )) == -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  301)    fatal_html( "Cannot open %s file: %s", fname, strerror( errno ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  302) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  303)   len = strbuf_read( sb, fd, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  304)   close( fd );
05d292b2 (kx 2023-03-24 03:51:10 +0300  305) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  306)   return len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  307) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  308) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  309) static size_t read_http_root_env_file( struct strbuf *sb, const char *fname )
05d292b2 (kx 2023-03-24 03:51:10 +0300  310) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  311)   char    path[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300  312)   FILE   *fp = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  313)   size_t  len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  314) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  315)   if( !sb || !fname || !*fname ) return len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  316) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  317)   bzero( (void *)path, PATH_MAX );
05d292b2 (kx 2023-03-24 03:51:10 +0300  318)   strcpy( (char *)&path[0], ctx.env.http_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  319)   if( *fname != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  320)     strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  321) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  322)   strcat( (char *)&path[0], fname );
05d292b2 (kx 2023-03-24 03:51:10 +0300  323) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  324)   if( (fp = fopen( (const char *)&path[0], "r" )) == NULL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  325)    fatal_html( "Cannot open %s file: %s", fname, strerror( errno ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  326) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  327)   len = strbuf_env_fread( sb, fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300  328)   fclose( fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300  329) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  330)   if( len > STRBUF_MAXLINE )
05d292b2 (kx 2023-03-24 03:51:10 +0300  331)     fatal_html( "The '%s' file is too large. No more than 8192 bytes is allowed for includes", fname );
05d292b2 (kx 2023-03-24 03:51:10 +0300  332) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  333)   return len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  334) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  335) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  336) static void read_donate_html( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  337) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  338)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  339)   char  *html = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  340) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  341)   if( !ctx.promo.donate ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  342)   if( !ctx.promo.donate_html || !*ctx.promo.donate_html ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  343) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  344)   (void)read_http_root_env_file( &buf, ctx.promo.donate_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  345) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  346)   html = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  347)   memcpy( (void *)html, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  348)   ctx.promo.donate_html = (const char *)html;
05d292b2 (kx 2023-03-24 03:51:10 +0300  349)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  350) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  351) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  352) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  353) static char psize[4] = { 0, 0, 0, 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  354) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  355) static void ctx_page_size_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  356) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  357)   struct variable f = { (unsigned char *)"page-size", { 0 }, DT_NUMERICAL }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  358)   var = lookup_global( lookup_global_section( config ), &f );
05d292b2 (kx 2023-03-24 03:51:10 +0300  359)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  360)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  361)     if( var->type == DT_NUMERICAL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  362)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  363)       if( var->_v.val > 9 && var->_v.val < 201 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  364)         snprintf( &psize[0], 4, "%d", var->_v.val );
05d292b2 (kx 2023-03-24 03:51:10 +0300  365)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  366)         snprintf( &psize[0], 4, "%d", 200 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  367)       ctx.vars.page_size = &psize[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  368)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  369)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300  370)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  371)       int size = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  372)       sscanf( (const char *)var->_v.vptr, "%d", &size );
05d292b2 (kx 2023-03-24 03:51:10 +0300  373)       if( size > 9 && size < 201 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  374)         ctx.vars.page_size = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  375)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  376)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  377)         snprintf( &psize[0], 4, "%d", 200 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  378)         ctx.vars.page_size = &psize[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  379)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  380)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  381)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  382) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  383) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  384) static void ctx_page_size_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300  385) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  386)   struct variable f = { (unsigned char *)"page-size", { 0 }, DT_NUMERICAL }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  387)   var = lookup( repo, &f );
05d292b2 (kx 2023-03-24 03:51:10 +0300  388)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  389)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  390)     if( var->type == DT_NUMERICAL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  391)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  392)       if( var->_v.val > 9 && var->_v.val < 201 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  393)         snprintf( &psize[0], 4, "%d", var->_v.val );
05d292b2 (kx 2023-03-24 03:51:10 +0300  394)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  395)         snprintf( &psize[0], 4, "%d", 200 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  396)       ctx.vars.page_size = &psize[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  397)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  398)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300  399)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  400)       int size = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  401)       sscanf( (const char *)var->_v.vptr, "%d", &size );
05d292b2 (kx 2023-03-24 03:51:10 +0300  402)       if( size > 9 && size < 201 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  403)         ctx.vars.page_size = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  404)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  405)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  406)         snprintf( &psize[0], 4, "%d", 200 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  407)         ctx.vars.page_size = &psize[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  408)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  409)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  410)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  411) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  412) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  413) static void ctx_repo_dirs_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  414) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  415)   struct variable  git_root  = { (unsigned char *)"git-root",  { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  416)   struct variable  repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  417)   struct variable  trunk     = { (unsigned char *)"trunk",     { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  418)   struct variable  ro_prefix = { (unsigned char *)"clone-prefix-readonly", { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  419)   struct variable  rw_prefix = { (unsigned char *)"clone-prefix",          { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  420)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  421) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  422)   var = lookup_global( lookup_global_section( config ), &git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  423)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  424)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  425)     ctx.repo.git_root = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  426)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  427)   var = lookup_global( lookup_global_section( config ), &repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  428)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  429)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  430)     ctx.repo.repo_root = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  431)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  432)   var = lookup_global( lookup_global_section( config ), &trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  433)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  434)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  435)     ctx.repo.trunk = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  436)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  437)   var = lookup_global( lookup_global_section( config ), &rw_prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  438)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  439)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  440)     ctx.repo.clone_prefix = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  441)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  442)   var = lookup_global( lookup_global_section( config ), &ro_prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  443)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  444)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  445)     ctx.repo.clone_ro_prefix = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  446)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  447) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  448) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  449) static void ctx_site_vars_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  450) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  451)   struct variable                   css = { (unsigned char *)"css",                  { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  452)   struct variable                 owner = { (unsigned char *)"owner",                { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  453)   struct variable                author = { (unsigned char *)"author",               { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  454)   struct variable                 title = { (unsigned char *)"title",                { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  455)   struct variable           description = { (unsigned char *)"description",          { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  456)   struct variable              keywords = { (unsigned char *)"keywords",             { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  457)   struct variable      copyright_notice = { (unsigned char *)"copyright-notice",     { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  458)   struct variable             copyright = { (unsigned char *)"copyright",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  459)   struct variable          favicon_path = { (unsigned char *)"favicon-path",         { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  460)   struct variable                  logo = { (unsigned char *)"logo",                 { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  461)   struct variable              logo_alt = { (unsigned char *)"logo-alt",             { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  462)   struct variable             logo_link = { (unsigned char *)"logo-link",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  463)   struct variable             home_page = { (unsigned char *)"home-page",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  464)   struct variable             snapshots = { (unsigned char *)"snapshots",            { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  465)   struct variable        main_menu_logo = { (unsigned char *)"main-menu-logo",       { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  466)   struct variable  syntax_highlight_css = { (unsigned char *)"syntax-highlight-css", { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  467)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  468) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  469)   var = lookup_global( lookup_global_section( config ), &css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  470)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  471)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  472)     ctx.vars.css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  473)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  474)   var = lookup_global( lookup_global_section( config ), &owner );
05d292b2 (kx 2023-03-24 03:51:10 +0300  475)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  476)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  477)     ctx.vars.owner = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  478)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  479)   var = lookup_global( lookup_global_section( config ), &author );
05d292b2 (kx 2023-03-24 03:51:10 +0300  480)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  481)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  482)     ctx.vars.author = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  483)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  484)   var = lookup_global( lookup_global_section( config ), &title );
05d292b2 (kx 2023-03-24 03:51:10 +0300  485)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  486)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  487)     ctx.vars.title = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  488)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  489)   var = lookup_global( lookup_global_section( config ), &description );
05d292b2 (kx 2023-03-24 03:51:10 +0300  490)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  491)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  492)     ctx.vars.description = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  493)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  494)   var = lookup_global( lookup_global_section( config ), &keywords );
05d292b2 (kx 2023-03-24 03:51:10 +0300  495)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  496)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  497)     ctx.vars.keywords = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  498)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  499)   var = lookup_global( lookup_global_section( config ), &copyright_notice );
05d292b2 (kx 2023-03-24 03:51:10 +0300  500)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  501)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  502)     ctx.vars.copyright_notice = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  503)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  504)   var = lookup_global( lookup_global_section( config ), &copyright );
05d292b2 (kx 2023-03-24 03:51:10 +0300  505)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  506)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  507)     ctx.vars.copyright = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  508)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  509)   var = lookup_global( lookup_global_section( config ), &favicon_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300  510)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  511)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  512)     ctx.vars.favicon_path = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  513)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  514)   var = lookup_global( lookup_global_section( config ), &logo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  515)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  516)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  517)     ctx.vars.logo = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  518)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  519)   var = lookup_global( lookup_global_section( config ), &logo_alt );
05d292b2 (kx 2023-03-24 03:51:10 +0300  520)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  521)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  522)     ctx.vars.logo_alt = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  523)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  524)   var = lookup_global( lookup_global_section( config ), &logo_link );
05d292b2 (kx 2023-03-24 03:51:10 +0300  525)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  526)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  527)     ctx.vars.logo_link = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  528)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  529)   var = lookup_global( lookup_global_section( config ), &home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300  530)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  531)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  532)     ctx.vars.home_page = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  533)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  534)   var = lookup_global( lookup_global_section( config ), &snapshots );
05d292b2 (kx 2023-03-24 03:51:10 +0300  535)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  536)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  537)     ctx.vars.snapshots = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  538)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  539)   var = lookup_global( lookup_global_section( config ), &main_menu_logo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  540)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  541)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  542)     ctx.vars.main_menu_logo = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  543)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  544)   var = lookup_global( lookup_global_section( config ), &syntax_highlight_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  545)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  546)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  547)     ctx.vars.syntax_highlight_css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  548)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  549) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  550) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  551) static void ctx_promo_vars_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  552) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  553)   struct variable  analytic_links   = { (unsigned char *)"analytic-links",   { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  554)   struct variable  analytic_scripts = { (unsigned char *)"analytic-scripts", { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  555)   struct variable  donate           = { (unsigned char *)"donate",           { 0 }, DT_NUMERICAL };
05d292b2 (kx 2023-03-24 03:51:10 +0300  556)   struct variable  donate_css       = { (unsigned char *)"donate-css",       { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  557)   struct variable  donate_html      = { (unsigned char *)"donate-html",      { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  558)   struct variable  donate_js        = { (unsigned char *)"donate-js",        { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  559)   struct variable  donate_header    = { (unsigned char *)"donate-header",    { 0 }, DT_STRING    };
05d292b2 (kx 2023-03-24 03:51:10 +0300  560)   struct variable  donate_purpose   = { (unsigned char *)"donate-purpose",   { 0 }, DT_STRING    };
05d292b2 (kx 2023-03-24 03:51:10 +0300  561)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  562) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  563)   var = lookup_global( lookup_global_section( config ), &analytic_links );
05d292b2 (kx 2023-03-24 03:51:10 +0300  564)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  565)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  566)     ctx.promo.analytic_links = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  567) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  568)     if( ctx.promo.analytic_links && *ctx.promo.analytic_links )
05d292b2 (kx 2023-03-24 03:51:10 +0300  569)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  570)       struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  571)       char  *links = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  572) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  573)       (void)read_http_root_raw_file( &buf, ctx.promo.analytic_links );
05d292b2 (kx 2023-03-24 03:51:10 +0300  574) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  575)       links = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  576)       memcpy( (void *)links, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  577)       ctx.promo.analytic_links = (const char *)links;
05d292b2 (kx 2023-03-24 03:51:10 +0300  578)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  579)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  580)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  581)   var = lookup_global( lookup_global_section( config ), &analytic_scripts );
05d292b2 (kx 2023-03-24 03:51:10 +0300  582)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  583)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  584)     ctx.promo.analytic_scripts = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  585) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  586)     if( ctx.promo.analytic_scripts && *ctx.promo.analytic_scripts )
05d292b2 (kx 2023-03-24 03:51:10 +0300  587)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  588)       struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  589)       char  *scripts = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  590) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  591)       (void)read_http_root_raw_file( &buf, ctx.promo.analytic_scripts );
05d292b2 (kx 2023-03-24 03:51:10 +0300  592) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  593)       scripts = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  594)       memcpy( (void *)scripts, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  595)       ctx.promo.analytic_scripts = (const char *)scripts;
05d292b2 (kx 2023-03-24 03:51:10 +0300  596)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  597)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  598)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  599) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  600)   var = lookup_global( lookup_global_section( config ), &donate );
05d292b2 (kx 2023-03-24 03:51:10 +0300  601)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  602)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  603)     if( var->type == DT_NUMERICAL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  604)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  605)       ctx.promo.donate = var->_v.val;
05d292b2 (kx 2023-03-24 03:51:10 +0300  606)       if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300  607)         ctx.promo.donate = 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  608)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  609)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  610) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  611)   if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300  612)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  613)     var = lookup_global( lookup_global_section( config ), &donate_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  614)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  615)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  616)       ctx.promo.donate_css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  617) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  618)       if( ctx.promo.donate_css && *ctx.promo.donate_css )
05d292b2 (kx 2023-03-24 03:51:10 +0300  619)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  620)         struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  621)         char  *css = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  622) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  623)         strbuf_addf( &buf, "<link rel=\"stylesheet\" href=\"%s\">", ctx.promo.donate_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  624)         strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  625)         css = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  626)         memcpy( (void *)css, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  627)         ctx.promo.donate_css = (const char *)css;
05d292b2 (kx 2023-03-24 03:51:10 +0300  628)         strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  629)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  630)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  631)     var = lookup_global( lookup_global_section( config ), &donate_js );
05d292b2 (kx 2023-03-24 03:51:10 +0300  632)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  633)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  634)       ctx.promo.donate_js = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  635) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  636)       if( ctx.promo.donate_js && *ctx.promo.donate_js )
05d292b2 (kx 2023-03-24 03:51:10 +0300  637)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  638)         struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  639)         char  *js = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  640) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  641)         strbuf_addf( &buf, "<script src=\"%s\"></script>", ctx.promo.donate_js );
05d292b2 (kx 2023-03-24 03:51:10 +0300  642)         strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  643)         js = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  644)         memcpy( (void *)js, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  645)         ctx.promo.donate_js = (const char *)js;
05d292b2 (kx 2023-03-24 03:51:10 +0300  646)         strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  647)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  648)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  649)     var = lookup_global( lookup_global_section( config ), &donate_header );
05d292b2 (kx 2023-03-24 03:51:10 +0300  650)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  651)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  652)       ctx.promo.donate_header = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  653)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  654)     var = lookup_global( lookup_global_section( config ), &donate_purpose );
05d292b2 (kx 2023-03-24 03:51:10 +0300  655)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  656)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  657)       ctx.promo.donate_purpose = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  658)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  659) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  660)     var = lookup_global( lookup_global_section( config ), &donate_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  661)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  662)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  663)       ctx.promo.donate_html = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  664) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  665)       if( ctx.promo.donate_html && *ctx.promo.donate_html )
05d292b2 (kx 2023-03-24 03:51:10 +0300  666)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  667)         envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  668)         envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  669)         read_donate_html();
05d292b2 (kx 2023-03-24 03:51:10 +0300  670)         envtab_release( &strbuf_envtab );
05d292b2 (kx 2023-03-24 03:51:10 +0300  671)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  672)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  673)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  674) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  675) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  676) static void ctx_repo_dirs_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300  677) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  678)   struct variable  git_root  = { (unsigned char *)"git-root",  { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  679)   struct variable  repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  680)   struct variable  trunk     = { (unsigned char *)"trunk",     { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  681)   struct variable  ro_prefix = { (unsigned char *)"clone-prefix-readonly", { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  682)   struct variable  rw_prefix = { (unsigned char *)"clone-prefix",          { 0 }, DT_PATH };
05d292b2 (kx 2023-03-24 03:51:10 +0300  683)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  684) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  685)   if( !repo ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  686) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  687)   var = lookup( repo, &git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  688)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  689)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  690)     ctx.repo.git_root = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  691)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  692)   var = lookup( repo, &repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  693)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  694)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  695)     ctx.repo.repo_root = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  696)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  697)   var = lookup( repo, &trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  698)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  699)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  700)     ctx.repo.trunk = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  701)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  702)   var = lookup( repo, &rw_prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  703)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  704)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  705)     ctx.repo.clone_prefix = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  706)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  707)   var = lookup( repo, &ro_prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  708)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  709)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  710)     ctx.repo.clone_ro_prefix = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  711)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  712) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  713) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  714) static void ctx_site_vars_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300  715) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  716)   struct variable                   css = { (unsigned char *)"css",                  { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  717)   struct variable                 owner = { (unsigned char *)"owner",                { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  718)   struct variable                author = { (unsigned char *)"author",               { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  719)   struct variable                 title = { (unsigned char *)"title",                { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  720)   struct variable           description = { (unsigned char *)"description",          { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  721)   struct variable              keywords = { (unsigned char *)"keywords",             { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  722)   struct variable      copyright_notice = { (unsigned char *)"copyright-notice",     { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  723)   struct variable             copyright = { (unsigned char *)"copyright",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  724)   struct variable          favicon_path = { (unsigned char *)"favicon-path",         { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  725)   struct variable                  logo = { (unsigned char *)"logo",                 { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  726)   struct variable              logo_alt = { (unsigned char *)"logo-alt",             { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  727)   struct variable             logo_link = { (unsigned char *)"logo-link",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  728)   struct variable             home_page = { (unsigned char *)"home-page",            { 0 }, DT_STRING };
05d292b2 (kx 2023-03-24 03:51:10 +0300  729)   struct variable             snapshots = { (unsigned char *)"snapshots",            { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  730)   struct variable        main_menu_logo = { (unsigned char *)"main-menu-logo",       { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  731)   struct variable  syntax_highlight_css = { (unsigned char *)"syntax-highlight-css", { 0 }, DT_PATH   };
05d292b2 (kx 2023-03-24 03:51:10 +0300  732)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  733) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  734)   if( !repo ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  735) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  736)   var = lookup( repo, &css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  737)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  738)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  739)     ctx.vars.css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  740)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  741)   var = lookup( repo, &owner );
05d292b2 (kx 2023-03-24 03:51:10 +0300  742)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  743)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  744)     ctx.vars.owner = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  745)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  746)   var = lookup( repo, &author );
05d292b2 (kx 2023-03-24 03:51:10 +0300  747)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  748)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  749)     ctx.vars.author = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  750)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  751)   var = lookup( repo, &title );
05d292b2 (kx 2023-03-24 03:51:10 +0300  752)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  753)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  754)     ctx.vars.title = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  755)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  756)   var = lookup( repo, &description );
05d292b2 (kx 2023-03-24 03:51:10 +0300  757)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  758)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  759)     ctx.vars.description = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  760)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  761)   var = lookup( repo, &keywords );
05d292b2 (kx 2023-03-24 03:51:10 +0300  762)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  763)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  764)     ctx.vars.keywords = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  765)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  766)   var = lookup( repo, &copyright_notice );
05d292b2 (kx 2023-03-24 03:51:10 +0300  767)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  768)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  769)     ctx.vars.copyright_notice = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  770)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  771)   var = lookup( repo, &copyright );
05d292b2 (kx 2023-03-24 03:51:10 +0300  772)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  773)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  774)     ctx.vars.copyright = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  775)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  776)   var = lookup( repo, &favicon_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300  777)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  778)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  779)     ctx.vars.favicon_path = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  780)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  781)   var = lookup( repo, &logo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  782)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  783)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  784)     ctx.vars.logo = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  785)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  786)   var = lookup( repo, &logo_alt );
05d292b2 (kx 2023-03-24 03:51:10 +0300  787)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  788)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  789)     ctx.vars.logo_alt = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  790)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  791)   var = lookup( repo, &logo_link );
05d292b2 (kx 2023-03-24 03:51:10 +0300  792)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  793)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  794)     ctx.vars.logo_link = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  795)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  796)   var = lookup( repo, &home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300  797)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  798)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  799)     ctx.vars.home_page = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  800)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  801)   var = lookup( repo, &snapshots );
05d292b2 (kx 2023-03-24 03:51:10 +0300  802)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  803)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  804)     ctx.vars.snapshots = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  805)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  806)   var = lookup( repo, &main_menu_logo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  807)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  808)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  809)     ctx.vars.main_menu_logo = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  810)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  811)   var = lookup( repo, &syntax_highlight_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  812)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  813)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  814)     ctx.vars.syntax_highlight_css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  815)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  816) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  817) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  818) static void ctx_promo_vars_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300  819) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  820)   struct variable  analytic_links   = { (unsigned char *)"analytic-links",   { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  821)   struct variable  analytic_scripts = { (unsigned char *)"analytic-scripts", { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  822)   struct variable  donate           = { (unsigned char *)"donate",           { 0 }, DT_NUMERICAL };
05d292b2 (kx 2023-03-24 03:51:10 +0300  823)   struct variable  donate_css       = { (unsigned char *)"donate-css",       { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  824)   struct variable  donate_html      = { (unsigned char *)"donate-html",      { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  825)   struct variable  donate_js        = { (unsigned char *)"donate-js",        { 0 }, DT_PATH      };
05d292b2 (kx 2023-03-24 03:51:10 +0300  826)   struct variable  donate_header    = { (unsigned char *)"donate-header",    { 0 }, DT_STRING    };
05d292b2 (kx 2023-03-24 03:51:10 +0300  827)   struct variable  donate_purpose   = { (unsigned char *)"donate-purpose",   { 0 }, DT_STRING    };
05d292b2 (kx 2023-03-24 03:51:10 +0300  828)   struct variable *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  829) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  830)   /*
05d292b2 (kx 2023-03-24 03:51:10 +0300  831)     Analytics reads from global section only:
05d292b2 (kx 2023-03-24 03:51:10 +0300  832)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300  833)   var = lookup_global( lookup_global_section( config ), &analytic_links );
05d292b2 (kx 2023-03-24 03:51:10 +0300  834)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  835)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  836)     ctx.promo.analytic_links = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  837) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  838)     if( ctx.promo.analytic_links && *ctx.promo.analytic_links )
05d292b2 (kx 2023-03-24 03:51:10 +0300  839)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  840)       struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  841)       char  *links = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  842) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  843)       (void)read_http_root_raw_file( &buf, ctx.promo.analytic_links );
05d292b2 (kx 2023-03-24 03:51:10 +0300  844) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  845)       links = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  846)       memcpy( (void *)links, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  847)       ctx.promo.analytic_links = (const char *)links;
05d292b2 (kx 2023-03-24 03:51:10 +0300  848)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  849)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  850)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  851)   var = lookup_global( lookup_global_section( config ), &analytic_scripts );
05d292b2 (kx 2023-03-24 03:51:10 +0300  852)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  853)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  854)     ctx.promo.analytic_scripts = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  855) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  856)     if( ctx.promo.analytic_scripts && *ctx.promo.analytic_scripts )
05d292b2 (kx 2023-03-24 03:51:10 +0300  857)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  858)       struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  859)       char  *scripts = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  860) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  861)       (void)read_http_root_raw_file( &buf, ctx.promo.analytic_scripts );
05d292b2 (kx 2023-03-24 03:51:10 +0300  862) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  863)       scripts = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  864)       memcpy( (void *)scripts, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  865)       ctx.promo.analytic_scripts = (const char *)scripts;
05d292b2 (kx 2023-03-24 03:51:10 +0300  866)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  867)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  868)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  869) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  870)   var = lookup( repo, &donate );
05d292b2 (kx 2023-03-24 03:51:10 +0300  871)   if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  872)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  873)     if( var->type == DT_NUMERICAL )
05d292b2 (kx 2023-03-24 03:51:10 +0300  874)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  875)       ctx.promo.donate = var->_v.val;
05d292b2 (kx 2023-03-24 03:51:10 +0300  876)       if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300  877)         ctx.promo.donate = 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  878)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  879)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  880) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  881)   if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300  882)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  883)     var = lookup( repo, &donate_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  884)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  885)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  886)       ctx.promo.donate_css = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  887) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  888)       if( ctx.promo.donate_css && *ctx.promo.donate_css )
05d292b2 (kx 2023-03-24 03:51:10 +0300  889)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  890)         struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  891)         char  *css = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  892) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  893)         strbuf_addf( &buf, "<link rel=\"stylesheet\" href=\"%s\">", ctx.promo.donate_css );
05d292b2 (kx 2023-03-24 03:51:10 +0300  894)         strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  895)         css = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  896)         memcpy( (void *)css, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  897)         ctx.promo.donate_css = (const char *)css;
05d292b2 (kx 2023-03-24 03:51:10 +0300  898)         strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  899)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  900)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  901)     var = lookup( repo, &donate_js );
05d292b2 (kx 2023-03-24 03:51:10 +0300  902)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  903)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  904)       ctx.promo.donate_js = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  905) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  906)       if( ctx.promo.donate_js && *ctx.promo.donate_js )
05d292b2 (kx 2023-03-24 03:51:10 +0300  907)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  908)         struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  909)         char  *js = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  910) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  911)         strbuf_addf( &buf, "<script src=\"%s\"></script>", ctx.promo.donate_js );
05d292b2 (kx 2023-03-24 03:51:10 +0300  912)         strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  913)         js = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  914)         memcpy( (void *)js, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  915)         ctx.promo.donate_js = (const char *)js;
05d292b2 (kx 2023-03-24 03:51:10 +0300  916)         strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  917)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  918)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  919)     var = lookup( repo, &donate_header );
05d292b2 (kx 2023-03-24 03:51:10 +0300  920)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  921)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  922)       ctx.promo.donate_header = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  923)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  924)     var = lookup( repo, &donate_purpose );
05d292b2 (kx 2023-03-24 03:51:10 +0300  925)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  926)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  927)       ctx.promo.donate_purpose = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  928)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  929)     var = lookup( repo, &donate_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  930)     if( var )
05d292b2 (kx 2023-03-24 03:51:10 +0300  931)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  932)       ctx.promo.donate_html = (const char *)var->_v.vptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300  933) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  934)       if( ctx.promo.donate_html && *ctx.promo.donate_html )
05d292b2 (kx 2023-03-24 03:51:10 +0300  935)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  936)         envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  937)         envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html );
05d292b2 (kx 2023-03-24 03:51:10 +0300  938)         read_donate_html();
05d292b2 (kx 2023-03-24 03:51:10 +0300  939)         envtab_release( &strbuf_envtab );
05d292b2 (kx 2023-03-24 03:51:10 +0300  940)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  941)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  942)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  943) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  944) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  945) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  946) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  947) static char nrepos[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  948) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  949) static void ctx_num_of_repos( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  950) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  951)   int32_t  num = repolist_length( config );
05d292b2 (kx 2023-03-24 03:51:10 +0300  952)   num &= 0x7fffffff;
05d292b2 (kx 2023-03-24 03:51:10 +0300  953)   if( num > 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  954)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  955)     snprintf( &nrepos[0], 11, "%d", num );
05d292b2 (kx 2023-03-24 03:51:10 +0300  956)     ctx.vars.num_of_repos = &nrepos[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  957)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  958) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  959) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  960) static void ctx_repolist_status_line( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  961) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  962)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  963)   char    *nrepos_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  964)   char    *status_line   = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  965)   int32_t  num = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  966) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  967)   sscanf( ctx.vars.num_of_repos, "%d", &num );
05d292b2 (kx 2023-03-24 03:51:10 +0300  968) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  969)   strbuf_addf( &buf, Q_("%d Git Repository", "%d Git Repositories", num), num );
05d292b2 (kx 2023-03-24 03:51:10 +0300  970)   nrepos_string = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  971)   memcpy( (void *)nrepos_string, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  972)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  973) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  974)   buf.alloc = 0, buf.len = 0, buf.fatal = strbuf_fatal, buf.buf = strbuf_slopbuf;
05d292b2 (kx 2023-03-24 03:51:10 +0300  975) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  976)   strbuf_addf( &buf, "<span class=\"las la-cloud-upload\"></span> %s\n", nrepos_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300  977)   if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300  978)     strbuf_addf( &buf, "&nbsp; | <a class=\"donate\"><span class=\"icon las la-credit-card\"></span> Donate</a>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  979) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  980)   status_line = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  981)   memcpy( (void *)status_line, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  982)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300  983) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  984)   ctx.vars.status_line = (const char *)status_line;
05d292b2 (kx 2023-03-24 03:51:10 +0300  985) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  986) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  987) static void ctx_repo_status_line( struct cgit_repository *rctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300  988) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  989)   struct strbuf buf      = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  990)   struct strbuf branches = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  991)   struct strbuf commits  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  992)   struct strbuf tags     = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300  993)   char  *status_line = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  994) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  995)   if( !rctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  996) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  997)   strbuf_addf( &commits, Q_("%d Commit", "%d Commits", rctx->ncommits), rctx->ncommits );
05d292b2 (kx 2023-03-24 03:51:10 +0300  998)   strbuf_addf( &branches, Q_("%d Branch", "%d Branches", rctx->nbranches), rctx->nbranches );
05d292b2 (kx 2023-03-24 03:51:10 +0300  999)   strbuf_addf( &tags, Q_("%d Tag", "%d Tags", rctx->ntags), rctx->ntags );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1000) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1001)   if( rctx->ncommits == 9999 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1002)     strbuf_addf( &buf, "<span class=\"las la-code-commit\"></span> More than %s &nbsp;\n", commits.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1003)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1004)     strbuf_addf( &buf, "<span class=\"las la-code-commit\"></span> %s &nbsp;\n", commits.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1005)   strbuf_addf( &buf, "<span class=\"las la-code-branch\"></span> %s &nbsp;\n", branches.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1006)   strbuf_addf( &buf, "<span class=\"las la-tags\"></span> %s\n", tags.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1007)   if( ctx.promo.donate )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1008)     strbuf_addf( &buf, "&nbsp; | <a class=\"donate\"><span class=\"icon las la-credit-card\"></span> Donate</a>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1009) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1010)   strbuf_release( &branches );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1011)   strbuf_release( &commits );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1012)   strbuf_release( &tags );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1013) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1014)   status_line = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1015)   memcpy( (void *)status_line, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1016)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1017) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1018)   ctx.vars.status_line = (const char *)status_line;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1019) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1020) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1021) static void ctx_repolist_menu( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1022) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1023)   struct strbuf mmenu = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1024)   struct strbuf popup = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1025)   struct strbuf right = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1026) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1027)   char *main_menu  = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1028)   char *popup_menu = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1029)   char *right_menu = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1030) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1031)   strbuf_addf( &mmenu, "<a href=\"/\">Index</a>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1032)   strbuf_addf( &popup, "<div class=\"item\"><span class=\"icon las la-home\"></span><a href=\"%s\" target=\"_blank\">Home page</a></div>\n", ctx.vars.home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1033)   strbuf_addf( &right, "<div class=\"item\"><a href=\"%s\" target=\"_blank\">Home page</a></div>\n", ctx.vars.home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1034) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1035)   main_menu = (char *)__sbrk( (int)mmenu.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1036)   memcpy( (void *)main_menu, (const void *)mmenu.buf, mmenu.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1037)   strbuf_release( &mmenu );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1038)   ctx.vars.main_menu_item = (const char *)main_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1039) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1040)   popup_menu = (char *)__sbrk( (int)popup.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1041)   memcpy( (void *)popup_menu, (const void *)popup.buf, popup.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1042)   strbuf_release( &popup );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1043)   ctx.vars.popup_menu_items = (const char *)popup_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1044) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1045)   right_menu = (char *)__sbrk( (int)right.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1046)   memcpy( (void *)right_menu, (const void *)right.buf, right.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1047)   strbuf_release( &right );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1048)   ctx.vars.right_menu_items = (const char *)right_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1049) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1050) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1051) static void ctx_repo_menu( struct cgit_repository *rctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1052) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1053)   struct strbuf mmenu = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1054)   struct strbuf left  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1055)   struct strbuf popup = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1056)   struct strbuf right = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1057) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1058)   char *main_menu  = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1059)   char *left_menu  = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1060)   char *popup_menu = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1061)   char *right_menu = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1062) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1063)   if( !rctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1064) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1065)   strbuf_addf( &mmenu, "<a href=\"/\">Index</a>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1066) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1067)   strbuf_addf( &left, "<div class=\"item\"><a href=\"/%s/%s/\">Trunk</a></div>\n", rctx->name, "trunk" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1068)   strbuf_addf( &left, "<div class=\"item\"><a href=\"/%s/%s/\">Branches</a></div>\n", rctx->name, "branches" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1069)   strbuf_addf( &left, "<div class=\"item\"><a href=\"/%s/%s/\">Tags</a></div>\n", rctx->name, "tags" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1070) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1071)   strbuf_addf( &popup, "<div class=\"item\"><span class=\"icon las la-road\"></span><a href=\"/%s/%s/\">Trunk</a></div>\n", rctx->name, "trunk" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1072)   strbuf_addf( &popup, "<div class=\"item\"><span class=\"icon las la-code-branch\"></span><a href=\"/%s/%s/\">Branches</a></div>\n", rctx->name, "branches" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1073)   strbuf_addf( &popup, "<div class=\"item\"><span class=\"icon las la-tags\"></span><a href=\"/%s/%s/\">Tags</a></div>\n", rctx->name, "tags" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1074)   strbuf_addf( &popup, "<div class=\"divider\"></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1075)   strbuf_addf( &popup, "<div class=\"item\"><span class=\"icon las la-home\"></span><a href=\"%s\" target=\"_blank\">Home page</a></div>\n", ctx.vars.home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1076) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1077)   strbuf_addf( &right, "<div class=\"item\"><a href=\"%s\" target=\"_blank\">Home page</a></div>\n", ctx.vars.home_page );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1078) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1079)   main_menu = (char *)__sbrk( (int)mmenu.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1080)   memcpy( (void *)main_menu, (const void *)mmenu.buf, mmenu.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1081)   strbuf_release( &mmenu );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1082)   ctx.vars.main_menu_item = (const char *)main_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1083) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1084)   left_menu = (char *)__sbrk( (int)left.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1085)   memcpy( (void *)left_menu, (const void *)left.buf, left.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1086)   strbuf_release( &left );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1087)   ctx.vars.left_menu_items = (const char *)left_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1088) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1089)   popup_menu = (char *)__sbrk( (int)popup.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1090)   memcpy( (void *)popup_menu, (const void *)popup.buf, popup.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1091)   strbuf_release( &popup );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1092)   ctx.vars.popup_menu_items = (const char *)popup_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1093) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1094)   right_menu = (char *)__sbrk( (int)right.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1095)   memcpy( (void *)right_menu, (const void *)right.buf, right.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1096)   strbuf_release( &right );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1097)   ctx.vars.right_menu_items = (const char *)right_menu;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1098) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1099) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1100) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1101) static void ctx_header_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1102) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1103)   struct strbuf   buf  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1104)   struct variable head = { (unsigned char *)"header", { 0 }, DT_PATH }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1105)   char  *pheader = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1106) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1107)   var = lookup_global( lookup_global_section( config ), &head );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1108)   strbuf_selfdir( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1109) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1110)   if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1111)   else      { strbuf_addf( &buf, "%s", ctx.page.header );            }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1112) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1113)   pheader = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1114)   sprintf( pheader, "%s", buf.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1115)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1116)   ctx.page.header = (const char *)pheader;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1117) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1118) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1119) static void ctx_header_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1120) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1121)   struct strbuf   buf  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1122)   struct variable head = { (unsigned char *)"header", { 0 }, DT_PATH }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1123)   char  *pheader = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1124) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1125)   var = lookup( repo, &head );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1126)   strbuf_selfdir( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1127) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1128)   if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1129)   else      { strbuf_addf( &buf, "%s", ctx.page.header );            }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1130) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1131)   pheader = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1132)   sprintf( pheader, "%s", buf.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1133)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1134)   ctx.page.header = (const char *)pheader;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1135) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1136) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1137) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1138) static void ctx_footer_from_global( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1139) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1140)   struct strbuf   buf  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1141)   struct variable foot = { (unsigned char *)"footer", { 0 }, DT_PATH }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1142)   char  *pfooter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1143) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1144)   var = lookup_global( lookup_global_section( config ), &foot );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1145)   strbuf_selfdir( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1146) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1147)   if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1148)   else      { strbuf_addf( &buf, "%s", ctx.page.footer );            }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1149) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1150)   pfooter = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1151)   sprintf( pfooter, "%s", buf.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1152)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1153)   ctx.page.footer = (const char *)pfooter;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1154) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1155) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1156) static void ctx_footer_from_repo( struct repo *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1157) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1158)   struct strbuf   buf  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1159)   struct variable foot = { (unsigned char *)"footer", { 0 }, DT_PATH }, *var = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1160)   char  *pfooter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1161) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1162)   var = lookup( repo, &foot );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1163)   strbuf_selfdir( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1164) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1165)   if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1166)   else      { strbuf_addf( &buf, "%s", ctx.page.footer );            }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1167) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1168)   pfooter = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1169)   sprintf( pfooter, "%s", buf.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1170)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1171)   ctx.page.footer = (const char *)pfooter;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1172) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1173) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1174) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1175) static char name[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1176) static char repo_root[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1177) static char relative_path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1178) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1179) static char try[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1180) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1181) static struct repo *ctx_repo_name( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1182) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1183)   struct repo *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1184)   char *s, *p = NULL, *n, *path, *path_info;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1185)   int   len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1186) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1187)   if( strcmp( "/", ctx.env.path_info ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1188)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1189)     path_info = xstrdup( ctx.env.path_info );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1190)     s = path_info;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1191) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1192)     while( *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1193)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1194)       while( *s && is_dir_sep( *s ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1195)         ++s;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1196)       n = p = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1197) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1198)       while( *p && !is_dir_sep( *p ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1199)         ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1200)       if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1201)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1202)         *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1203) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1204)         /****************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1205)           The repo name can be given as a relative path in the git-root:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1206)          */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1207)         if( repo_root[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1208)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1209)           sprintf( try, "%s", repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1210)           strcat( try, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1211)           strcat( try, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1212)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1213)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1214)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1215)           sprintf( try, "%s", n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1216)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1217) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1218)         if( (repo = lookup_repo( config, try )) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1219)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1220)           sprintf( name, "%s", try );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1221)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1222)             char *rr = strstr( repo_root, try );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1223)             if( rr )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1224)               *rr = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 1225)             else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1226)               repo_root[0] = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 1227)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1228)           break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1229)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1230)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1231)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1232)           if( repo_root[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1233)             strcat( repo_root, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1234)           strcat( repo_root, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1235)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1236)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1237)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1238)         s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1239)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1240) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1241)     ctx.repo.name = (const char *)&name[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1242)     ctx.repo.repo_root = (const char *)&repo_root[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1243) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1244)     path = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1245) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1246)     if( *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1247)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1248)       len = (int)strlen( path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1249) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1250)       if( path[len-1] =='/' ) { path[len-1] = '\0'; --len; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1251)       len += 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1252) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1253)       sprintf( relative_path, "%s", path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1254)       ctx.repo.relative_path = (const char *)&relative_path[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1255)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1256) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1257)     free( path_info );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1258)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1259) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1260)   return repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1261) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1262) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1263) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1264) /*************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1265)   Get integer value of query parameter 'name' and remove this
05d292b2 (kx 2023-03-24 03:51:10 +0300 1266)   parameter 'name=..' from ctx.env.query_string.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1267)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1268) int ctx_grab_int_query_param( const char *name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1269) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1270)   char *pofs = NULL, *query_string, *s = (char *)ctx.env.query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1271)   int   ret = 0, len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1272) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1273)   if( !name || !*name ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1274) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1275)   if( s && *s && (pofs = strstr( s, name )) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1276)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1277)     char *rem, *p, *val = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1278)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1279) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1280)     p = pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1281) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1282)     /* move to end of 'ofs=val' declaration: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1283)     while( *p && *p != '&' && *p != '=' ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1284)     if( *p == '=' ) { val = ++p; while( *p && *p != '&' ) ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1285)     if( *p ) { *p = '\0'; rem = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1286)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1287)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1288)       rem = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1289)       if( s < pofs && (pofs[-1] == '&' || pofs[-1] == '=') ) --pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1290)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1291) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1292)     /* fill buffer: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1293)     while( s < pofs ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1294)     s = rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1295)     while( *s ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1296)     strbuf_addch( &buf, '\0' );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1297) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1298)     /* get value: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1299)     if( val && *val ) { ret = atoi( val ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1300)     else              { ret = 0;           }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1301) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1302)     len = (int)buf.len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1303)     query_string = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1304)     memcpy( (void *)query_string, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1305)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1306)     ctx.env.query_string = (const char *)query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1307)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1308) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1309)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1310) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1311) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1312) /*************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1313)   Get string value of query parameter 'name' and remove this
05d292b2 (kx 2023-03-24 03:51:10 +0300 1314)   parameter 'name=..' from ctx.env.query_string.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1315)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1316) const char *ctx_grab_str_query_param( const char *name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1317) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1318)   const char *ret = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1319)   char *pofs = NULL, *query_string, *s = (char *)ctx.env.query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1320)   int   len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1321) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1322)   if( !name || !*name ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1323) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1324)   if( s && *s && (pofs = strstr( s, name )) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1325)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1326)     char *rem, *p, *val = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1327)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1328) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1329)     p = pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1330) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1331)     /* move to end of 'ofs=val' declaration: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1332)     while( *p && *p != '&' && *p != '=' ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1333)     if( *p == '=' ) { val = ++p; while( *p && *p != '&' ) ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1334)     if( *p ) { *p = '\0'; rem = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1335)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1336)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1337)       rem = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1338)       if( s < pofs && (pofs[-1] == '&' || pofs[-1] == '=') ) --pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1339)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1340) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1341)     /* fill buffer: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1342)     while( s < pofs ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1343)     s = rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1344)     while( *s ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1345)     strbuf_addch( &buf, '\0' );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1346) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1347)     /* get value: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1348)     if( val && *val )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1349)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1350)       char *value = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1351) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1352)       len = (int)strlen( val ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1353)       value = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1354)       memcpy( (void *)value, (const void *)val, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1355) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1356)       ret = (const char *)value;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1357)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1358) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1359)     len = (int)buf.len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1360)     query_string = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1361)     memcpy( (void *)query_string, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1362)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1363)     ctx.env.query_string = (const char *)query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1364)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1365) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1366)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1367) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1368) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1369) /***************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1370)   Rmove parametr with specified 'name=...' fom query string and
05d292b2 (kx 2023-03-24 03:51:10 +0300 1371)   return modified query string allocated in context _mem[].
05d292b2 (kx 2023-03-24 03:51:10 +0300 1372)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1373) const char *ctx_remove_query_param( const char *query_string, const char *name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1374) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1375)   char *pofs = NULL, *query = NULL, *s = (char *)query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1376)   int len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1377) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1378)   if( !name || !*name ) return (const char *)query;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1379) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1380)   if( s && *s && (pofs = strstr( s, name )) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1381)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1382)     char *rem, *p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1383)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1384) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1385)     p = pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1386) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1387)     /* move to end of 'ofs=val' declaration: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1388)     while( *p && *p != '&' && *p != '=' ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1389)     if( *p == '=' ) { while( *p && *p != '&' ) ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1390)     if( *p ) { *p = '\0'; rem = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1391)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1392)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1393)       rem = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1394)       if( s < pofs && (pofs[-1] == '&' || pofs[-1] == '=') ) --pofs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1395)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1396) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1397)     /* fill buffer: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1398)     while( s < pofs ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1399)     s = rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1400)     while( *s ) { strbuf_addch( &buf, *s ); ++s; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1401)     strbuf_addch( &buf, '\0' );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1402) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1403)     len = (int)buf.len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1404)     query = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1405)     memcpy( (void *)query, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1406)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1407)     return (const char *)query;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1408)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1409) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1410)   return (const char *)query;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1411) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1412) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1413) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1414) static void ctx_search_placeholder( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1415) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1416)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1417)   char  *revision;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1418)   int    len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1419) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1420)   if( !strcmp( ctx.vars.page_type, ptype_repo ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1421)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1422)     if( ctx.query.rev && strcmp( ctx.query.rev, "0" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1423)       strbuf_addf( &buf, "%0.12s...", ctx.query.rev );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1424)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1425)       strbuf_addf( &buf, "%0.12s...", ctx.repo.info.revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1426) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1427)     len = (int)strlen( buf.buf ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1428)     revision = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1429)     memcpy( (void *)revision, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1430)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1431) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1432)     ctx.repo.search_placeholder = (const char *)revision;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1433)     /* ctx.repo.search_placeholder = "HEAD"; */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1434)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1435) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1436) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1437) static void ctx_relative_html( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1438) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1439)   struct strbuf buf  = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1440)   char  *relative_html;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1441)   int    len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1442) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1443)   if( !strcmp( ctx.vars.page_type, ptype_repolist ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1444)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1445)     if( ctx.env.http_host && *ctx.env.http_host )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1446)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1447)       strbuf_addf( &buf, "<a class='base' href='/'>%s</a>/", ctx.env.http_host );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1448)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1449)     else if( ctx.env.server_name && *ctx.env.server_name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1450)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1451)       strbuf_addf( &buf, "<a class='base' href='/'>%s</a>/", ctx.env.server_name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1452)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1453)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1454)   else if( !strcmp( ctx.vars.page_type, ptype_repo ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1455)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1456)     if( ctx.repo.name && *ctx.repo.name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1457)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1458)       if( ctx.repo.repo_root && *ctx.repo.repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1459)         strbuf_addf( &buf, "<a class='base' href='/%s/%s/'>%s/%s</a>/", ctx.repo.repo_root, ctx.repo.name, ctx.repo.repo_root, ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1460)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1461)         strbuf_addf( &buf, "<a class='base' href='/%s/'>%s</a>/", ctx.repo.name, ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1462)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1463)     if( ctx.repo.relative_path && *ctx.repo.relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1464)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1465)       char   *p, *s, *rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1466)       int     msize;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1467)       char   *path, *href;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1468)       size_t  length;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1469) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1470)       length = strlen( ctx.repo.relative_path ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1471)       msize = (int)strlen(ctx.repo.name) + (int)strlen(ctx.repo.relative_path) + 4; /* '/' repo.name '/' relative_path '/' + '\0' */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1472) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1473)       href = (char *)__sbrk( msize );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1474)       sprintf( href, "/%s/", ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1475) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1476)       path = (char *)__sbrk( msize );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1477)       memcpy( (void *)path, (const void *)ctx.repo.relative_path, length );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1478) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1479)       p = s = path;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1480)       while( *p && !is_dir_sep( *p ) ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1481)       if( *p ) { *p = '\0'; rem = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1482)       else     { rem = p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1483)       strcat( href, s ); strcat( href, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1484) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1485)       if( !strcmp( s, "trunk" )    ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 1486)           !strcmp( s, "branches" ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 1487)           !strcmp( s, "tags" )       )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1488)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1489)         strbuf_addf( &buf, "<a class='base' href='%s'>%s</a>/", href, s );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1490) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1491)         /**********************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1492)           Searching the real name of branch or tag:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1493)          */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1494)         if( !strcmp( s, "branches" ) || !strcmp( s, "tags" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1495)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1496)           char  reminder[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1497)           char *n, *r = (char *)&reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1498) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1499)           sprintf( reminder, "%s", rem );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1500)           n = r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1501) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1502)           while( *r && !is_dir_sep( *r ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1503)             ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1504)           if( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1505)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1506)             *r = '\0'; ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1507)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1508) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1509)           if( n && *n )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1510)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1511)             int   found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1512)             char  ref[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1513)             char *b;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1514) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1515)             struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1516) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1517)             sprintf( ref, "%s", n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1518) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1519)             if( !strcmp( s, "branches" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1520)               lookup_branches_by_prefix( &names, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1521)             else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1522)               lookup_tags_by_prefix( &names, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1523) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1524)             while( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1525)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1526)               b = r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1527)               while( *r && *r != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1528)                 ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1529)               if( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1530)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1531)                 *r = '\0'; ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1532)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1533) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1534)               if( b && *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1535)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1536)                 char probe[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1537)                 sprintf( probe, "%s/%s", ref, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1538) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1539)                 found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1540)                 {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1541)                   size_t i, len = strlen( probe );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1542)                   for( i = 0; i < names->len; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1543)                   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1544)                     if( !strncmp( probe, names->name[i], len ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1545)                     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1546)                       ++found;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1547)                     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1548)                   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1549)                 }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1550)                 if( found == 1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1551)                 {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1552)                   strcat( ref, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1553)                   strcat( ref, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1554)                   break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1555)                 }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1556)                 if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1557)                 {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1558)                   strcat( ref, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1559)                   strcat( ref, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1560)                 }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1561)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1562)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1563)             cgit_ref_names_free( names );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1564) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1565)             if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1566)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1567)               strcat( href, ref ); strcat( href, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1568)               strbuf_addf( &buf, "<a class='relative' href='%s'>%s</a>/", href, ref );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1569)               rem += r - &reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1570)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1571)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1572)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1573)         /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 1574)           End of searching real name of branch or tag.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1575)          **********************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 1576)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1577)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1578)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1579)         strbuf_addf( &buf, "<a class='relative' href='%s'>%s</a>/", href, s );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1580)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1581) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1582)       s = rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1583)       while( *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1584)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1585)         p = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1586)         while( *p && !is_dir_sep( *p ) ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1587)         if( *p ) { *p = '\0'; rem = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1588)         else     { rem = p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1589)         strcat( href, s ); strcat( href, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1590)         strbuf_addf( &buf, "<a class='relative' href='%s'>%s</a>/", href, s );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1591)         s = rem;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1592)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1593) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1594)       if( ctx.repo.relative_info.kind == GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1595)         strbuf_trim_trailing_dir_sep( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1596) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1597)       ctx.repo.relative_href = (const char *)href;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1598) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1599)       (void)__sbrk( - msize ); /* free ctx memory alocated for path only */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1600)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1601)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1602) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1603)   len = (int)strlen( buf.buf ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1604)   relative_html = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1605)   memcpy( (void *)relative_html, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1606)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1607)   ctx.repo.relative_html = (const char *)relative_html;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1608) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1609) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1610) static void ctx_check_query_uri( int replace_query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1611) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1612)   /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 1613)     Nginx passed QUERY_STRING for all cgi engines by: {fastcgi, scgi, uwsgi}_params.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1614)     But PATH_INFO passed onlyfor UWSGI by uwsgi_params.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1615)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1616)   if( !ctx.env.path_info && ctx.env.request_uri && *ctx.env.request_uri )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1617)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1618)     char *path_info = NULL, *query_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1619)     char *p, *path, *query = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1620)     int   len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1621) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1622)     p = path = (char *)ctx.env.request_uri;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1623) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1624)     while( *p && *p != '?' ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1625)     if( *p == '?' ) { *p = '\0'; query = ++p; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1626) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1627)     len = strlen( path ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1628)     path_info = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1629)     memcpy( (void *)path_info, (const void *)path, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1630)     ctx.env.path_info = (const char *)path_info;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1631) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1632)     if( query && *query && replace_query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1633)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1634)       len = strlen( query ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1635)       query_string = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1636)       memcpy( (void *)query_string, (const void *)query, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1637)       ctx.env.query_string = (const char *)query_string;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1638)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1639)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1640) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1641) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1642) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1643) static void querystring_cb( const char *name, const char *value )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1644) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1645)   char *val;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1646)   int   len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1647) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1648)   if( !value )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1649)     value = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1650) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1651)   if( !strcmp( name, "rev" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1652)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1653)     len = (int)strlen( value ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1654)     val = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1655)     memcpy( (void *)val, (const void *)value, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1656)     ctx.query.revision = (const char *)val;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1657)     if( !strcasecmp( val, "HEAD" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1658)       ctx.query.rev = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1659)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1660)       ctx.query.rev = ctx.query.revision;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1661)     /*****************************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1662)       NOTE:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1663)       ====
05d292b2 (kx 2023-03-24 03:51:10 +0300 1664)         We have to call http_parse_querystring() strongly after calling
05d292b2 (kx 2023-03-24 03:51:10 +0300 1665)         cgit_rpath_info() or ctx_relative_html() because the structs
05d292b2 (kx 2023-03-24 03:51:10 +0300 1666)         ctx.repo.info and ctx.repo.relative_info should be completed before
05d292b2 (kx 2023-03-24 03:51:10 +0300 1667)         parsing special Git revision names.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1668) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1669)         Revision at start of the date '{' DATE '}' we will not support.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1670)      *****************************************************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 1671)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1672)   else if( !strcmp( name, "op" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1673)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1674)     len = (int)strlen( value ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1675)     val = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1676)     memcpy( (void *)val, (const void *)value, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1677)     ctx.query.operation = (const char *)val;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1678)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1679)   else if( !strcmp( name, "search" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1680)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1681)     len = (int)strlen( value ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1682)     val = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1683)     memcpy( (void *)val, (const void *)value, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1684)     ctx.query.search = (const char *)val;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1685)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1686) /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 1687)   else if( another parameter )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1688)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1689)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1690)   ...
05d292b2 (kx 2023-03-24 03:51:10 +0300 1691)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1692)   /* NOTE: Do not parse 'ofs=' parameter! */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1693) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1694) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1695) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1696) void cgit_parse_query( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1697) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1698)   char *path_info = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1699) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1700)   get_selfdir();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1701) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1702)   ctx_check_query_uri( 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1703) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1704)   path_info = xstrdup( ctx.env.path_info );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1705) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1706)   ctx.query.ofs = ctx_grab_int_query_param( "ofs" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1707)   http_parse_querystring( ctx.env.query_string, querystring_cb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1708)   if( !strcmp( ctx.query.rev, "0" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1709)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1710)     (void)ctx_grab_str_query_param( "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1711)     ctx.query.rev = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1712)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1713) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1714)   if( path_info )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1715)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1716)     if( !strcmp( "/", path_info ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1717)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1718)       ctx_page_size_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1719)       ctx_repo_dirs_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1720)       ctx_site_vars_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1721)       ctx_promo_vars_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1722)       ctx_header_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1723)       ctx_footer_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1724)       ctx_num_of_repos();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1725)       ctx_repolist_status_line();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1726)       ctx_repolist_menu();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1727)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1728)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1729)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1730)       struct repo *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1731) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1732)       repo = ctx_repo_name();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1733)       if( repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1734)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1735)         ctx_page_size_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1736)         ctx_repo_dirs_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1737)         ctx_site_vars_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1738)         ctx_promo_vars_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1739)         ctx_header_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1740)         ctx_footer_from_repo( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1741)         ctx.vars.page_type = ptype_repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1742) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1743)         cgit_repo_info( &ctx.repo.info, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1744)         if( ctx.repo.relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1745)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1746)           cgit_rpath_info( &ctx.repo.relative_info, ctx.repo.relative_path, (!strcmp( ctx.query.rev, "0" )) ? NULL : ctx.query.rev );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1747)           if( ctx.repo.relative_info.kind != GIT_OBJECT_TREE && ctx.repo.relative_info.kind != GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1748)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1749)             /* Query string requested invalid revision: */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1750)             memcpy( (void *)&ctx.repo.relative_info, (const void *)&ctx.repo.info, sizeof( struct cgit_info ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1751)             ctx.query.revision = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1752)             (void)ctx_grab_str_query_param( "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1753)             ctx.query.rev = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1754)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1755)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1756)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1757)           memcpy( (void *)&ctx.repo.relative_info, (const void *)&ctx.repo.info, sizeof( struct cgit_info ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1758) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1759)         cgit_repo_branches_number( &ctx.repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1760)         cgit_repo_commits_number( &ctx.repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1761)         cgit_repo_tags_number( &ctx.repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1762)         ctx_repo_status_line( &ctx.repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1763)         ctx_repo_menu( &ctx.repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1764)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1765)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1766)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1767)         ctx_page_size_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1768)         ctx_repo_dirs_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1769)         ctx_header_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1770)         ctx_footer_from_global();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1771) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1772)         ctx.page.status = 404;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1773)         ctx.page.status_message = "Page not found";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1774) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1775)         ctx.vars.title = "404";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1776)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1777)           struct strbuf  buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1778)           char  *stmsg = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1779) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1780)           /**************************************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 1781)             We slipped to the end of PATH_INFO when we were looking for a repository
05d292b2 (kx 2023-03-24 03:51:10 +0300 1782)             and now we printout the repo-root:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1783)            */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1784)           strbuf_addf( &buf, "Git Repository '%s' not found.", ctx.repo.repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1785)           stmsg = (char *)__sbrk( (int)buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1786)           memcpy( (void *)stmsg, (const void *)buf.buf, buf.len + 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1787)           strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1788)           ctx.vars.description = (const char *)stmsg;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1789)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1790)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1791) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1792)       ctx_num_of_repos();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1793)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1794) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1795)     ctx_relative_html();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1796)     ctx_search_placeholder();
05d292b2 (kx 2023-03-24 03:51:10 +0300 1797) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1798)     cgit_git_version( &ctx.vers );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1799)     cgit_nginx_version( &ctx.vers );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1800) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1801)     free( path_info );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1802)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1803) }