cSvn-UI for SVN Repositories

cGit-UI – is a web interface for Subversion (SVN) Repositories. cSvn CGI script is writen in C and therefore it's fast enough

6 Commits   0 Branches   2 Tags
bfc1508d (kx 2023-03-24 03:55:33 +0300   1) 
bfc1508d (kx 2023-03-24 03:55:33 +0300   2) #ifdef HAVE_CONFIG_H
bfc1508d (kx 2023-03-24 03:55:33 +0300   3) #include <config.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   4) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300   5) 
bfc1508d (kx 2023-03-24 03:55:33 +0300   6) #include <stdlib.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   7) #include <stdio.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   8) #include <sys/sysinfo.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   9) #include <sys/types.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  10) #ifdef HAVE_INTTYPES_H
bfc1508d (kx 2023-03-24 03:55:33 +0300  11) #include <inttypes.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  12) #else
bfc1508d (kx 2023-03-24 03:55:33 +0300  13) #include <stdint.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  14) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300  15) #include <stddef.h>   /* offsetof(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300  16) #include <dirent.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  17) #include <sys/stat.h> /* chmod(2)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300  18) #include <sys/file.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  19) #include <sys/mman.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  20) #include <fcntl.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  21) #include <limits.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  22) #include <string.h>   /* strdup(3)   */
bfc1508d (kx 2023-03-24 03:55:33 +0300  23) #include <libgen.h>   /* basename(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300  24) #include <ctype.h>    /* tolower(3)  */
bfc1508d (kx 2023-03-24 03:55:33 +0300  25) #include <errno.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  26) #include <time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  27) #include <sys/time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  28) #include <pwd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  29) #include <grp.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  30) #include <stdarg.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  31) #include <locale.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  32) #include <unistd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  33) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  34) #include <md4c.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  35) #include <md4c-html.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  36) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  37) #include <nls.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  38) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  39) #include <defs.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  40) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  41) #include <fatal.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  42) #include <http.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  43) #include <html.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  44) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  45) #include <dlist.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  46) #include <strbuf.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  47) #include <repolist.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  48) #include <wrapper.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  49) #include <system.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  50) #include <date.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  51) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  52) #include <ctx.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  53) #include <ui-shared.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  54) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  55) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  56) static int csvn_file_last_changed_revision( const char *relative_path )
bfc1508d (kx 2023-03-24 03:55:33 +0300  57) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  58)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300  59)   const char *name      = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300  60)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300  61)   int ret = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300  62) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  63)   if( !relative_path ) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300  64) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  65)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300  66)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300  67)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300  68)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300  69)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300  70)     pid_t p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300  71)     int   rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300  72) 
c7693c71 (kx 2023-04-12 19:21:06 +0300  73)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300  74)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300  75)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300  76)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300  77)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300  78)     strcat( (char *)&repo_path[0], name );
c7693c71 (kx 2023-04-12 19:21:06 +0300  79) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  80)     snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300  81)               "svn info --show-item last-changed-revision --no-newline %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300  82)               co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300  83)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300  84)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300  85)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300  86)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300  87)       return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300  88)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300  89)     strbuf_trim( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300  90)     ret = atoi( buf.buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300  91)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300  92)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300  93)   return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300  94) }
bfc1508d (kx 2023-03-24 03:55:33 +0300  95) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  96) static void csvn_print_file_links( struct strbuf *sb, const char *relative_path, int revision, int top )
bfc1508d (kx 2023-03-24 03:55:33 +0300  97) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  98)   const char *query_string = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  99)   const char *place = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 100)   char rev[80] = { 0 };
bfc1508d (kx 2023-03-24 03:55:33 +0300 101) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 102)   if( !sb || !relative_path ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 103) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 104)   if( top )
bfc1508d (kx 2023-03-24 03:55:33 +0300 105)     place = "top";
bfc1508d (kx 2023-03-24 03:55:33 +0300 106)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 107)     place = "bottom";
bfc1508d (kx 2023-03-24 03:55:33 +0300 108) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 109)   strbuf_addf( sb, "<div class=\"%s file-links-menu\">\n", place );
bfc1508d (kx 2023-03-24 03:55:33 +0300 110)   strbuf_addf( sb, "  <div class=\"right links-menu\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 111) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 112)   query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 113)   query_string = ctx_remove_query_param( query_string, "op" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 114) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 115)   if( !revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 116)     revision = csvn_file_last_changed_revision( relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 117)   sprintf( (char *)&rev[0], "%d", revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 118) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 119)   if( query_string && *query_string )
bfc1508d (kx 2023-03-24 03:55:33 +0300 120)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 121)     if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 122)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 123)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-scroll\"></span><a href=\"/%s/%s/%s/?op=log&rev=%s&%s\">log</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 124)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-diff\"></span><a href=\"/%s/%s/%s/?op=diff&rev=%s&%s\">diff</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 125)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-blame\"></span><a href=\"/%s/%s/%s/?op=blame&rev=%s&%s\">blame</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 126)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 127)     else
c7693c71 (kx 2023-04-12 19:21:06 +0300 128)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 129)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-scroll\"></span><a href=\"/%s/%s/?op=log&rev=%s&%s\">log</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 130)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-diff\"></span><a href=\"/%s/%s/?op=diff&rev=%s&%s\">diff</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 131)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-blame\"></span><a href=\"/%s/%s/?op=blame&rev=%s&%s\">blame</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0], query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 132)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 133)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 134)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 135)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 136)     if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 137)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 138)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-scroll\"></span><a href=\"/%s/%s/%s/?op=log&rev=%s\">log</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 139)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-diff\"></span><a href=\"/%s/%s/%s/?op=diff&rev=%s\">diff</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 140)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-blame\"></span><a href=\"/%s/%s/%s/?op=blame&rev=%s\">blame</a></div>\n", ctx.repo.repo_root, ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 141)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 142)     else
c7693c71 (kx 2023-04-12 19:21:06 +0300 143)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 144)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-scroll\"></span><a href=\"/%s/%s/?op=log&rev=%s\">log</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 145)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-diff\"></span><a href=\"/%s/%s/?op=diff&rev=%s\">diff</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 146)       strbuf_addf( sb, "    <div class=\"item\"><span class=\"icon las la-blame\"></span><a href=\"/%s/%s/?op=blame&rev=%s\">blame</a></div>\n", ctx.repo.name, relative_path, (char *)&rev[0] );
c7693c71 (kx 2023-04-12 19:21:06 +0300 147)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 148)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 149) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 150)   strbuf_addf( sb, "  </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 151)   strbuf_addf( sb, "</div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 152) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 153) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 154) static void process_markdown_output( const MD_CHAR *text, MD_SIZE size, void *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 155) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 156)   strbuf_add( (struct strbuf *)sb, (const void *)text, (size_t)size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 157) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 158) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 159) static int csvn_write_markdown_content( struct strbuf *sb, const struct strbuf *input )
bfc1508d (kx 2023-03-24 03:55:33 +0300 160) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 161)   unsigned parser_flags   = MD_DIALECT_GITHUB; /* | MD_DIALECT_COMMONMARK */
bfc1508d (kx 2023-03-24 03:55:33 +0300 162)   unsigned renderer_flags = MD_FLAG_WIKILINKS; /* | MD_HTML_FLAG_DEBUG    */
bfc1508d (kx 2023-03-24 03:55:33 +0300 163) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 164)   /*********************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 165)     md_html() returns 0 on success:
bfc1508d (kx 2023-03-24 03:55:33 +0300 166)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300 167)   return md_html( input->buf, input->len, process_markdown_output,
bfc1508d (kx 2023-03-24 03:55:33 +0300 168)                   (void *)sb, parser_flags, renderer_flags );
bfc1508d (kx 2023-03-24 03:55:33 +0300 169) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 170) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 171) static void csvn_print_markdown_file( struct strbuf *sb, const char *relative_path, int revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 172) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 173)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300 174)   const char *name      = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300 175)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300 176) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 177)   if( !sb || !relative_path ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 178) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 179)   csvn_print_file_links( sb, relative_path, revision, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 180) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 181)   strbuf_addstr( sb, "<div class='markdown-content'>" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 182) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 183)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 184)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 185)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300 186)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 187)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 188)     pid_t p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 189)     int   rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 190) 
c7693c71 (kx 2023-04-12 19:21:06 +0300 191)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 192)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 193)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300 194)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300 195)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 196)     strcat( (char *)&repo_path[0], name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 197) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 198)     if( revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 199)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 200)                 "svn cat --revision %d %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 201)                 revision, co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 202)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 203)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 204)                 "svn cat %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 205)                 co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 206)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 207)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 208)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 209)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 210)       strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 211)       return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 212)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 213) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 214)     (void)csvn_write_markdown_content( sb, (const struct strbuf *)&buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 215) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 216)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 217)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 218) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 219)   strbuf_addstr( sb, "\n</div> <!-- End of Markdown Content -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 220) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 221)   csvn_print_file_links( sb, relative_path, revision, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 222) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 223)   return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 224) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 225) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 226) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 227) static void csvn_print_file( struct strbuf *sb, const char *relative_path, int revision, const char *lang )
bfc1508d (kx 2023-03-24 03:55:33 +0300 228) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 229)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300 230)   const char *name      = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300 231)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300 232) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 233)   if( !sb || !relative_path ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 234) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 235)   csvn_print_file_links( sb, relative_path, revision, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 236) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 237)   if( lang )
bfc1508d (kx 2023-03-24 03:55:33 +0300 238)     strbuf_addf( sb, "<pre><code class='language-%s'>", lang );
bfc1508d (kx 2023-03-24 03:55:33 +0300 239)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 240)     strbuf_addstr( sb, "<pre><code class='highlight'>" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 241) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 242)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 243)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 244)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300 245)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 246)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 247)     char  *raw = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 248)     pid_t  p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 249)     int    rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 250) 
c7693c71 (kx 2023-04-12 19:21:06 +0300 251)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 252)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 253)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300 254)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300 255)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 256)     strcat( (char *)&repo_path[0], name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 257) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 258)     if( revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 259)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 260)                 "svn cat --revision %d %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 261)                 revision, co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 262)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 263)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 264)                 "svn cat %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 265)                 co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 266)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 267)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 268)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 269)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 270)       strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 271)       return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 272)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 273) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 274)     raw = strbuf_detach( &buf, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 275)     strbuf_addstr_xml_quoted( &buf, (const char *)raw );
bfc1508d (kx 2023-03-24 03:55:33 +0300 276)     free( raw );
bfc1508d (kx 2023-03-24 03:55:33 +0300 277) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 278)     strbuf_addbuf( sb, (const struct strbuf *)&buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 279)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 280)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 281) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 282)   strbuf_addstr( sb, "\n</code></pre>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 283) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 284)   csvn_print_file_links( sb, relative_path, revision, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 285) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 286)   return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 287) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 288) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 289) static void csvn_print_image_file( struct strbuf *sb, const char *relative_path, int revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 290) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 291)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300 292)   const char *name      = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300 293)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300 294) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 295)   if( !sb || !relative_path ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 296) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 297)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 298)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 299)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300 300)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 301)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 302)     pid_t  p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 303)     int    rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 304) 
c7693c71 (kx 2023-04-12 19:21:06 +0300 305)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 306)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 307)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300 308)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300 309)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 310)     strcat( (char *)&repo_path[0], name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 311) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 312)     if( revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 313)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 314)                 "svn cat --revision %d %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 315)                 revision, co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 316)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 317)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 318)                 "svn cat %s/%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 319)                 co_prefix, (char *)&repo_path[0], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 320)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 321)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 322)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 323)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 324)       strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 325)       return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 326)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 327) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 328)     /****************************************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 329)       This call should terminate the program on success:
bfc1508d (kx 2023-03-24 03:55:33 +0300 330)      */
bfc1508d (kx 2023-03-24 03:55:33 +0300 331)     csvn_print_raw_file( &buf, ctx.repo.relative_info.mime );
bfc1508d (kx 2023-03-24 03:55:33 +0300 332) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 333)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 334)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 335) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 336)   return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 337) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 338) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 339) void csvn_print_file_page( void )
bfc1508d (kx 2023-03-24 03:55:33 +0300 340) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 341)   FILE  *fp;
bfc1508d (kx 2023-03-24 03:55:33 +0300 342)   struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 343) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 344)   fp = xfopen( ctx.page.header, "r" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 345)   (void)strbuf_env_fread( &buf, fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 346)   fclose( fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 347) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 348)   strbuf_addf( &buf, "        <div class=\"content segment\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 349)   strbuf_addf( &buf, "          <div class=\"container\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 350)   strbuf_addf( &buf, "            <div class=\"csvn-main-content\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 351) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 352)   if( ctx.repo.relative_info.kind == KIND_FILE )
bfc1508d (kx 2023-03-24 03:55:33 +0300 353)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 354)     if( !strncmp( ctx.repo.relative_info.mime, "text/", 5 ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 355)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 356)       if( ctx.repo.name )
bfc1508d (kx 2023-03-24 03:55:33 +0300 357)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 358)         if( ctx.repo.relative_info.lang )
bfc1508d (kx 2023-03-24 03:55:33 +0300 359)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 360)           if( !strcmp( ctx.repo.relative_info.lang, "Markdown" ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 361)             csvn_print_markdown_file( &buf, ctx.repo.relative_path, ctx.query.rev );
bfc1508d (kx 2023-03-24 03:55:33 +0300 362)           else
bfc1508d (kx 2023-03-24 03:55:33 +0300 363)             csvn_print_file( &buf, ctx.repo.relative_path, ctx.query.rev, ctx.repo.relative_info.lang );
bfc1508d (kx 2023-03-24 03:55:33 +0300 364)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 365)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 366)           csvn_print_file( &buf, ctx.repo.relative_path, ctx.query.rev, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 367)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 368)       else
bfc1508d (kx 2023-03-24 03:55:33 +0300 369)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 370)         strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 371)         strbuf_addf( &buf, "              <p class='leading'>Repository '%s' not found.</p>\n", ctx.repo.name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 372)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 373)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 374)     else if( !strncmp( ctx.repo.relative_info.mime, "image/", 6 ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 375)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 376)       /****************************************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 377)         This call should terminate the program on success:
bfc1508d (kx 2023-03-24 03:55:33 +0300 378)        */
bfc1508d (kx 2023-03-24 03:55:33 +0300 379)       csvn_print_image_file( &buf, ctx.repo.relative_path, ctx.query.rev );
bfc1508d (kx 2023-03-24 03:55:33 +0300 380) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 381)       strbuf_addf( &buf, "              <h1>Requested file cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 382)       strbuf_addf( &buf, "              <p class='leading'>Files with mime type such as '%s' cannot be present.</p>\n", ctx.repo.relative_info.mime );
bfc1508d (kx 2023-03-24 03:55:33 +0300 383)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 384)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 385)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 386)       strbuf_addf( &buf, "              <h1>Requested file cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 387)       strbuf_addf( &buf, "              <p class='leading'>Files with mime type such as '%s' cannot be present.</p>\n", ctx.repo.relative_info.mime );
bfc1508d (kx 2023-03-24 03:55:33 +0300 388)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 389)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 390)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 391)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 392)     strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 393)     strbuf_addf( &buf, "              <p class='leading'>This page assume plain text files to be present.</p>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 394)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 395) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 396)   strbuf_addf( &buf, "            </div> <!-- End of csvn-main-content -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 397)   strbuf_addf( &buf, "          </div> <!-- End of container -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 398)   strbuf_addf( &buf, "        </div> <!-- End of content segment -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 399) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 400)   fp = xfopen( ctx.page.footer, "r" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 401)   (void)strbuf_env_fread( &buf, fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 402)   fclose( fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 403) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 404)   ctx.page.size = buf.len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 405)   csvn_print_http_headers();
bfc1508d (kx 2023-03-24 03:55:33 +0300 406)   strbuf_write( &buf, STDOUT_FILENO );
bfc1508d (kx 2023-03-24 03:55:33 +0300 407)   strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 408) }