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) #include <stdint.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  11) #include <dirent.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  12) #include <sys/stat.h> /* chmod(2)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300  13) #include <sys/file.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  14) #include <sys/mman.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  15) #include <fcntl.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  16) #include <limits.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  17) #include <string.h>   /* strdup(3)   */
bfc1508d (kx 2023-03-24 03:55:33 +0300  18) #include <libgen.h>   /* basename(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300  19) #include <ctype.h>    /* tolower(3)  */
bfc1508d (kx 2023-03-24 03:55:33 +0300  20) #include <errno.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  21) #include <time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  22) #include <sys/time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  23) #include <pwd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  24) #include <grp.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  25) #include <stdarg.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  26) #include <unistd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  27) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  28) #include <defs.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  29) #include <fatal.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  30) #include <http.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  31) #include <html.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  32) #include <strbuf.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  33) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  34) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  35) const signed char hexval_table[256] = {
bfc1508d (kx 2023-03-24 03:55:33 +0300  36)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 00-07 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  37)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 08-0f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  38)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 10-17 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  39)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 18-1f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  40)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 20-27 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  41)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 28-2f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  42)    0,  1,  2,  3,  4,  5,  6,  7,  /* 30-37 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  43)    8,  9, -1, -1, -1, -1, -1, -1,  /* 38-3f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  44)   -1, 10, 11, 12, 13, 14, 15, -1,  /* 40-47 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  45)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 48-4f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  46)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 50-57 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  47)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 58-5f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  48)   -1, 10, 11, 12, 13, 14, 15, -1,  /* 60-67 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  49)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 68-67 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  50)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 70-77 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  51)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 78-7f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  52)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 80-87 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  53)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 88-8f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  54)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 90-97 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  55)   -1, -1, -1, -1, -1, -1, -1, -1,  /* 98-9f */
bfc1508d (kx 2023-03-24 03:55:33 +0300  56)   -1, -1, -1, -1, -1, -1, -1, -1,  /* a0-a7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  57)   -1, -1, -1, -1, -1, -1, -1, -1,  /* a8-af */
bfc1508d (kx 2023-03-24 03:55:33 +0300  58)   -1, -1, -1, -1, -1, -1, -1, -1,  /* b0-b7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  59)   -1, -1, -1, -1, -1, -1, -1, -1,  /* b8-bf */
bfc1508d (kx 2023-03-24 03:55:33 +0300  60)   -1, -1, -1, -1, -1, -1, -1, -1,  /* c0-c7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  61)   -1, -1, -1, -1, -1, -1, -1, -1,  /* c8-cf */
bfc1508d (kx 2023-03-24 03:55:33 +0300  62)   -1, -1, -1, -1, -1, -1, -1, -1,  /* d0-d7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  63)   -1, -1, -1, -1, -1, -1, -1, -1,  /* d8-df */
bfc1508d (kx 2023-03-24 03:55:33 +0300  64)   -1, -1, -1, -1, -1, -1, -1, -1,  /* e0-e7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  65)   -1, -1, -1, -1, -1, -1, -1, -1,  /* e8-ef */
bfc1508d (kx 2023-03-24 03:55:33 +0300  66)   -1, -1, -1, -1, -1, -1, -1, -1,  /* f0-f7 */
bfc1508d (kx 2023-03-24 03:55:33 +0300  67)   -1, -1, -1, -1, -1, -1, -1, -1,  /* f8-ff */
bfc1508d (kx 2023-03-24 03:55:33 +0300  68) };
bfc1508d (kx 2023-03-24 03:55:33 +0300  69) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  70) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  71) static char *
bfc1508d (kx 2023-03-24 03:55:33 +0300  72) url_decode_internal( const char **query, int len,
bfc1508d (kx 2023-03-24 03:55:33 +0300  73)                      const char *stop_at, struct strbuf *out,
bfc1508d (kx 2023-03-24 03:55:33 +0300  74)                      int decode_plus )
bfc1508d (kx 2023-03-24 03:55:33 +0300  75) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  76)   const char *q = *query;
bfc1508d (kx 2023-03-24 03:55:33 +0300  77) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  78)   while( len )
bfc1508d (kx 2023-03-24 03:55:33 +0300  79)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  80)     unsigned char c = *q;
bfc1508d (kx 2023-03-24 03:55:33 +0300  81) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  82)     if( !c )
bfc1508d (kx 2023-03-24 03:55:33 +0300  83)       break;
bfc1508d (kx 2023-03-24 03:55:33 +0300  84)     if( stop_at && strchr( stop_at, c ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300  85)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300  86)       ++q;
bfc1508d (kx 2023-03-24 03:55:33 +0300  87)       --len;
bfc1508d (kx 2023-03-24 03:55:33 +0300  88)       break;
bfc1508d (kx 2023-03-24 03:55:33 +0300  89)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300  90) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  91)     if( c == '%' && (len < 0 || len >= 3) )
bfc1508d (kx 2023-03-24 03:55:33 +0300  92)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300  93)       int val = hex2chr( q + 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300  94)       if( 0 < val )
bfc1508d (kx 2023-03-24 03:55:33 +0300  95)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300  96)         strbuf_addch( out, val );
bfc1508d (kx 2023-03-24 03:55:33 +0300  97)         q += 3;
bfc1508d (kx 2023-03-24 03:55:33 +0300  98)         len -= 3;
bfc1508d (kx 2023-03-24 03:55:33 +0300  99)         continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 100)       }
bfc1508d (kx 2023-03-24 03:55:33 +0300 101)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 102) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 103)     if( decode_plus && c == '+' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 104)       strbuf_addch( out, ' ' );
bfc1508d (kx 2023-03-24 03:55:33 +0300 105)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 106)       strbuf_addch( out, c );
bfc1508d (kx 2023-03-24 03:55:33 +0300 107)     ++q;
bfc1508d (kx 2023-03-24 03:55:33 +0300 108)     --len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 109)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 110)   *query = q;
bfc1508d (kx 2023-03-24 03:55:33 +0300 111) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 112)   return strbuf_detach( out, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 113) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 114) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 115) char *url_decode_mem( const char *url, int len )
bfc1508d (kx 2023-03-24 03:55:33 +0300 116) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 117)   struct strbuf out = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 118)   const char *colon = memchr( url, ':', len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 119) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 120)   /* Skip protocol part if present */
bfc1508d (kx 2023-03-24 03:55:33 +0300 121)   if( colon && url < colon )
bfc1508d (kx 2023-03-24 03:55:33 +0300 122)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 123)     strbuf_add( &out, url, colon - url );
bfc1508d (kx 2023-03-24 03:55:33 +0300 124)     len -= colon - url;
bfc1508d (kx 2023-03-24 03:55:33 +0300 125)     url = colon;
bfc1508d (kx 2023-03-24 03:55:33 +0300 126)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 127)   return url_decode_internal( &url, len, NULL, &out, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 128) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 129) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 130) char *url_percent_decode( const char *encoded )
bfc1508d (kx 2023-03-24 03:55:33 +0300 131) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 132)   struct strbuf out = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 133)   return url_decode_internal( &encoded, strlen(encoded), NULL, &out, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 134) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 135) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 136) char *url_decode_parameter_name( const char **query )
bfc1508d (kx 2023-03-24 03:55:33 +0300 137) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 138)   struct strbuf out = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 139)   return url_decode_internal( query, -1, "&=", &out, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 140) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 141) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 142) char *url_decode_parameter_value( const char **query )
bfc1508d (kx 2023-03-24 03:55:33 +0300 143) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 144)   struct strbuf out = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 145)   return url_decode_internal( query, -1, "&", &out, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 146) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 147) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 148) void http_parse_querystring( const char *txt, void (*fn)(const char *name, const char *value) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 149) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 150)   const char *t = txt;
bfc1508d (kx 2023-03-24 03:55:33 +0300 151) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 152)   while( t && *t )
bfc1508d (kx 2023-03-24 03:55:33 +0300 153)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 154)     char *name = url_decode_parameter_name( &t );
bfc1508d (kx 2023-03-24 03:55:33 +0300 155)     if( *name )
bfc1508d (kx 2023-03-24 03:55:33 +0300 156)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 157)       char *value = url_decode_parameter_value( &t );
bfc1508d (kx 2023-03-24 03:55:33 +0300 158)       fn( name, value );
bfc1508d (kx 2023-03-24 03:55:33 +0300 159)       free( value );
bfc1508d (kx 2023-03-24 03:55:33 +0300 160)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 161)     free( name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 162)   }
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) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 166) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 167) #define HTTP_ERRMSG_SIZE 4096
bfc1508d (kx 2023-03-24 03:55:33 +0300 168) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 169) void http_error( const char *fmt, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 170) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 171)   va_list arg_ptr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 172)   char  buf[HTTP_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 173)   char  msg[HTTP_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 174)   char *format = "%s: %s\n";
bfc1508d (kx 2023-03-24 03:55:33 +0300 175) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 176)   va_start( arg_ptr, fmt );
bfc1508d (kx 2023-03-24 03:55:33 +0300 177) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 178)   vsnprintf( msg, HTTP_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
bfc1508d (kx 2023-03-24 03:55:33 +0300 179) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 180)   va_end( arg_ptr ); /* Reset variable arguments. */
bfc1508d (kx 2023-03-24 03:55:33 +0300 181) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 182)   snprintf( buf, HTTP_ERRMSG_SIZE, format, "http", msg );
bfc1508d (kx 2023-03-24 03:55:33 +0300 183) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 184)   (void)write( STDERR_FILENO, buf, strlen( buf ) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 185) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 186)   exit( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 187) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 188) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 189) http_errfunc http_fatal = http_error;
bfc1508d (kx 2023-03-24 03:55:33 +0300 190) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 191) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 192) static struct
bfc1508d (kx 2023-03-24 03:55:33 +0300 193) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 194)   int         code;
bfc1508d (kx 2023-03-24 03:55:33 +0300 195)   const char *desc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 196) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 197) status[] =
bfc1508d (kx 2023-03-24 03:55:33 +0300 198) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 199)   { 100, "Continue" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 200)   { 101, "Switching Protocols" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 201)   { 200, "OK" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 202)   { 201, "Created" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 203)   { 202, "Accepted" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 204)   { 203, "Non-Authoritative Information" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 205)   { 204, "No Content" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 206)   { 205, "Reset Content" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 207)   { 206, "Partial Content" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 208)   { 300, "Multiple Choices" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 209)   { 301, "Moved Permanently" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 210)   { 302, "Found" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 211)   { 303, "See Other" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 212)   { 304, "Not Modified" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 213)   { 305, "Use Proxy" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 214)   { 307, "Temporary Redirect" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 215)   { 400, "Bad Request" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 216)   { 401, "Unauthorized" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 217)   { 402, "Payment Required" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 218)   { 403, "Forbidden" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 219)   { 404, "Not Found" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 220)   { 405, "Method Not Allowed" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 221)   { 406, "Not Acceptable" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 222)   { 407, "Proxy Authentication Required" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 223)   { 408, "Request Timeout" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 224)   { 409, "Conflict" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 225)   { 410, "Gone" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 226)   { 411, "Length Required" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 227)   { 412, "Precondition Failed" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 228)   { 413, "Request Entity Too Large" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 229)   { 414, "Request-URI Too Long" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 230)   { 415, "Unsupported Media Type" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 231)   { 416, "Requested Range Not Satisfiable" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 232)   { 417, "Expectation Failed" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 233)   { 418, "I'm a teapot" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 234)   { 500, "Internal Server Error" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 235)   { 501, "Not Implemented" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 236)   { 502, "Bad Gateway" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 237)   { 503, "Service Unavailable" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 238)   { 504, "Gateway Timeout" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 239)   { 505, "HTTP Version Not Supported" },
bfc1508d (kx 2023-03-24 03:55:33 +0300 240)   {   0, NULL }
bfc1508d (kx 2023-03-24 03:55:33 +0300 241) };
bfc1508d (kx 2023-03-24 03:55:33 +0300 242) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 243) const char *http_status( int status_code )
bfc1508d (kx 2023-03-24 03:55:33 +0300 244) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 245)   int i = 0, code;
bfc1508d (kx 2023-03-24 03:55:33 +0300 246) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 247)   while( (code = status[i].code) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 248)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 249)     if( code == status_code ) return status[i].desc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 250)     ++i;
bfc1508d (kx 2023-03-24 03:55:33 +0300 251)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 252)   return NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 253) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 254) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 255) char *fmt( const char *format, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 256) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 257)   static char buf[8][1024];
bfc1508d (kx 2023-03-24 03:55:33 +0300 258)   static int bufidx;
bfc1508d (kx 2023-03-24 03:55:33 +0300 259)   int len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 260)   va_list args;
bfc1508d (kx 2023-03-24 03:55:33 +0300 261) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 262)   bufidx++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 263)   bufidx &= 7;
bfc1508d (kx 2023-03-24 03:55:33 +0300 264) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 265)   va_start( args, format );
bfc1508d (kx 2023-03-24 03:55:33 +0300 266)   len = vsnprintf( buf[bufidx], sizeof(buf[bufidx]), format, args );
bfc1508d (kx 2023-03-24 03:55:33 +0300 267)   va_end(args);
bfc1508d (kx 2023-03-24 03:55:33 +0300 268)   if( len > sizeof(buf[bufidx]) ) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 269)     http_fatal( "string truncated: %s", format );
bfc1508d (kx 2023-03-24 03:55:33 +0300 270)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 271)   return buf[bufidx];
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) char *fmtalloc( const char *format, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 275) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 276)   struct strbuf sb = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 277)   va_list args;
bfc1508d (kx 2023-03-24 03:55:33 +0300 278) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 279)   va_start( args, format );
bfc1508d (kx 2023-03-24 03:55:33 +0300 280)   strbuf_vaddf( &sb, format, args );
bfc1508d (kx 2023-03-24 03:55:33 +0300 281)   va_end( args );
bfc1508d (kx 2023-03-24 03:55:33 +0300 282) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 283)   return strbuf_detach( &sb, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 284) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 285) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 286) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 287) char *http_date( time_t t )
bfc1508d (kx 2023-03-24 03:55:33 +0300 288) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 289)   static char day[][4] =
bfc1508d (kx 2023-03-24 03:55:33 +0300 290)     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
bfc1508d (kx 2023-03-24 03:55:33 +0300 291)   static char month[][4] =
bfc1508d (kx 2023-03-24 03:55:33 +0300 292)     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
bfc1508d (kx 2023-03-24 03:55:33 +0300 293)       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
bfc1508d (kx 2023-03-24 03:55:33 +0300 294)   struct tm *tm = gmtime(&t);
bfc1508d (kx 2023-03-24 03:55:33 +0300 295)   return fmt( "%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
bfc1508d (kx 2023-03-24 03:55:33 +0300 296)               tm->tm_mday, month[tm->tm_mon], 1900 + tm->tm_year,
bfc1508d (kx 2023-03-24 03:55:33 +0300 297)               tm->tm_hour, tm->tm_min, tm->tm_sec );
bfc1508d (kx 2023-03-24 03:55:33 +0300 298) }