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 <libxml/parser.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  35) #include <libxml/tree.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 <cmpvers.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  46) #include <dlist.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  47) #include <strbuf.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  48) #include <repolist.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  49) #include <wrapper.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  50) #include <system.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  51) #include <date.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  52) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  53) #include <ctx.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  54) #include <ui-shared.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  55) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  56) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  57) /********************************
bfc1508d (kx 2023-03-24 03:55:33 +0300  58)   Sorted dlist functions:
bfc1508d (kx 2023-03-24 03:55:33 +0300  59)  */
bfc1508d (kx 2023-03-24 03:55:33 +0300  60) struct tree_line {
bfc1508d (kx 2023-03-24 03:55:33 +0300  61)   char *name;
bfc1508d (kx 2023-03-24 03:55:33 +0300  62)   char *revision;
bfc1508d (kx 2023-03-24 03:55:33 +0300  63)   char *date;
bfc1508d (kx 2023-03-24 03:55:33 +0300  64)   char *size;
bfc1508d (kx 2023-03-24 03:55:33 +0300  65) };
bfc1508d (kx 2023-03-24 03:55:33 +0300  66) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  67) static struct dlist *directories = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  68) static struct dlist *files       = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  69) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  70) static struct tree_line *tree_line_alloc( const char *name, const char *revision, const char *date, const char *size  )
bfc1508d (kx 2023-03-24 03:55:33 +0300  71) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  72)   struct tree_line *line = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  73)   line = (struct tree_line *)xmalloc( sizeof(struct tree_line) );
bfc1508d (kx 2023-03-24 03:55:33 +0300  74) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  75)   if( name )     { line->name     = xstrdup( name );     }
bfc1508d (kx 2023-03-24 03:55:33 +0300  76)   if( revision ) { line->revision = xstrdup( revision ); }
bfc1508d (kx 2023-03-24 03:55:33 +0300  77)   if( date )     { line->date     = xstrdup( date );     }
bfc1508d (kx 2023-03-24 03:55:33 +0300  78)   if( size )     { line->size     = xstrdup( size );     }
bfc1508d (kx 2023-03-24 03:55:33 +0300  79) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  80)   return line;
bfc1508d (kx 2023-03-24 03:55:33 +0300  81) }
bfc1508d (kx 2023-03-24 03:55:33 +0300  82) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  83) static void __line_free( void *data, void *user_data )
bfc1508d (kx 2023-03-24 03:55:33 +0300  84) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  85)   struct tree_line *line = (struct tree_line *)data;
bfc1508d (kx 2023-03-24 03:55:33 +0300  86)   if( line )
bfc1508d (kx 2023-03-24 03:55:33 +0300  87)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  88)     if( line->name )     { free( line->name );     line->name     = NULL; }
bfc1508d (kx 2023-03-24 03:55:33 +0300  89)     if( line->revision ) { free( line->revision ); line->revision = NULL; }
bfc1508d (kx 2023-03-24 03:55:33 +0300  90)     if( line->date )     { free( line->date );     line->date     = NULL; }
bfc1508d (kx 2023-03-24 03:55:33 +0300  91)     if( line->size )     { free( line->size );     line->size     = NULL; }
bfc1508d (kx 2023-03-24 03:55:33 +0300  92) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  93)     free( line );
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) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  97) static struct dlist *tree_lines_free( struct dlist *lines )
bfc1508d (kx 2023-03-24 03:55:33 +0300  98) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  99)   if( lines )
bfc1508d (kx 2023-03-24 03:55:33 +0300 100)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 101)     dlist_free( lines, __line_free );
bfc1508d (kx 2023-03-24 03:55:33 +0300 102)     lines = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 103)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 104)   return lines;
bfc1508d (kx 2023-03-24 03:55:33 +0300 105) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 106) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 107) static int __cmp_tree_lines_bytag( const void *a, const void *b )
bfc1508d (kx 2023-03-24 03:55:33 +0300 108) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 109)   char *v1 = NULL, *v2 = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 110)   int   ret = -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 111) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 112)   struct tree_line *line1 = (struct tree_line *)a;
bfc1508d (kx 2023-03-24 03:55:33 +0300 113)   struct tree_line *line2 = (struct tree_line *)b;
bfc1508d (kx 2023-03-24 03:55:33 +0300 114) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 115)   if( line1->name && line2->name )
bfc1508d (kx 2023-03-24 03:55:33 +0300 116)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 117)     v1 = line1->name;
bfc1508d (kx 2023-03-24 03:55:33 +0300 118)     v2 = line2->name;
bfc1508d (kx 2023-03-24 03:55:33 +0300 119)     while( *v1 && !isdigit( *v1 ) ) ++v1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 120)     while( *v2 && !isdigit( *v2 ) ) ++v2;
bfc1508d (kx 2023-03-24 03:55:33 +0300 121)     ret = strcmp( line1->name, line2->name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 122)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 123)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 124)     return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 125) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 126)   if( !*v1 || !*v2 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 127)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 128)     return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 129)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 130) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 131)   /******************************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 132)     sort reversive to show newest tag first:
bfc1508d (kx 2023-03-24 03:55:33 +0300 133)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300 134)   return -cmp_version( (const char *)v1, (const char *)v2 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 135) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 136) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 137) static struct dlist *tree_lines_sort_bytag( struct dlist *lines )
bfc1508d (kx 2023-03-24 03:55:33 +0300 138) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 139)   if( lines ) { lines = dlist_sort( lines, __cmp_tree_lines_bytag ); }
bfc1508d (kx 2023-03-24 03:55:33 +0300 140)   return lines;
bfc1508d (kx 2023-03-24 03:55:33 +0300 141) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 142) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 143)   End of sorted dlist functions.
bfc1508d (kx 2023-03-24 03:55:33 +0300 144)  ********************************/
bfc1508d (kx 2023-03-24 03:55:33 +0300 145) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 146) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 147) static const char *is_file_executable( const char *relative_path, const char *name, int revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 148) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 149)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300 150)   const char *repo_name = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300 151)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300 152)   const char *ret  = "";
bfc1508d (kx 2023-03-24 03:55:33 +0300 153)   char *path = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 154) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 155)   if( !name ) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 156) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 157)   if( relative_path && *relative_path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 158)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 159)     path = (char *)xmalloc( strlen( relative_path ) + 2 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 160)     path[0] = '/';
bfc1508d (kx 2023-03-24 03:55:33 +0300 161)     sprintf( (char *)&path[1], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 162)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 163)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 164)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 165)     path = (char *)xmalloc( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 166)     path[0] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 167)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 168) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 169)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 170)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 171)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300 172)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 173)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 174)     pid_t p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 175)     int   rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 176) 
c7693c71 (kx 2023-04-12 19:21:06 +0300 177)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 178)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 179)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300 180)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300 181)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 182)     strcat( (char *)&repo_path[0], repo_name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 183) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 184)     if( revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 185)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 186)                 "svn propget svn:executable --revision %d %s/%s%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 187)                 revision, co_prefix, (char *)&repo_path[0], path, name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 188)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 189)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 190)                 "svn propget svn:executable %s/%s%s/%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 191)                 co_prefix, (char *)&repo_path[0], path, name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 192)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 193)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 194)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 195)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 196)       strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 197)       free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 198)       return "";
bfc1508d (kx 2023-03-24 03:55:33 +0300 199)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 200) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 201)     strbuf_trim( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 202)     if( buf.buf[0] == '*' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 203)       ret = " exec";
bfc1508d (kx 2023-03-24 03:55:33 +0300 204)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 205)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 206) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 207)   free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 208)   return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 209) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 210) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 211) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 212) static xmlNode *xml_find_node_by_name( xmlNode *root, const char *name )
bfc1508d (kx 2023-03-24 03:55:33 +0300 213) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 214)   xmlNode *node = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 215)   xmlNode *ret  = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 216) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 217)   if( !name || !*name || !root || !root->children ) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 218) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 219)   for( node = root->children; node; node = node->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300 220)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 221)     if( node->type == XML_ELEMENT_NODE )
bfc1508d (kx 2023-03-24 03:55:33 +0300 222)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 223)       if( !strcmp( (char *)name, (char *)node->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 224)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 225)         return node;
bfc1508d (kx 2023-03-24 03:55:33 +0300 226)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 227)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 228)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 229)   return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 230) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 231) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 232) static void xml_csvn_tree( const struct strbuf *buf )
bfc1508d (kx 2023-03-24 03:55:33 +0300 233) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 234)   xmlDocPtr doc = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 235)   xmlNode *root = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 236) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 237)   if( !buf || !buf->buf ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 238) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 239)   LIBXML_TEST_VERSION
bfc1508d (kx 2023-03-24 03:55:33 +0300 240) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 241)   doc = xmlReadMemory( buf->buf, buf->len, "list.xml", NULL, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 242)   if( !doc )
bfc1508d (kx 2023-03-24 03:55:33 +0300 243)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 244)     html_fatal( "cannot parse svn list.xml" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 245)     return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 246)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 247) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 248)   root = xmlDocGetRootElement( doc );
bfc1508d (kx 2023-03-24 03:55:33 +0300 249)   if( !root )
bfc1508d (kx 2023-03-24 03:55:33 +0300 250)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 251)     xmlFreeDoc( doc );
bfc1508d (kx 2023-03-24 03:55:33 +0300 252)     xmlCleanupParser();
bfc1508d (kx 2023-03-24 03:55:33 +0300 253)     return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 254)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 255) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 256)   if( !strcmp( "lists", (char *)root->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 257)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 258)     xmlNode *list = NULL, *node = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 259) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 260)     list = xml_find_node_by_name( root, "list" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 261)     if( !list )
bfc1508d (kx 2023-03-24 03:55:33 +0300 262)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 263)       xmlFreeDoc( doc );
bfc1508d (kx 2023-03-24 03:55:33 +0300 264)       xmlCleanupParser();
bfc1508d (kx 2023-03-24 03:55:33 +0300 265)       return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 266)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 267) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 268)     /****************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 269)       Collect directories first:
bfc1508d (kx 2023-03-24 03:55:33 +0300 270)      */
bfc1508d (kx 2023-03-24 03:55:33 +0300 271)     for( node = list->children; node; node = node->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300 272)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 273)       if( node->type == XML_ELEMENT_NODE && !strcmp( "entry", (char *)node->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 274)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 275)         xmlChar *content = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 276)         xmlNode *param   = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 277) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 278)         content = xmlGetProp( node, (const unsigned char *)"kind" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 279)         if( !strcmp( (const char *)content, "dir" ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 280)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 281)           xmlChar *name = NULL, *revision = NULL, *date = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 282) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 283)           for( param = node->children; param; param= param->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300 284)           {
bfc1508d (kx 2023-03-24 03:55:33 +0300 285)             if( param->type == XML_ELEMENT_NODE && !strcmp( "name", (char *)param->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 286)             {
bfc1508d (kx 2023-03-24 03:55:33 +0300 287)               name = xmlNodeGetContent( param );
bfc1508d (kx 2023-03-24 03:55:33 +0300 288)             }
bfc1508d (kx 2023-03-24 03:55:33 +0300 289)             if( param->type == XML_ELEMENT_NODE && !strcmp( "commit", (char *)param->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 290)             {
bfc1508d (kx 2023-03-24 03:55:33 +0300 291)               xmlNode *commit_date = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 292)               revision = xmlGetProp( param, (const unsigned char *)"revision" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 293)               commit_date = xml_find_node_by_name( param, "date" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 294)               if( commit_date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 295)                 date = xmlNodeGetContent( commit_date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 296)             }
bfc1508d (kx 2023-03-24 03:55:33 +0300 297)           } /* End for entry parameters */
bfc1508d (kx 2023-03-24 03:55:33 +0300 298) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 299)           if( name && revision && date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 300)           {
bfc1508d (kx 2023-03-24 03:55:33 +0300 301)             struct tree_line *line = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 302) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 303)             line = tree_line_alloc( (const char *)name, (const char *)revision, (const char *)date, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 304)             directories = dlist_append( directories, (void *)line );
bfc1508d (kx 2023-03-24 03:55:33 +0300 305) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 306)             xmlFree( name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 307)             xmlFree( revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 308)             xmlFree( date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 309)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 310)           else
bfc1508d (kx 2023-03-24 03:55:33 +0300 311)           {
bfc1508d (kx 2023-03-24 03:55:33 +0300 312)             if( name )     xmlFree( name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 313)             if( revision ) xmlFree( revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 314)             if( date )     xmlFree( date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 315)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 316)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 317)         xmlFree( content );
bfc1508d (kx 2023-03-24 03:55:33 +0300 318)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 319)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 320) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 321)     /****************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 322)       Collect files:
bfc1508d (kx 2023-03-24 03:55:33 +0300 323)      */
bfc1508d (kx 2023-03-24 03:55:33 +0300 324)     for( node = list->children; node; node = node->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300 325)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 326)       if( node->type == XML_ELEMENT_NODE && !strcmp( "entry", (char *)node->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 327)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 328)         xmlChar *content = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 329)         xmlNode *param   = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 330) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 331)         content = xmlGetProp( node, (const unsigned char *)"kind" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 332)         if( !strcmp( (const char *)content, "file" ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 333)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 334)           xmlChar *name = NULL, *size = NULL, *revision = NULL, *date = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 335) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 336)           for( param = node->children; param; param= param->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300 337)           {
bfc1508d (kx 2023-03-24 03:55:33 +0300 338)             if( param->type == XML_ELEMENT_NODE && !strcmp( "name", (char *)param->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 339)             {
bfc1508d (kx 2023-03-24 03:55:33 +0300 340)               name = xmlNodeGetContent( param );
bfc1508d (kx 2023-03-24 03:55:33 +0300 341)             }
bfc1508d (kx 2023-03-24 03:55:33 +0300 342)             if( param->type == XML_ELEMENT_NODE && !strcmp( "size", (char *)param->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 343)             {
bfc1508d (kx 2023-03-24 03:55:33 +0300 344)               size = xmlNodeGetContent( param );
bfc1508d (kx 2023-03-24 03:55:33 +0300 345)             }
bfc1508d (kx 2023-03-24 03:55:33 +0300 346)             if( param->type == XML_ELEMENT_NODE && !strcmp( "commit", (char *)param->name ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 347)             {
bfc1508d (kx 2023-03-24 03:55:33 +0300 348)               xmlNode *commit_date = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 349)               revision = xmlGetProp( param, (const unsigned char *)"revision" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 350)               commit_date = xml_find_node_by_name( param, "date" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 351)               if( commit_date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 352)                 date = xmlNodeGetContent( commit_date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 353)             }
bfc1508d (kx 2023-03-24 03:55:33 +0300 354)           } /* End for entry parameters */
bfc1508d (kx 2023-03-24 03:55:33 +0300 355) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 356)           if( name && size && revision && date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 357)           {
bfc1508d (kx 2023-03-24 03:55:33 +0300 358)             struct tree_line *line = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 359) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 360)             line = tree_line_alloc( (const char *)name, (const char *)revision, (const char *)date, (const char *)size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 361)             files = dlist_append( files, (void *)line );
bfc1508d (kx 2023-03-24 03:55:33 +0300 362) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 363)             xmlFree( name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 364)             xmlFree( size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 365)             xmlFree( revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 366)             xmlFree( date );
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)             if( name )     xmlFree( name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 371)             if( size )     xmlFree( size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 372)             if( revision ) xmlFree( revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 373)             if( date )     xmlFree( date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 374)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 375)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 376)         xmlFree( content );
bfc1508d (kx 2023-03-24 03:55:33 +0300 377)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 378)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 379)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 380) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 381)   xmlFreeDoc(doc);
bfc1508d (kx 2023-03-24 03:55:33 +0300 382)   xmlCleanupParser();
bfc1508d (kx 2023-03-24 03:55:33 +0300 383) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 384) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 385) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 386) static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int rev )
bfc1508d (kx 2023-03-24 03:55:33 +0300 387) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 388)   char  *path = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 389) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 390)   if( !sb || !sb->len ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 391) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 392)   if( relative_path && *relative_path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 393)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 394)     path = (char *)xmalloc( strlen( relative_path ) + 2 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 395)     path[0] = '/';
bfc1508d (kx 2023-03-24 03:55:33 +0300 396)     sprintf( (char *)&path[1], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 397)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 398)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 399)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 400)     path = (char *)xmalloc( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 401)     path[0] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 402)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 403) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 404)   if( path && *path && !strcmp( (char *)&path[1], ctx.repo.tags ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 405)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 406)     directories = tree_lines_sort_bytag( directories );
bfc1508d (kx 2023-03-24 03:55:33 +0300 407)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 408) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 409)   strbuf_addstr( sb, "\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 410)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 411)   strbuf_addf( sb, "                <div class=\"row\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 412)   strbuf_addf( sb, "                  <div class=\"col-path\">Path</div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 413)   strbuf_addf( sb, "                  <div class=\"col-size\"><div class=\"tree-size trunc\">Size</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 414)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div class=\"tree-rev trunc\">Rev</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 415)   strbuf_addf( sb, "                  <div class=\"col-date\"><div class=\"tree-date trunc\">Date</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 416)   strbuf_addf( sb, "                  <div class=\"col-links\"><div class=\"tree-links trunc\">Links</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 417)   strbuf_addf( sb, "                </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 418)   strbuf_addf( sb, "              </div>\n\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 419) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 420)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 421) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 422)   /**************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 423)     Print directories first:
bfc1508d (kx 2023-03-24 03:55:33 +0300 424)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300 425)   if( directories )
bfc1508d (kx 2023-03-24 03:55:33 +0300 426)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 427)     struct dlist *list = directories;
bfc1508d (kx 2023-03-24 03:55:33 +0300 428)     while( list )
bfc1508d (kx 2023-03-24 03:55:33 +0300 429)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 430)       struct tree_line *line = (struct tree_line *)list->data;
bfc1508d (kx 2023-03-24 03:55:33 +0300 431) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 432)       if( line->name && line->revision && line->date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 433)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 434)         struct tm   tm;
bfc1508d (kx 2023-03-24 03:55:33 +0300 435)         time_t      time = -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 436)         const char *query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 437) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 438)         query_string = ctx_remove_query_param( query_string, "op" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 439) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 440)         time = parse_date( &tm, (const char *)line->date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 441) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 442)         strbuf_addf( sb, "                <div class=\"row\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 443)         if( ctx.env.query_string && *ctx.env.query_string )
c7693c71 (kx 2023-04-12 19:21:06 +0300 444)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 445)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 446)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 447)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, ctx.env.query_string, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 448)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 449)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 450)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 451)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 452)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 453)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 454)         else
c7693c71 (kx 2023-04-12 19:21:06 +0300 455)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 456)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 457)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 458)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 459)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 460)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 461)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 462)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 463)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 464)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 465)         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">4096</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 466)         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\">%s</div></div>\n", line->revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 467)         if( time != -1 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 468)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 469)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 470)           csvn_print_age( sb, time, 0, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 471)           strbuf_addf( sb, "</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 472)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 473)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 474)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 475)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 476)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 477)         strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 478)         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 479)         if( query_string && *query_string )
bfc1508d (kx 2023-03-24 03:55:33 +0300 480)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 481)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 482)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 483)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 484)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 485)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 486)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 487)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 488)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 489)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 490)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 491)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 492)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 493)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 494)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 495)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 496)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 497)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 498)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 499)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 500)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 501)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 502)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 503)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 504)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 505)         strbuf_addf( sb, "                    </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 506)         strbuf_addf( sb, "                  </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 507)         strbuf_addf( sb, "                </div>\n\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 508)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 509) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 510)       list = dlist_next( list );
bfc1508d (kx 2023-03-24 03:55:33 +0300 511)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 512)     directories = tree_lines_free( directories );
bfc1508d (kx 2023-03-24 03:55:33 +0300 513)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 514) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 515)   /**************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 516)     Print files:
bfc1508d (kx 2023-03-24 03:55:33 +0300 517)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300 518)   if( files )
bfc1508d (kx 2023-03-24 03:55:33 +0300 519)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 520)     struct dlist *list = files;
bfc1508d (kx 2023-03-24 03:55:33 +0300 521)     while( list )
bfc1508d (kx 2023-03-24 03:55:33 +0300 522)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 523)       struct tree_line *line = (struct tree_line *)list->data;
bfc1508d (kx 2023-03-24 03:55:33 +0300 524) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 525)       if( line->name && line->size && line->revision && line->date )
bfc1508d (kx 2023-03-24 03:55:33 +0300 526)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 527)         struct tm   tm;
bfc1508d (kx 2023-03-24 03:55:33 +0300 528)         time_t      time = -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 529)         const char *query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 530)         const char *exec         = is_file_executable( relative_path, (const char *)line->name, rev );
bfc1508d (kx 2023-03-24 03:55:33 +0300 531) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 532)         query_string = ctx_remove_query_param( query_string, "op" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 533) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 534)         time = parse_date( &tm, (const char *)line->date );
bfc1508d (kx 2023-03-24 03:55:33 +0300 535) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 536)         strbuf_addf( sb, "                <div class=\"row\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 537)         if( ctx.env.query_string && *ctx.env.query_string )
c7693c71 (kx 2023-04-12 19:21:06 +0300 538)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 539)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 540)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 541)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/?%s\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, ctx.env.query_string, exec, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 542)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 543)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 544)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 545)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, exec, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 546)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 547)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 548)         else
c7693c71 (kx 2023-04-12 19:21:06 +0300 549)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 550)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 551)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 552)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, exec, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 553)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 554)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 555)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 556)             strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, exec, line->name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 557)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 558)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 559)         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%s</div></div>\n", line->size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 560)         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\">%s</div></div>\n", line->revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 561)         if( time != -1 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 562)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 563)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 564)           csvn_print_age( sb, time, 0, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 565)           strbuf_addf( sb, "</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 566)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 567)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 568)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 569)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 570)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 571)         strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 572)         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 573)         if( query_string && *query_string )
bfc1508d (kx 2023-03-24 03:55:33 +0300 574)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 575)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 576)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 577)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 578)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s&%s\">diff &nbsp;</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 579)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 580)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 581)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 582)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 583)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 584)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff &nbsp;</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 585)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
c7693c71 (kx 2023-04-12 19:21:06 +0300 586)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 587)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 588)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 589)         {
c7693c71 (kx 2023-04-12 19:21:06 +0300 590)           if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 591)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 592)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 593)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 594)             strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 595)           }
c7693c71 (kx 2023-04-12 19:21:06 +0300 596)           else
c7693c71 (kx 2023-04-12 19:21:06 +0300 597)           {
c7693c71 (kx 2023-04-12 19:21:06 +0300 598)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 599)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 600)             strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision );
c7693c71 (kx 2023-04-12 19:21:06 +0300 601)           }
bfc1508d (kx 2023-03-24 03:55:33 +0300 602)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 603)         strbuf_addf( sb, "                    </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 604)         strbuf_addf( sb, "                  </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 605)         strbuf_addf( sb, "                </div>\n\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 606)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 607) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 608)       list = dlist_next( list );
bfc1508d (kx 2023-03-24 03:55:33 +0300 609)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 610)     files = tree_lines_free( files );
bfc1508d (kx 2023-03-24 03:55:33 +0300 611)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 612) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 613)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 614) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 615)   free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 616) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 617) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 618) static void csvn_print_tree( struct strbuf *sb, const char *relative_path, int revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 619) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 620)   const char *co_prefix = ctx.repo.checkout_ro_prefix;
c7693c71 (kx 2023-04-12 19:21:06 +0300 621)   const char *name      = ctx.repo.name;
c7693c71 (kx 2023-04-12 19:21:06 +0300 622)   const char *repo_root = ctx.repo.repo_root;
bfc1508d (kx 2023-03-24 03:55:33 +0300 623)   char *path = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 624) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 625)   if( !sb ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 626) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 627)   if( relative_path && *relative_path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 628)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 629)     path = (char *)xmalloc( strlen( relative_path ) + 2 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 630)     path[0] = '/';
bfc1508d (kx 2023-03-24 03:55:33 +0300 631)     sprintf( (char *)&path[1], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 632)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 633)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 634)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 635)     path = (char *)xmalloc( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 636)     path[0] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 637)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 638) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 639)   if( co_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 640)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 641)     char repo_path[PATH_MAX] = { 0 };
c7693c71 (kx 2023-04-12 19:21:06 +0300 642)     char cmd[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 643)     struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 644)     pid_t p = (pid_t) -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 645)     int   rc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 646) 
c7693c71 (kx 2023-04-12 19:21:06 +0300 647)     if( repo_root && *repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 648)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 649)       strcat( (char *)&repo_path[0], repo_root );
c7693c71 (kx 2023-04-12 19:21:06 +0300 650)       strcat( (char *)&repo_path[0], "/" );
c7693c71 (kx 2023-04-12 19:21:06 +0300 651)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 652)     strcat( (char *)&repo_path[0], name );
c7693c71 (kx 2023-04-12 19:21:06 +0300 653) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 654)     if( revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 655)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 656)                 "svn list --revision %d --xml %s/%s%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 657)                 revision, co_prefix, (char *)&repo_path[0], path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 658)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 659)       snprintf( (char *)&cmd[0], 1024,
bfc1508d (kx 2023-03-24 03:55:33 +0300 660)                 "svn list --xml %s/%s%s 2>/dev/null",
c7693c71 (kx 2023-04-12 19:21:06 +0300 661)                 co_prefix, (char *)&repo_path[0], path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 662)     p = sys_exec_command( &buf, cmd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 663)     rc = sys_wait_command( p, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 664)     if( rc != 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 665)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 666)       strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 667)       free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 668)       return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 669)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 670) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 671)     xml_csvn_tree( (const struct strbuf *)&buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 672)     strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 673) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 674)     dlist_csvn_tree( sb, relative_path, revision );
bfc1508d (kx 2023-03-24 03:55:33 +0300 675)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 676) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 677)   free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 678)   return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 679) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 680) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 681) static void csvn_print_checkout_urls( struct strbuf *sb, const char *relative_path, int revision )
bfc1508d (kx 2023-03-24 03:55:33 +0300 682) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 683)   char *path = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 684) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 685)   if( !sb ) return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 686) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 687)   if( relative_path && *relative_path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 688)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 689)     path = (char *)xmalloc( strlen( relative_path ) + 2 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 690)     path[0] = '/';
bfc1508d (kx 2023-03-24 03:55:33 +0300 691)     sprintf( (char *)&path[1], relative_path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 692)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 693)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 694)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 695)     path = (char *)xmalloc( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 696)     path[0] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 697)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 698) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 699)   strbuf_addf( sb, "                <div class=\"checkout-box\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 700)   strbuf_addf( sb, "                  <div class=\"checkout-header\">Checkout</div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 701)   strbuf_addf( sb, "                  <div class=\"checkout-urls\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 702)   strbuf_addf( sb, "                    <div class=\"checkout-line\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 703)   strbuf_addf( sb, "                      <div class=\"checkout-perms\">ro:</div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 704) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 705)   if( revision )
c7693c71 (kx 2023-04-12 19:21:06 +0300 706)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 707)     if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 708)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 709)       strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s/%s%s</div>\n", revision, ctx.repo.checkout_ro_prefix, ctx.repo.repo_root, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 710)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 711)     else
c7693c71 (kx 2023-04-12 19:21:06 +0300 712)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 713)       strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 714)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 715)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 716)   else
c7693c71 (kx 2023-04-12 19:21:06 +0300 717)   {
c7693c71 (kx 2023-04-12 19:21:06 +0300 718)     if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 719)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 720)       strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s/%s%s</div>\n", ctx.repo.checkout_ro_prefix, ctx.repo.repo_root, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 721)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 722)     else
c7693c71 (kx 2023-04-12 19:21:06 +0300 723)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 724)       strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 725)     }
c7693c71 (kx 2023-04-12 19:21:06 +0300 726)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 727) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 728)   strbuf_addf( sb, "                    </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 729)   if( ctx.repo.checkout_prefix && *ctx.repo.checkout_prefix )
bfc1508d (kx 2023-03-24 03:55:33 +0300 730)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 731)     strbuf_addf( sb, "                    <div class=\"checkout-line\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 732)     strbuf_addf( sb, "                      <div class=\"checkout-perms\">rw:</div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 733) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 734)     if( revision )
c7693c71 (kx 2023-04-12 19:21:06 +0300 735)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 736)       if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 737)       {
c7693c71 (kx 2023-04-12 19:21:06 +0300 738)         strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s/%s%s</div>\n", revision, ctx.repo.checkout_prefix, ctx.repo.repo_root, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 739)       }
c7693c71 (kx 2023-04-12 19:21:06 +0300 740)       else
c7693c71 (kx 2023-04-12 19:21:06 +0300 741)       {
c7693c71 (kx 2023-04-12 19:21:06 +0300 742)         strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_prefix, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 743)       }
c7693c71 (kx 2023-04-12 19:21:06 +0300 744)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 745)     else
c7693c71 (kx 2023-04-12 19:21:06 +0300 746)     {
c7693c71 (kx 2023-04-12 19:21:06 +0300 747)       if( ctx.repo.repo_root && *ctx.repo.repo_root )
c7693c71 (kx 2023-04-12 19:21:06 +0300 748)       {
c7693c71 (kx 2023-04-12 19:21:06 +0300 749)         strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s/%s%s</div>\n", ctx.repo.checkout_prefix, ctx.repo.repo_root, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 750)       }
c7693c71 (kx 2023-04-12 19:21:06 +0300 751)       else
c7693c71 (kx 2023-04-12 19:21:06 +0300 752)       {
c7693c71 (kx 2023-04-12 19:21:06 +0300 753)         strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_prefix, ctx.repo.name, path );
c7693c71 (kx 2023-04-12 19:21:06 +0300 754)       }
c7693c71 (kx 2023-04-12 19:21:06 +0300 755)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 756) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 757)     strbuf_addf( sb, "                    </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 758)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 759)   strbuf_addf( sb, "                  </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 760)   strbuf_addf( sb, "                </div>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 761) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 762)   free( path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 763) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 764) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 765) void csvn_print_tree_page( void )
bfc1508d (kx 2023-03-24 03:55:33 +0300 766) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 767)   FILE  *fp;
bfc1508d (kx 2023-03-24 03:55:33 +0300 768)   struct strbuf buf = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 769) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 770)   fp = xfopen( ctx.page.header, "r" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 771)   (void)strbuf_env_fread( &buf, fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 772)   fclose( fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 773) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 774)   strbuf_addf( &buf, "        <div class=\"content segment\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 775)   strbuf_addf( &buf, "          <div class=\"container\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 776)   strbuf_addf( &buf, "            <div class=\"csvn-main-content\">\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 777) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 778)   if( ctx.repo.relative_info.kind == KIND_DIR )
bfc1508d (kx 2023-03-24 03:55:33 +0300 779)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 780)     if( ctx.repo.name )
bfc1508d (kx 2023-03-24 03:55:33 +0300 781)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 782)       csvn_print_tree( &buf, ctx.repo.relative_path, ctx.query.rev );
bfc1508d (kx 2023-03-24 03:55:33 +0300 783)       csvn_print_checkout_urls( &buf, ctx.repo.relative_path, ctx.query.rev );
bfc1508d (kx 2023-03-24 03:55:33 +0300 784)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 785)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 786)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 787)       strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 788)       strbuf_addf( &buf, "              <p class='leading'>Repository '%s' not found.</p>\n", ctx.repo.name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 789)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 790)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 791)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 792)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 793)     strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 794)     strbuf_addf( &buf, "              <p class='leading'>This page assume the repository tree to be shown.</p>\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 795)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 796) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 797)   strbuf_addf( &buf, "            </div> <!-- End of csvn-main-content -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 798)   strbuf_addf( &buf, "          </div> <!-- End of container -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 799)   strbuf_addf( &buf, "        </div> <!-- End of content segment -->\n" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 800) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 801)   fp = xfopen( ctx.page.footer, "r" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 802)   (void)strbuf_env_fread( &buf, fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 803)   fclose( fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 804) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 805)   ctx.page.size = buf.len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 806)   csvn_print_http_headers();
bfc1508d (kx 2023-03-24 03:55:33 +0300 807)   strbuf_write( &buf, STDOUT_FILENO );
bfc1508d (kx 2023-03-24 03:55:33 +0300 808)   strbuf_release( &buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 809) }