#ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_INTTYPES_H #include #else #include #endif #include /* offsetof(3) */ #include #include /* chmod(2) */ #include #include #include #include #include /* strdup(3) */ #include /* strcasecmp(3) */ #include /* basename(3) */ #include /* tolower(3) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Allocate memory in .bss segment: */ static struct __context mctx; /* Share address of __context: */ struct __context *pmctx = &mctx; void __mctx_init( void ) { pmctx->_cur_brk = (void *)&((pmctx->_mem)[0]); } static int __brk( void *end_d ) { void *ptr = __mem; if( (unsigned char *)end_d < (unsigned char *)ptr || (unsigned char *)end_d > (unsigned char *)ptr + CONTEXT_MEM_SIZE ) { errno = ENOMEM; return( -1 ); } /* __cur_brk = (unsigned char *)end_d; Функция __brk() лишь проверяет границы области памяти, значение __cur_brk выставляется в __sbrk() . *************************************************/ return( 0 ); } /* End of __brk() */ void * __sbrk( int incr ) { void *ptr = __cur_brk; register int rc; if( incr == 0 ) return( ptr ); rc = __brk( ptr + incr ); if( rc == -1 ) { /* errno is set into __brk() */ return( (void *)0 ); } __cur_brk = ((unsigned char *)ptr) + (int)incr; return( ptr ); } /* End of __sbrk() */ struct csvn_context ctx; const char *ptype_repolist = "repolist"; const char *ptype_repo = "repo"; void csvn_prepare_context( void ) { memset( &ctx, 0, sizeof(ctx) ); ctx.env.http_host = getenv("HTTP_HOST"); ctx.env.https = getenv("HTTPS"); ctx.env.no_http = getenv("NO_HTTP"); ctx.env.path_info = getenv("PATH_INFO"); ctx.env.query_string = getenv("QUERY_STRING"); ctx.env.request_uri = getenv("REQUEST_URI"); if( ctx.env.request_uri == NULL ) ctx.env.request_uri = "/"; ctx.env.request_scheme = getenv("REQUEST_SCHEME"); ctx.env.request_method = getenv("REQUEST_METHOD"); ctx.env.script_name = getenv("SCRIPT_NAME"); ctx.env.server_name = getenv("SERVER_NAME"); ctx.env.server_port = getenv("SERVER_PORT"); ctx.env.http_cookie = getenv("HTTP_COOKIE"); ctx.env.content_lenght = getenv("CONTENT_LENGTH") ? strtoul(getenv("CONTENT_LENGTH"), NULL, 10) : 0; ctx.env.http_root = NULL; ctx.env.authenticated = 0; ctx.query.ofs = 0; ctx.query.rev = 0; ctx.query.revision = NULL; ctx.query.operation = NULL; ctx.query.search = NULL; ctx.page.mimetype = "text/html"; ctx.page.charset = "UTF-8"; ctx.page.size = 0; ctx.page.modified = time(NULL); ctx.page.expires = ctx.page.modified + 5 * 60; ctx.page.status = 200; ctx.page.status_message = "OK"; ctx.page.header = "/.csvn/html/header.html"; ctx.page.footer = "/.csvn/html/footer.html"; ctx.vars.css = "/.csvn/css/csvn.css"; ctx.vars.owner = "Andrey V.Kosteltsev"; ctx.vars.author = "Andrey V.Kosteltsev"; ctx.vars.description = "Subversion repositories hosted at Solar System, Earth"; ctx.vars.keywords = "cSvn repositories"; ctx.vars.title = "SVN Repositories"; ctx.vars.favicon_path = "/.csvn/pixmaps/favicon"; ctx.vars.syntax_highlight_css = "_csvn.css"; ctx.vars.logo = "/.csvn/pixmaps/csvn-banner-280x280.png"; ctx.vars.logo_alt = "Example.org"; ctx.vars.logo_link = "https://example.org"; ctx.vars.home_page = "https://example.org"; ctx.vars.snapshots = "tar.xz"; ctx.vars.status_line = "Subversion Repositories"; ctx.vars.main_menu_logo = "/.csvn/pixmaps/logo/SVN-logo-white-744x744.svg"; ctx.vars.main_menu_item = "Index"; ctx.vars.left_menu_items = ""; ctx.vars.popup_menu_items = ""; ctx.vars.right_menu_items = ""; ctx.vars.copyright_notice = "By using any website materials you agree to indicate source."; ctx.vars.copyright = "© 2020 Andrey V.Kosteltsev. All Rights Reserved."; ctx.vars.page_type = ptype_repolist; ctx.vars.page_size = "200"; ctx.vars.num_of_repos = "0"; ctx.repo.name = NULL; ctx.repo.info = CSVN_INFO_INIT; ctx.repo.repo_root = NULL; ctx.repo.relative_path = NULL; ctx.repo.relative_info = CSVN_INFO_INIT; ctx.repo.relative_html = NULL; ctx.repo.relative_href = "/"; ctx.repo.search_placeholder = "repository..."; ctx.repo.trunk = "trunk"; ctx.repo.branches = "branches"; ctx.repo.tags = "tags"; ctx.repo.checkout_prefix = NULL; ctx.repo.checkout_ro_prefix = NULL; ctx.repo.nbranches = 0; ctx.repo.ntags = 0; ctx.promo.analytic_links = NULL; ctx.promo.analytic_scripts = NULL; ctx.promo.donate = 0; ctx.promo.donate_css = NULL; ctx.promo.donate_html = NULL; ctx.promo.donate_js = NULL; ctx.promo.donate_header = NULL; ctx.promo.donate_purpose = NULL; ctx.vers.subversion = NULL; ctx.vers.nginx = NULL; ctx.vers.csvn = PROGRAM_VERSION; } void csvn_prepare_template_variables( void ) { envtab_install( &strbuf_envtab, "css", ctx.vars.css, fatal_html ); envtab_install( &strbuf_envtab, "owner", ctx.vars.owner, fatal_html ); envtab_install( &strbuf_envtab, "author", ctx.vars.author, fatal_html ); envtab_install( &strbuf_envtab, "description", ctx.vars.description, fatal_html ); envtab_install( &strbuf_envtab, "keywords", ctx.vars.keywords, fatal_html ); envtab_install( &strbuf_envtab, "title", ctx.vars.title, fatal_html ); envtab_install( &strbuf_envtab, "favicon-path", ctx.vars.favicon_path, fatal_html ); envtab_install( &strbuf_envtab, "syntax-highlight-css", ctx.vars.syntax_highlight_css, fatal_html ); envtab_install( &strbuf_envtab, "logo", ctx.vars.logo, fatal_html ); envtab_install( &strbuf_envtab, "logo-alt", ctx.vars.logo_alt, fatal_html ); envtab_install( &strbuf_envtab, "logo-link", ctx.vars.logo_link, fatal_html ); envtab_install( &strbuf_envtab, "home-page", ctx.vars.home_page, fatal_html ); envtab_install( &strbuf_envtab, "snapshots", ctx.vars.snapshots, fatal_html ); envtab_install( &strbuf_envtab, "status-line", ctx.vars.status_line, fatal_html ); envtab_install( &strbuf_envtab, "main-menu-logo", ctx.vars.main_menu_logo, fatal_html ); envtab_install( &strbuf_envtab, "main-menu-item", ctx.vars.main_menu_item, fatal_html ); envtab_install( &strbuf_envtab, "left-menu-items", ctx.vars.left_menu_items, fatal_html ); envtab_install( &strbuf_envtab, "popup-menu-items", ctx.vars.popup_menu_items, fatal_html ); envtab_install( &strbuf_envtab, "right-menu-items", ctx.vars.right_menu_items, fatal_html ); envtab_install( &strbuf_envtab, "relative-html", ctx.repo.relative_html, fatal_html ); envtab_install( &strbuf_envtab, "search-placeholder", ctx.repo.search_placeholder, fatal_html ); envtab_install( &strbuf_envtab, "analytic-links", ctx.promo.analytic_links, fatal_html ); envtab_install( &strbuf_envtab, "analytic-scripts", ctx.promo.analytic_scripts, fatal_html ); envtab_install( &strbuf_envtab, "donate-css", ctx.promo.donate_css, fatal_html ); envtab_install( &strbuf_envtab, "donate-html", ctx.promo.donate_html, fatal_html ); envtab_install( &strbuf_envtab, "donate-js", ctx.promo.donate_js, fatal_html ); envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html ); envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html ); envtab_install( &strbuf_envtab, "svn-version", ctx.vers.subversion, fatal_html ); envtab_install( &strbuf_envtab, "nginx-version", ctx.vers.nginx, fatal_html ); envtab_install( &strbuf_envtab, "csvn-version", ctx.vers.csvn, fatal_html ); envtab_install( &strbuf_envtab, "copyright-notice", ctx.vars.copyright_notice, fatal_html ); envtab_install( &strbuf_envtab, "copyright", ctx.vars.copyright, fatal_html ); envtab_install( &strbuf_envtab, "page-type", ctx.vars.page_type, fatal_html ); envtab_install( &strbuf_envtab, "page-size", ctx.vars.page_size, fatal_html ); envtab_install( &strbuf_envtab, "num-of-repos", ctx.vars.num_of_repos, fatal_html ); } void csvn_release_template_variables( void ) { envtab_release( &strbuf_envtab ); } static void get_selfdir( void ) { char path[PATH_MAX]; ssize_t len; bzero( (void *)path, PATH_MAX ); len = readlink( "/proc/self/exe", &path[0], (size_t)PATH_MAX ); if( len > 0 && len < PATH_MAX ) { char *selfdir = NULL; selfdir = (char *)__sbrk( (int)len + 1 ); strcpy( selfdir, (const char *)dirname( (char *)&path[0] ) ); ctx.env.http_root = selfdir; } else fatal_html( "cannot get selfdir" ); } static size_t read_http_root_raw_file( struct strbuf *sb, const char *fname ) { char path[PATH_MAX]; int fd = -1; size_t len = 0; if( !sb || !fname || !*fname ) return len; bzero( (void *)path, PATH_MAX ); strcpy( (char *)&path[0], ctx.env.http_root ); if( *fname != '/' ) strcat( (char *)&path[0], "/" ); strcat( (char *)&path[0], fname ); if( (fd = open( (const char *)&path[0], O_RDONLY )) == -1 ) fatal_html( "Cannot open %s file: %s", fname, strerror( errno ) ); len = strbuf_read( sb, fd, 0 ); close( fd ); return len; } static size_t read_http_root_env_file( struct strbuf *sb, const char *fname ) { char path[PATH_MAX]; FILE *fp = NULL; size_t len = 0; if( !sb || !fname || !*fname ) return len; bzero( (void *)path, PATH_MAX ); strcpy( (char *)&path[0], ctx.env.http_root ); if( *fname != '/' ) strcat( (char *)&path[0], "/" ); strcat( (char *)&path[0], fname ); if( (fp = fopen( (const char *)&path[0], "r" )) == NULL ) fatal_html( "Cannot open %s file: %s", fname, strerror( errno ) ); len = strbuf_env_fread( sb, fp ); fclose( fp ); if( len > STRBUF_MAXLINE ) fatal_html( "The '%s' file is too large. No more than 8192 bytes is allowed for includes", fname ); return len; } static void read_donate_html( void ) { struct strbuf buf = STRBUF_INIT; char *html = NULL; if( !ctx.promo.donate ) return; if( !ctx.promo.donate_html || !*ctx.promo.donate_html ) return; (void)read_http_root_env_file( &buf, ctx.promo.donate_html ); html = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)html, (const void *)buf.buf, buf.len + 1 ); ctx.promo.donate_html = (const char *)html; strbuf_release( &buf ); } static char psize[4] = { 0, 0, 0, 0 }; static void ctx_page_size_from_global( void ) { struct variable f = { (unsigned char *)"page-size", { 0 }, DT_NUMERICAL }, *var = NULL; var = lookup_global( lookup_global_section( config ), &f ); if( var ) { if( var->type == DT_NUMERICAL ) { if( var->_v.val > 9 && var->_v.val < 201 ) snprintf( &psize[0], 4, "%d", var->_v.val ); else snprintf( &psize[0], 4, "%d", 200 ); ctx.vars.page_size = &psize[0]; } else { int size = 0; sscanf( (const char *)var->_v.vptr, "%d", &size ); if( size > 9 && size < 201 ) ctx.vars.page_size = (const char *)var->_v.vptr; else { snprintf( &psize[0], 4, "%d", 200 ); ctx.vars.page_size = &psize[0]; } } } } static void ctx_page_size_from_repo( struct repo *repo ) { struct variable f = { (unsigned char *)"page-size", { 0 }, DT_NUMERICAL }, *var = NULL; var = lookup( repo, &f ); if( var ) { if( var->type == DT_NUMERICAL ) { if( var->_v.val > 9 && var->_v.val < 201 ) snprintf( &psize[0], 4, "%d", var->_v.val ); else snprintf( &psize[0], 4, "%d", 200 ); ctx.vars.page_size = &psize[0]; } else { int size = 0; sscanf( (const char *)var->_v.vptr, "%d", &size ); if( size > 9 && size < 201 ) ctx.vars.page_size = (const char *)var->_v.vptr; else { snprintf( &psize[0], 4, "%d", 200 ); ctx.vars.page_size = &psize[0]; } } } } static void ctx_repo_dirs_from_global( void ) { struct variable repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH }; struct variable trunk = { (unsigned char *)"trunk", { 0 }, DT_PATH }; struct variable branches = { (unsigned char *)"branches", { 0 }, DT_PATH }; struct variable tags = { (unsigned char *)"tags", { 0 }, DT_PATH }; struct variable ro_prefix = { (unsigned char *)"checkout-prefix-readonly", { 0 }, DT_PATH }; struct variable rw_prefix = { (unsigned char *)"checkout-prefix", { 0 }, DT_PATH }; struct variable *var = NULL; var = lookup_global( lookup_global_section( config ), &repo_root ); if( var ) { ctx.repo.repo_root = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &trunk ); if( var ) { ctx.repo.trunk = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &branches ); if( var ) { ctx.repo.branches = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &tags ); if( var ) { ctx.repo.tags = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &rw_prefix ); if( var ) { ctx.repo.checkout_prefix = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &ro_prefix ); if( var ) { ctx.repo.checkout_ro_prefix = (const char *)var->_v.vptr; } } static void ctx_site_vars_from_global( void ) { struct variable css = { (unsigned char *)"css", { 0 }, DT_PATH }; struct variable owner = { (unsigned char *)"owner", { 0 }, DT_STRING }; struct variable author = { (unsigned char *)"author", { 0 }, DT_STRING }; struct variable title = { (unsigned char *)"title", { 0 }, DT_STRING }; struct variable description = { (unsigned char *)"description", { 0 }, DT_STRING }; struct variable keywords = { (unsigned char *)"keywords", { 0 }, DT_STRING }; struct variable copyright_notice = { (unsigned char *)"copyright-notice", { 0 }, DT_STRING }; struct variable copyright = { (unsigned char *)"copyright", { 0 }, DT_STRING }; struct variable favicon_path = { (unsigned char *)"favicon-path", { 0 }, DT_PATH }; struct variable logo = { (unsigned char *)"logo", { 0 }, DT_PATH }; struct variable logo_alt = { (unsigned char *)"logo-alt", { 0 }, DT_STRING }; struct variable logo_link = { (unsigned char *)"logo-link", { 0 }, DT_STRING }; struct variable home_page = { (unsigned char *)"home-page", { 0 }, DT_STRING }; struct variable snapshots = { (unsigned char *)"snapshots", { 0 }, DT_PATH }; struct variable main_menu_logo = { (unsigned char *)"main-menu-logo", { 0 }, DT_PATH }; struct variable syntax_highlight_css = { (unsigned char *)"syntax-highlight-css", { 0 }, DT_PATH }; struct variable *var = NULL; var = lookup_global( lookup_global_section( config ), &css ); if( var ) { ctx.vars.css = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &owner ); if( var ) { ctx.vars.owner = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &author ); if( var ) { ctx.vars.author = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &title ); if( var ) { ctx.vars.title = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &description ); if( var ) { ctx.vars.description = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &keywords ); if( var ) { ctx.vars.keywords = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), ©right_notice ); if( var ) { ctx.vars.copyright_notice = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), ©right ); if( var ) { ctx.vars.copyright = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &favicon_path ); if( var ) { ctx.vars.favicon_path = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &logo ); if( var ) { ctx.vars.logo = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &logo_alt ); if( var ) { ctx.vars.logo_alt = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &logo_link ); if( var ) { ctx.vars.logo_link = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &home_page ); if( var ) { ctx.vars.home_page = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &snapshots ); if( var ) { ctx.vars.snapshots = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &main_menu_logo ); if( var ) { ctx.vars.main_menu_logo = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &syntax_highlight_css ); if( var ) { ctx.vars.syntax_highlight_css = (const char *)var->_v.vptr; } } static void ctx_promo_vars_from_global( void ) { struct variable analytic_links = { (unsigned char *)"analytic-links", { 0 }, DT_PATH }; struct variable analytic_scripts = { (unsigned char *)"analytic-scripts", { 0 }, DT_PATH }; struct variable donate = { (unsigned char *)"donate", { 0 }, DT_NUMERICAL }; struct variable donate_css = { (unsigned char *)"donate-css", { 0 }, DT_PATH }; struct variable donate_html = { (unsigned char *)"donate-html", { 0 }, DT_PATH }; struct variable donate_js = { (unsigned char *)"donate-js", { 0 }, DT_PATH }; struct variable donate_header = { (unsigned char *)"donate-header", { 0 }, DT_STRING }; struct variable donate_purpose = { (unsigned char *)"donate-purpose", { 0 }, DT_STRING }; struct variable *var = NULL; var = lookup_global( lookup_global_section( config ), &analytic_links ); if( var ) { ctx.promo.analytic_links = (const char *)var->_v.vptr; if( ctx.promo.analytic_links && *ctx.promo.analytic_links ) { struct strbuf buf = STRBUF_INIT; char *links = NULL; (void)read_http_root_raw_file( &buf, ctx.promo.analytic_links ); links = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)links, (const void *)buf.buf, buf.len + 1 ); ctx.promo.analytic_links = (const char *)links; strbuf_release( &buf ); } } var = lookup_global( lookup_global_section( config ), &analytic_scripts ); if( var ) { ctx.promo.analytic_scripts = (const char *)var->_v.vptr; if( ctx.promo.analytic_scripts && *ctx.promo.analytic_scripts ) { struct strbuf buf = STRBUF_INIT; char *scripts = NULL; (void)read_http_root_raw_file( &buf, ctx.promo.analytic_scripts ); scripts = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)scripts, (const void *)buf.buf, buf.len + 1 ); ctx.promo.analytic_scripts = (const char *)scripts; strbuf_release( &buf ); } } var = lookup_global( lookup_global_section( config ), &donate ); if( var ) { if( var->type == DT_NUMERICAL ) { ctx.promo.donate = var->_v.val; if( ctx.promo.donate ) ctx.promo.donate = 1; } } if( ctx.promo.donate ) { var = lookup_global( lookup_global_section( config ), &donate_css ); if( var ) { ctx.promo.donate_css = (const char *)var->_v.vptr; if( ctx.promo.donate_css && *ctx.promo.donate_css ) { struct strbuf buf = STRBUF_INIT; char *css = NULL; strbuf_addf( &buf, "", ctx.promo.donate_css ); strbuf_trim( &buf ); css = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)css, (const void *)buf.buf, buf.len + 1 ); ctx.promo.donate_css = (const char *)css; strbuf_release( &buf ); } } var = lookup_global( lookup_global_section( config ), &donate_js ); if( var ) { ctx.promo.donate_js = (const char *)var->_v.vptr; if( ctx.promo.donate_js && *ctx.promo.donate_js ) { struct strbuf buf = STRBUF_INIT; char *js = NULL; strbuf_addf( &buf, "", ctx.promo.donate_js ); strbuf_trim( &buf ); js = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)js, (const void *)buf.buf, buf.len + 1 ); ctx.promo.donate_js = (const char *)js; strbuf_release( &buf ); } } var = lookup_global( lookup_global_section( config ), &donate_header ); if( var ) { ctx.promo.donate_header = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &donate_purpose ); if( var ) { ctx.promo.donate_purpose = (const char *)var->_v.vptr; } var = lookup_global( lookup_global_section( config ), &donate_html ); if( var ) { ctx.promo.donate_html = (const char *)var->_v.vptr; if( ctx.promo.donate_html && *ctx.promo.donate_html ) { envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html ); envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html ); read_donate_html(); envtab_release( &strbuf_envtab ); } } } } static void ctx_repo_dirs_from_repo( struct repo *repo ) { struct variable repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH }; struct variable trunk = { (unsigned char *)"trunk", { 0 }, DT_PATH }; struct variable branches = { (unsigned char *)"branches", { 0 }, DT_PATH }; struct variable tags = { (unsigned char *)"tags", { 0 }, DT_PATH }; struct variable ro_prefix = { (unsigned char *)"checkout-prefix-readonly", { 0 }, DT_PATH }; struct variable rw_prefix = { (unsigned char *)"checkout-prefix", { 0 }, DT_PATH }; struct variable *var = NULL; if( !repo ) return; var = lookup( repo, &repo_root ); if( var ) { ctx.repo.repo_root = (const char *)var->_v.vptr; } var = lookup( repo, &trunk ); if( var ) { ctx.repo.trunk = (const char *)var->_v.vptr; } var = lookup( repo, &branches ); if( var ) { ctx.repo.branches = (const char *)var->_v.vptr; } var = lookup( repo, &tags ); if( var ) { ctx.repo.tags = (const char *)var->_v.vptr; } var = lookup( repo, &rw_prefix ); if( var ) { ctx.repo.checkout_prefix = (const char *)var->_v.vptr; } var = lookup( repo, &ro_prefix ); if( var ) { ctx.repo.checkout_ro_prefix = (const char *)var->_v.vptr; } } static void ctx_site_vars_from_repo( struct repo *repo ) { struct variable css = { (unsigned char *)"css", { 0 }, DT_PATH }; struct variable owner = { (unsigned char *)"owner", { 0 }, DT_STRING }; struct variable author = { (unsigned char *)"author", { 0 }, DT_STRING }; struct variable title = { (unsigned char *)"title", { 0 }, DT_STRING }; struct variable description = { (unsigned char *)"description", { 0 }, DT_STRING }; struct variable keywords = { (unsigned char *)"keywords", { 0 }, DT_STRING }; struct variable copyright_notice = { (unsigned char *)"copyright-notice", { 0 }, DT_STRING }; struct variable copyright = { (unsigned char *)"copyright", { 0 }, DT_STRING }; struct variable favicon_path = { (unsigned char *)"favicon-path", { 0 }, DT_PATH }; struct variable logo = { (unsigned char *)"logo", { 0 }, DT_PATH }; struct variable logo_alt = { (unsigned char *)"logo-alt", { 0 }, DT_STRING }; struct variable logo_link = { (unsigned char *)"logo-link", { 0 }, DT_STRING }; struct variable home_page = { (unsigned char *)"home-page", { 0 }, DT_STRING }; struct variable snapshots = { (unsigned char *)"snapshots", { 0 }, DT_PATH }; struct variable main_menu_logo = { (unsigned char *)"main-menu-logo", { 0 }, DT_PATH }; struct variable syntax_highlight_css = { (unsigned char *)"syntax-highlight-css", { 0 }, DT_PATH }; struct variable *var = NULL; if( !repo ) return; var = lookup( repo, &css ); if( var ) { ctx.vars.css = (const char *)var->_v.vptr; } var = lookup( repo, &owner ); if( var ) { ctx.vars.owner = (const char *)var->_v.vptr; } var = lookup( repo, &author ); if( var ) { ctx.vars.author = (const char *)var->_v.vptr; } var = lookup( repo, &title ); if( var ) { ctx.vars.title = (const char *)var->_v.vptr; } var = lookup( repo, &description ); if( var ) { ctx.vars.description = (const char *)var->_v.vptr; } var = lookup( repo, &keywords ); if( var ) { ctx.vars.keywords = (const char *)var->_v.vptr; } var = lookup( repo, ©right_notice ); if( var ) { ctx.vars.copyright_notice = (const char *)var->_v.vptr; } var = lookup( repo, ©right ); if( var ) { ctx.vars.copyright = (const char *)var->_v.vptr; } var = lookup( repo, &favicon_path ); if( var ) { ctx.vars.favicon_path = (const char *)var->_v.vptr; } var = lookup( repo, &logo ); if( var ) { ctx.vars.logo = (const char *)var->_v.vptr; } var = lookup( repo, &logo_alt ); if( var ) { ctx.vars.logo_alt = (const char *)var->_v.vptr; } var = lookup( repo, &logo_link ); if( var ) { ctx.vars.logo_link = (const char *)var->_v.vptr; } var = lookup( repo, &home_page ); if( var ) { ctx.vars.home_page = (const char *)var->_v.vptr; } var = lookup( repo, &snapshots ); if( var ) { ctx.vars.snapshots = (const char *)var->_v.vptr; } var = lookup( repo, &main_menu_logo ); if( var ) { ctx.vars.main_menu_logo = (const char *)var->_v.vptr; } var = lookup( repo, &syntax_highlight_css ); if( var ) { ctx.vars.syntax_highlight_css = (const char *)var->_v.vptr; } } static void ctx_promo_vars_from_repo( struct repo *repo ) { struct variable analytic_links = { (unsigned char *)"analytic-links", { 0 }, DT_PATH }; struct variable analytic_scripts = { (unsigned char *)"analytic-scripts", { 0 }, DT_PATH }; struct variable donate = { (unsigned char *)"donate", { 0 }, DT_NUMERICAL }; struct variable donate_css = { (unsigned char *)"donate-css", { 0 }, DT_PATH }; struct variable donate_html = { (unsigned char *)"donate-html", { 0 }, DT_PATH }; struct variable donate_js = { (unsigned char *)"donate-js", { 0 }, DT_PATH }; struct variable donate_header = { (unsigned char *)"donate-header", { 0 }, DT_STRING }; struct variable donate_purpose = { (unsigned char *)"donate-purpose", { 0 }, DT_STRING }; struct variable *var = NULL; /* Analytics reads from global section only: */ var = lookup_global( lookup_global_section( config ), &analytic_links ); if( var ) { ctx.promo.analytic_links = (const char *)var->_v.vptr; if( ctx.promo.analytic_links && *ctx.promo.analytic_links ) { struct strbuf buf = STRBUF_INIT; char *links = NULL; (void)read_http_root_raw_file( &buf, ctx.promo.analytic_links ); links = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)links, (const void *)buf.buf, buf.len + 1 ); ctx.promo.analytic_links = (const char *)links; strbuf_release( &buf ); } } var = lookup_global( lookup_global_section( config ), &analytic_scripts ); if( var ) { ctx.promo.analytic_scripts = (const char *)var->_v.vptr; if( ctx.promo.analytic_scripts && *ctx.promo.analytic_scripts ) { struct strbuf buf = STRBUF_INIT; char *scripts = NULL; (void)read_http_root_raw_file( &buf, ctx.promo.analytic_scripts ); scripts = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)scripts, (const void *)buf.buf, buf.len + 1 ); ctx.promo.analytic_scripts = (const char *)scripts; strbuf_release( &buf ); } } var = lookup( repo, &donate ); if( var ) { if( var->type == DT_NUMERICAL ) { ctx.promo.donate = var->_v.val; if( ctx.promo.donate ) ctx.promo.donate = 1; } } if( ctx.promo.donate ) { var = lookup( repo, &donate_css ); if( var ) { ctx.promo.donate_css = (const char *)var->_v.vptr; if( ctx.promo.donate_css && *ctx.promo.donate_css ) { struct strbuf buf = STRBUF_INIT; char *css = NULL; strbuf_addf( &buf, "", ctx.promo.donate_css ); strbuf_trim( &buf ); css = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)css, (const void *)buf.buf, buf.len + 1 ); ctx.promo.donate_css = (const char *)css; strbuf_release( &buf ); } } var = lookup( repo, &donate_js ); if( var ) { ctx.promo.donate_js = (const char *)var->_v.vptr; if( ctx.promo.donate_js && *ctx.promo.donate_js ) { struct strbuf buf = STRBUF_INIT; char *js = NULL; strbuf_addf( &buf, "", ctx.promo.donate_js ); strbuf_trim( &buf ); js = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)js, (const void *)buf.buf, buf.len + 1 ); ctx.promo.donate_js = (const char *)js; strbuf_release( &buf ); } } var = lookup( repo, &donate_header ); if( var ) { ctx.promo.donate_header = (const char *)var->_v.vptr; } var = lookup( repo, &donate_purpose ); if( var ) { ctx.promo.donate_purpose = (const char *)var->_v.vptr; } var = lookup( repo, &donate_html ); if( var ) { ctx.promo.donate_html = (const char *)var->_v.vptr; if( ctx.promo.donate_html && *ctx.promo.donate_html ) { envtab_install( &strbuf_envtab, "donate-header", ctx.promo.donate_header, fatal_html ); envtab_install( &strbuf_envtab, "donate-purpose", ctx.promo.donate_purpose, fatal_html ); read_donate_html(); envtab_release( &strbuf_envtab ); } } } } static char nrepos[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static void ctx_num_of_repos( void ) { int32_t num = repolist_length( config ); num &= 0x7fffffff; if( num > 0 ) { snprintf( &nrepos[0], 11, "%d", num ); ctx.vars.num_of_repos = &nrepos[0]; } } static void ctx_repolist_status_line( void ) { struct strbuf buf = STRBUF_INIT; char *nrepos_string = NULL; char *status_line = NULL; int32_t num = 0; sscanf( ctx.vars.num_of_repos, "%d", &num ); strbuf_addf( &buf, Q_("%d Subversion Repository", "%d Subversion Repositories", num), num ); nrepos_string = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)nrepos_string, (const void *)buf.buf, buf.len + 1 ); strbuf_release( &buf ); buf.alloc = 0, buf.len = 0, buf.fatal = strbuf_fatal, buf.buf = strbuf_slopbuf; strbuf_addf( &buf, " %s\n", nrepos_string ); if( ctx.promo.donate ) strbuf_addf( &buf, "  | Donate\n" ); status_line = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)status_line, (const void *)buf.buf, buf.len + 1 ); strbuf_release( &buf ); ctx.vars.status_line = (const char *)status_line; } static void ctx_repo_status_line( struct csvn_repository *rctx ) { struct strbuf buf = STRBUF_INIT; struct strbuf commits = STRBUF_INIT; struct strbuf branches = STRBUF_INIT; struct strbuf tags = STRBUF_INIT; char *status_line = NULL; if( !rctx ) return; strbuf_addf( &commits, Q_("%d Commit", "%d Commits", rctx->info.revision), rctx->info.revision ); strbuf_addf( &branches, Q_("%d Branch", "%d Branches", rctx->nbranches), rctx->nbranches ); strbuf_addf( &tags, Q_("%d Tag", "%d Tags", rctx->ntags), rctx->ntags ); strbuf_addf( &buf, " %s  \n", commits.buf ); strbuf_addf( &buf, " %s  \n", branches.buf ); strbuf_addf( &buf, " %s\n", tags.buf ); if( ctx.promo.donate ) strbuf_addf( &buf, "  | Donate\n" ); strbuf_release( &commits ); strbuf_release( &branches ); strbuf_release( &tags ); status_line = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)status_line, (const void *)buf.buf, buf.len + 1 ); strbuf_release( &buf ); ctx.vars.status_line = (const char *)status_line; } static void ctx_repolist_menu( void ) { struct strbuf mmenu = STRBUF_INIT; struct strbuf popup = STRBUF_INIT; struct strbuf right = STRBUF_INIT; char *main_menu = NULL; char *popup_menu = NULL; char *right_menu = NULL; strbuf_addf( &mmenu, "Index\n" ); strbuf_addf( &popup, "\n", ctx.vars.home_page ); strbuf_addf( &right, "\n", ctx.vars.home_page ); main_menu = (char *)__sbrk( (int)mmenu.len + 1 ); memcpy( (void *)main_menu, (const void *)mmenu.buf, mmenu.len + 1 ); strbuf_release( &mmenu ); ctx.vars.main_menu_item = (const char *)main_menu; popup_menu = (char *)__sbrk( (int)popup.len + 1 ); memcpy( (void *)popup_menu, (const void *)popup.buf, popup.len + 1 ); strbuf_release( &popup ); ctx.vars.popup_menu_items = (const char *)popup_menu; right_menu = (char *)__sbrk( (int)right.len + 1 ); memcpy( (void *)right_menu, (const void *)right.buf, right.len + 1 ); strbuf_release( &right ); ctx.vars.right_menu_items = (const char *)right_menu; } static void ctx_repo_menu( struct csvn_repository *rctx ) { struct strbuf mmenu = STRBUF_INIT; struct strbuf left = STRBUF_INIT; struct strbuf popup = STRBUF_INIT; struct strbuf right = STRBUF_INIT; char *main_menu = NULL; char *left_menu = NULL; char *popup_menu = NULL; char *right_menu = NULL; if( !rctx ) return; strbuf_addf( &mmenu, "Index\n" ); strbuf_addf( &left, "\n", rctx->name, rctx->trunk ); strbuf_addf( &left, "\n", rctx->name, rctx->branches ); strbuf_addf( &left, "\n", rctx->name, rctx->tags ); strbuf_addf( &popup, "\n", rctx->name, rctx->trunk ); strbuf_addf( &popup, "\n", rctx->name, rctx->branches ); strbuf_addf( &popup, "\n", rctx->name, rctx->tags ); strbuf_addf( &popup, "
\n" ); strbuf_addf( &popup, "\n", ctx.vars.home_page ); strbuf_addf( &right, "\n", ctx.vars.home_page ); main_menu = (char *)__sbrk( (int)mmenu.len + 1 ); memcpy( (void *)main_menu, (const void *)mmenu.buf, mmenu.len + 1 ); strbuf_release( &mmenu ); ctx.vars.main_menu_item = (const char *)main_menu; left_menu = (char *)__sbrk( (int)left.len + 1 ); memcpy( (void *)left_menu, (const void *)left.buf, left.len + 1 ); strbuf_release( &left ); ctx.vars.left_menu_items = (const char *)left_menu; popup_menu = (char *)__sbrk( (int)popup.len + 1 ); memcpy( (void *)popup_menu, (const void *)popup.buf, popup.len + 1 ); strbuf_release( &popup ); ctx.vars.popup_menu_items = (const char *)popup_menu; right_menu = (char *)__sbrk( (int)right.len + 1 ); memcpy( (void *)right_menu, (const void *)right.buf, right.len + 1 ); strbuf_release( &right ); ctx.vars.right_menu_items = (const char *)right_menu; } static void ctx_header_from_global( void ) { struct strbuf buf = STRBUF_INIT; struct variable head = { (unsigned char *)"header", { 0 }, DT_PATH }, *var = NULL; char *pheader = NULL; var = lookup_global( lookup_global_section( config ), &head ); strbuf_selfdir( &buf ); if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); } else { strbuf_addf( &buf, "%s", ctx.page.header ); } pheader = (char *)__sbrk( (int)buf.len + 1 ); sprintf( pheader, "%s", buf.buf ); strbuf_release( &buf ); ctx.page.header = (const char *)pheader; } static void ctx_header_from_repo( struct repo *repo ) { struct strbuf buf = STRBUF_INIT; struct variable head = { (unsigned char *)"header", { 0 }, DT_PATH }, *var = NULL; char *pheader = NULL; var = lookup( repo, &head ); strbuf_selfdir( &buf ); if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); } else { strbuf_addf( &buf, "%s", ctx.page.header ); } pheader = (char *)__sbrk( (int)buf.len + 1 ); sprintf( pheader, "%s", buf.buf ); strbuf_release( &buf ); ctx.page.header = (const char *)pheader; } static void ctx_footer_from_global( void ) { struct strbuf buf = STRBUF_INIT; struct variable foot = { (unsigned char *)"footer", { 0 }, DT_PATH }, *var = NULL; char *pfooter = NULL; var = lookup_global( lookup_global_section( config ), &foot ); strbuf_selfdir( &buf ); if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); } else { strbuf_addf( &buf, "%s", ctx.page.footer ); } pfooter = (char *)__sbrk( (int)buf.len + 1 ); sprintf( pfooter, "%s", buf.buf ); strbuf_release( &buf ); ctx.page.footer = (const char *)pfooter; } static void ctx_footer_from_repo( struct repo *repo ) { struct strbuf buf = STRBUF_INIT; struct variable foot = { (unsigned char *)"footer", { 0 }, DT_PATH }, *var = NULL; char *pfooter = NULL; var = lookup( repo, &foot ); strbuf_selfdir( &buf ); if( var ) { strbuf_addf( &buf, "%s", (const char *)var->_v.vptr ); } else { strbuf_addf( &buf, "%s", ctx.page.footer ); } pfooter = (char *)__sbrk( (int)buf.len + 1 ); sprintf( pfooter, "%s", buf.buf ); strbuf_release( &buf ); ctx.page.footer = (const char *)pfooter; } static char name[PATH_MAX] = { 0 }; static char repo_root[PATH_MAX] = { 0 }; static char relative_path[PATH_MAX] = { 0 }; static char try[PATH_MAX] = { 0 }; static struct repo *ctx_repo_name( void ) { struct repo *repo = NULL; char *s, *p = NULL, *n, *path, *path_info; int len = 0; if( strcmp( "/", ctx.env.path_info ) ) { path_info = xstrdup( ctx.env.path_info ); s = path_info; while( *s ) { while( *s && is_dir_sep( *s ) ) ++s; n = p = s; while( *p && !is_dir_sep( *p ) ) ++p; if( *p ) { *p = '\0'; s = ++p; /**************************************************************** The repo name can be given as a relative path in the git-root: */ if( repo_root[0] ) { sprintf( try, "%s", repo_root ); strcat( try, "/" ); strcat( try, n ); } else { sprintf( try, "%s", n ); } if( (repo = lookup_repo( config, try )) ) { sprintf( name, "%s", try ); { char *rr = strstr( repo_root, try ); if( rr ) *rr = '\0'; else repo_root[0] = '\0'; } break; } else { if( repo_root[0] ) strcat( repo_root, "/" ); strcat( repo_root, n ); } } else s = p; } ctx.repo.name = (const char *)&name[0]; ctx.repo.repo_root = (const char *)&repo_root[0]; path = p; if( *path ) { len = (int)strlen( path ); if( path[len-1] =='/' ) { path[len-1] = '\0'; --len; } len += 1; sprintf( relative_path, "%s", path ); ctx.repo.relative_path = (const char *)&relative_path[0]; } free( path_info ); } return repo; } /************************************************************* Get integer value of query parameter 'name' and remove this parameter 'name=..' from ctx.env.query_string. */ int ctx_grab_int_query_param( const char *name ) { char *pofs = NULL, *query_string, *s = (char *)ctx.env.query_string; int ret = 0, len = 0; if( !name || !*name ) return ret; if( s && *s && (pofs = strstr( s, name )) ) { char *rem, *p, *val = NULL; struct strbuf buf = STRBUF_INIT; p = pofs; /* move to end of 'ofs=val' declaration: */ while( *p && *p != '&' && *p != '=' ) ++p; if( *p == '=' ) { val = ++p; while( *p && *p != '&' ) ++p; } if( *p ) { *p = '\0'; rem = ++p; } else { rem = p; if( s < pofs && (pofs[-1] == '&' || pofs[-1] == '=') ) --pofs; } /* fill buffer: */ while( s < pofs ) { strbuf_addch( &buf, *s ); ++s; } s = rem; while( *s ) { strbuf_addch( &buf, *s ); ++s; } strbuf_addch( &buf, '\0' ); /* get value: */ if( val && *val ) { ret = atoi( val ); } else { ret = 0; } len = (int)buf.len; query_string = (char *)__sbrk( len ); memcpy( (void *)query_string, (const void *)buf.buf, (size_t)len ); strbuf_release( &buf ); ctx.env.query_string = (const char *)query_string; } return ret; } /*************************************************************** Rmove parametr with specified 'name=...' fom query string and return modified query string allocated in context _mem[]. */ const char *ctx_remove_query_param( const char *query_string, const char *name ) { char *pofs = NULL, *query = NULL, *s = (char *)query_string; int len = 0; if( !name || !*name ) return (const char *)query; if( s && *s && (pofs = strstr( s, name )) ) { char *rem, *p; struct strbuf buf = STRBUF_INIT; p = pofs; /* move to end of 'ofs=val' declaration: */ while( *p && *p != '&' && *p != '=' ) ++p; if( *p == '=' ) { while( *p && *p != '&' ) ++p; } if( *p ) { *p = '\0'; rem = ++p; } else { rem = p; if( s < pofs && (pofs[-1] == '&' || pofs[-1] == '=') ) --pofs; } /* fill buffer: */ while( s < pofs ) { strbuf_addch( &buf, *s ); ++s; } s = rem; while( *s ) { strbuf_addch( &buf, *s ); ++s; } strbuf_addch( &buf, '\0' ); len = (int)buf.len; query = (char *)__sbrk( len ); memcpy( (void *)query, (const void *)buf.buf, (size_t)len ); strbuf_release( &buf ); return (const char *)query; } return (const char *)query; } static void ctx_search_placeholder( void ) { struct strbuf buf = STRBUF_INIT; char *revision; int len; if( !strcmp( ctx.vars.page_type, ptype_repo ) ) { if( ctx.query.rev ) strbuf_addf( &buf, "%d", ctx.query.rev ); else strbuf_addf( &buf, "%d", ctx.repo.info.revision ); len = (int)strlen( buf.buf ) + 1; revision = (char *)__sbrk( len ); memcpy( (void *)revision, (const void *)buf.buf, (size_t)len ); strbuf_release( &buf ); ctx.repo.search_placeholder = (const char *)revision; /* ctx.repo.search_placeholder = "HEAD"; */ } } static void ctx_relative_html( void ) { struct strbuf buf = STRBUF_INIT; char *relative_html; int len; if( !strcmp( ctx.vars.page_type, ptype_repolist ) ) { if( ctx.env.http_host && *ctx.env.http_host ) { strbuf_addf( &buf, "%s/", ctx.env.http_host ); } else if( ctx.env.server_name && *ctx.env.server_name ) { strbuf_addf( &buf, "%s/", ctx.env.server_name ); } } else if( !strcmp( ctx.vars.page_type, ptype_repo ) ) { if( ctx.repo.name && *ctx.repo.name && ctx.repo.info.kind != KIND_UNKNOWN ) { if( ctx.repo.repo_root && *ctx.repo.repo_root ) strbuf_addf( &buf, "%s/%s/", ctx.repo.repo_root, ctx.repo.name, ctx.repo.repo_root, ctx.repo.name ); else strbuf_addf( &buf, "%s/", ctx.repo.name, ctx.repo.name ); } if( ctx.repo.relative_path && *ctx.repo.relative_path && ctx.repo.relative_info.kind != KIND_UNKNOWN ) { char *p, *s, *rem; int msize; char *path, *href; size_t length; length = strlen( ctx.repo.relative_path ) + 1; msize = (int)strlen(ctx.repo.name) + (int)strlen(ctx.repo.relative_path) + 4; /* '/' repo.name '/' relative_path '/' + '\0' */ href = (char *)__sbrk( msize ); sprintf( href, "/%s/", ctx.repo.name ); path = (char *)__sbrk( msize ); memcpy( (void *)path, (const void *)ctx.repo.relative_path, length ); p = s = path; while( *p && !is_dir_sep( *p ) ) ++p; if( *p ) { *p = '\0'; rem = ++p; } else { rem = p; } strcat( href, s ); strcat( href, "/" ); if( !strcmp( s, ctx.repo.trunk ) || !strcmp( s, ctx.repo.branches ) || !strcmp( s, ctx.repo.tags ) ) { strbuf_addf( &buf, "%s/", href, s ); } else { strbuf_addf( &buf, "%s/", href, s ); } s = rem; while( *s ) { p = s; while( *p && !is_dir_sep( *p ) ) ++p; if( *p ) { *p = '\0'; rem = ++p; } else { rem = p; } strcat( href, s ); strcat( href, "/" ); strbuf_addf( &buf, "%s/", href, s ); s = rem; } if( ctx.repo.relative_info.kind == KIND_FILE ) strbuf_trim_trailing_dir_sep( &buf ); ctx.repo.relative_href = (const char *)href; (void)__sbrk( - msize ); /* free ctx memory alocated for path only */ } } len = (int)strlen( buf.buf ) + 1; relative_html = (char *)__sbrk( len ); memcpy( (void *)relative_html, (const void *)buf.buf, (size_t)len ); strbuf_release( &buf ); ctx.repo.relative_html = (const char *)relative_html; } static void ctx_check_query_uri( int replace_query_string ) { /* Nginx passed QUERY_STRING for all cgi engines by: {fastcgi, scgi, uwsgi}_params. But PATH_INFO passed onlyfor UWSGI by uwsgi_params. */ if( !ctx.env.path_info && ctx.env.request_uri && *ctx.env.request_uri ) { char *path_info = NULL, *query_string = NULL; char *p, *path, *query = NULL; int len; p = path = (char *)ctx.env.request_uri; while( *p && *p != '?' ) ++p; if( *p == '?' ) { *p = '\0'; query = ++p; } len = strlen( path ) + 1; path_info = (char *)__sbrk( len ); memcpy( (void *)path_info, (const void *)path, (size_t)len ); ctx.env.path_info = (const char *)path_info; if( query && *query && replace_query_string ) { len = strlen( query ) + 1; query_string = (char *)__sbrk( len ); memcpy( (void *)query_string, (const void *)query, (size_t)len ); ctx.env.query_string = (const char *)query_string; } } } static void querystring_cb( const char *name, const char *value ) { char *val; int len; if( !value ) value = ""; if( !strcmp( name, "rev" ) ) { len = (int)strlen( value ) + 1; val = (char *)__sbrk( len ); memcpy( (void *)val, (const void *)value, (size_t)len ); ctx.query.revision = (const char *)val; if( !strcasecmp( val, "HEAD" ) ) ctx.query.rev = 0; else ctx.query.rev = atoi( val ); /***************************************************************************** NOTE: ==== If we will parse another string values of SVN revision such as 'BASE', 'COMMITED', 'PREV' then we have to call http_parse_querystring() strongly after calling csvn_rpath_info() or ctx_relative_html() because the structs ctx.repo.info and ctx.repo.relative_info should be completed before parsing special SVN revision names. Revision at start of the date '{' DATE '}' we will not support. *****************************************************************************/ } else if( !strcmp( name, "op" ) ) { len = (int)strlen( value ) + 1; val = (char *)__sbrk( len ); memcpy( (void *)val, (const void *)value, (size_t)len ); ctx.query.operation = (const char *)val; } else if( !strcmp( name, "search" ) ) { len = (int)strlen( value ) + 1; val = (char *)__sbrk( len ); memcpy( (void *)val, (const void *)value, (size_t)len ); ctx.query.search = (const char *)val; } /* else if( another parameter ) { } ... */ /* NOTE: Do not parse 'ofs=' parameter! */ } void csvn_parse_query( void ) { char *path_info = NULL; get_selfdir(); ctx_check_query_uri( 1 ); path_info = xstrdup( ctx.env.path_info ); ctx.query.ofs = ctx_grab_int_query_param( "ofs" ); if( path_info ) { if( !strcmp( "/", path_info ) ) { ctx_page_size_from_global(); ctx_repo_dirs_from_global(); ctx_site_vars_from_global(); ctx_promo_vars_from_global(); ctx_header_from_global(); ctx_footer_from_global(); ctx_num_of_repos(); ctx_repolist_status_line(); ctx_repolist_menu(); } else { struct repo *repo = NULL; repo = ctx_repo_name(); if( repo ) { ctx_page_size_from_repo( repo ); ctx_repo_dirs_from_repo( repo ); ctx_site_vars_from_repo( repo ); ctx_promo_vars_from_repo( repo ); ctx_header_from_repo( repo ); ctx_footer_from_repo( repo ); ctx.vars.page_type = ptype_repo; csvn_repo_info( &ctx.repo.info, 0 ); if( ctx.repo.relative_path ) csvn_rpath_info( &ctx.repo.relative_info, ctx.repo.relative_path, 0 ); else memcpy( (void *)&ctx.repo.relative_info, (const void *)&ctx.repo.info, sizeof( struct csvn_info ) ); csvn_repo_branches_number( &ctx.repo ); csvn_repo_tags_number( &ctx.repo ); ctx_repo_status_line( &ctx.repo ); ctx_repo_menu( &ctx.repo ); } else { ctx_page_size_from_global(); ctx_repo_dirs_from_global(); ctx_header_from_global(); ctx_footer_from_global(); ctx.page.status = 404; ctx.page.status_message = "Page not found"; ctx.vars.title = "404"; { struct strbuf buf = STRBUF_INIT; char *stmsg = NULL; /************************************************************************** We slipped to the end of PATH_INFO when we were looking for a repository and now we printout the repo-root: */ strbuf_addf( &buf, "Subversion Repository '%s' not found.", ctx.repo.repo_root ); stmsg = (char *)__sbrk( (int)buf.len + 1 ); memcpy( (void *)stmsg, (const void *)buf.buf, buf.len + 1 ); strbuf_release( &buf ); ctx.vars.description = (const char *)stmsg; } } ctx_num_of_repos(); } ctx_relative_html(); http_parse_querystring( ctx.env.query_string, querystring_cb ); if( ctx.query.rev < 1 ) { (void)ctx_grab_int_query_param( "rev" ); ctx.query.rev = 0; } ctx_search_placeholder(); csvn_svn_version( &ctx.vers ); csvn_nginx_version( &ctx.vers ); free( path_info ); } }