cGit-UI for Git Repositories

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

12 Commits   0 Branches   1 Tag
     5         kx 
     5         kx #ifdef HAVE_CONFIG_H
     5         kx #include <config.h>
     5         kx #endif
     5         kx 
     5         kx #include <stdlib.h>
     5         kx #include <stdio.h>
     5         kx #include <sys/sysinfo.h>
     5         kx #include <sys/types.h>
     5         kx #include <stdint.h>
     5         kx #include <dirent.h>
     5         kx #include <sys/stat.h> /* chmod(2)    */
     5         kx #include <sys/file.h>
     5         kx #include <sys/mman.h>
     5         kx #include <fcntl.h>
     5         kx #include <limits.h>
     5         kx #include <string.h>   /* strdup(3)   */
     5         kx #include <libgen.h>   /* basename(3) */
     5         kx #include <ctype.h>    /* tolower(3)  */
     5         kx #include <errno.h>
     5         kx #include <time.h>
     5         kx #include <sys/time.h>
     5         kx #include <pwd.h>
     5         kx #include <grp.h>
     5         kx #include <stdarg.h>
     5         kx #include <unistd.h>
     5         kx 
     5         kx #include <defs.h>
     5         kx #include <fatal.h>
     5         kx #include <http.h>
     5         kx #include <html.h>
     5         kx #include <strbuf.h>
     5         kx 
     5         kx 
     5         kx const signed char hexval_table[256] = {
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 00-07 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 08-0f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 10-17 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 18-1f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 20-27 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 28-2f */
     5         kx    0,  1,  2,  3,  4,  5,  6,  7,  /* 30-37 */
     5         kx    8,  9, -1, -1, -1, -1, -1, -1,  /* 38-3f */
     5         kx   -1, 10, 11, 12, 13, 14, 15, -1,  /* 40-47 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 48-4f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 50-57 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 58-5f */
     5         kx   -1, 10, 11, 12, 13, 14, 15, -1,  /* 60-67 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 68-67 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 70-77 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 78-7f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 80-87 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 88-8f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 90-97 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* 98-9f */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* a0-a7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* a8-af */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* b0-b7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* b8-bf */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* c0-c7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* c8-cf */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* d0-d7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* d8-df */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* e0-e7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* e8-ef */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* f0-f7 */
     5         kx   -1, -1, -1, -1, -1, -1, -1, -1,  /* f8-ff */
     5         kx };
     5         kx 
     5         kx 
     5         kx static char *
     5         kx url_decode_internal( const char **query, int len,
     5         kx                      const char *stop_at, struct strbuf *out,
     5         kx                      int decode_plus )
     5         kx {
     5         kx   const char *q = *query;
     5         kx 
     5         kx   while( len )
     5         kx   {
     5         kx     unsigned char c = *q;
     5         kx 
     5         kx     if( !c )
     5         kx       break;
     5         kx     if( stop_at && strchr( stop_at, c ) )
     5         kx     {
     5         kx       ++q;
     5         kx       --len;
     5         kx       break;
     5         kx     }
     5         kx 
     5         kx     if( c == '%' && (len < 0 || len >= 3) )
     5         kx     {
     5         kx       int val = hex2chr( q + 1 );
     5         kx       if( 0 < val )
     5         kx       {
     5         kx         strbuf_addch( out, val );
     5         kx         q += 3;
     5         kx         len -= 3;
     5         kx         continue;
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( decode_plus && c == '+' )
     5         kx       strbuf_addch( out, ' ' );
     5         kx     else
     5         kx       strbuf_addch( out, c );
     5         kx     ++q;
     5         kx     --len;
     5         kx   }
     5         kx   *query = q;
     5         kx 
     5         kx   return strbuf_detach( out, NULL );
     5         kx }
     5         kx 
     5         kx char *url_decode_mem( const char *url, int len )
     5         kx {
     5         kx   struct strbuf out = STRBUF_INIT;
     5         kx   const char *colon = memchr( url, ':', len );
     5         kx 
     5         kx   /* Skip protocol part if present */
     5         kx   if( colon && url < colon )
     5         kx   {
     5         kx     strbuf_add( &out, url, colon - url );
     5         kx     len -= colon - url;
     5         kx     url = colon;
     5         kx   }
     5         kx   return url_decode_internal( &url, len, NULL, &out, 0 );
     5         kx }
     5         kx 
     5         kx char *url_percent_decode( const char *encoded )
     5         kx {
     5         kx   struct strbuf out = STRBUF_INIT;
     5         kx   return url_decode_internal( &encoded, strlen(encoded), NULL, &out, 0 );
     5         kx }
     5         kx 
     5         kx char *url_decode_parameter_name( const char **query )
     5         kx {
     5         kx   struct strbuf out = STRBUF_INIT;
     5         kx   return url_decode_internal( query, -1, "&=", &out, 1 );
     5         kx }
     5         kx 
     5         kx char *url_decode_parameter_value( const char **query )
     5         kx {
     5         kx   struct strbuf out = STRBUF_INIT;
     5         kx   return url_decode_internal( query, -1, "&", &out, 1 );
     5         kx }
     5         kx 
     5         kx void http_parse_querystring( const char *txt, void (*fn)(const char *name, const char *value) )
     5         kx {
     5         kx   const char *t = txt;
     5         kx 
     5         kx   while( t && *t )
     5         kx   {
     5         kx     char *name = url_decode_parameter_name( &t );
     5         kx     if( *name )
     5         kx     {
     5         kx       char *value = url_decode_parameter_value( &t );
     5         kx       fn( name, value );
     5         kx       free( value );
     5         kx     }
     5         kx     free( name );
     5         kx   }
     5         kx }
     5         kx 
     5         kx 
     5         kx 
     5         kx #define HTTP_ERRMSG_SIZE 4096
     5         kx 
     5         kx void http_error( const char *fmt, ... )
     5         kx {
     5         kx   va_list arg_ptr;
     5         kx   char  buf[HTTP_ERRMSG_SIZE];
     5         kx   char  msg[HTTP_ERRMSG_SIZE];
     5         kx   char *format = "%s: %s\n";
     5         kx 
     5         kx   va_start( arg_ptr, fmt );
     5         kx 
     5         kx   vsnprintf( msg, HTTP_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
     5         kx 
     5         kx   va_end( arg_ptr ); /* Reset variable arguments. */
     5         kx 
     5         kx   snprintf( buf, HTTP_ERRMSG_SIZE, format, "http", msg );
     5         kx 
     5         kx   (void)write( STDERR_FILENO, buf, strlen( buf ) );
     5         kx 
     5         kx   exit( 1 );
     5         kx }
     5         kx 
     5         kx http_errfunc http_fatal = http_error;
     5         kx 
     5         kx 
     5         kx static struct
     5         kx {
     5         kx   int         code;
     5         kx   const char *desc;
     5         kx }
     5         kx status[] =
     5         kx {
     5         kx   { 100, "Continue" },
     5         kx   { 101, "Switching Protocols" },
     5         kx   { 200, "OK" },
     5         kx   { 201, "Created" },
     5         kx   { 202, "Accepted" },
     5         kx   { 203, "Non-Authoritative Information" },
     5         kx   { 204, "No Content" },
     5         kx   { 205, "Reset Content" },
     5         kx   { 206, "Partial Content" },
     5         kx   { 300, "Multiple Choices" },
     5         kx   { 301, "Moved Permanently" },
     5         kx   { 302, "Found" },
     5         kx   { 303, "See Other" },
     5         kx   { 304, "Not Modified" },
     5         kx   { 305, "Use Proxy" },
     5         kx   { 307, "Temporary Redirect" },
     5         kx   { 400, "Bad Request" },
     5         kx   { 401, "Unauthorized" },
     5         kx   { 402, "Payment Required" },
     5         kx   { 403, "Forbidden" },
     5         kx   { 404, "Not Found" },
     5         kx   { 405, "Method Not Allowed" },
     5         kx   { 406, "Not Acceptable" },
     5         kx   { 407, "Proxy Authentication Required" },
     5         kx   { 408, "Request Timeout" },
     5         kx   { 409, "Conflict" },
     5         kx   { 410, "Gone" },
     5         kx   { 411, "Length Required" },
     5         kx   { 412, "Precondition Failed" },
     5         kx   { 413, "Request Entity Too Large" },
     5         kx   { 414, "Request-URI Too Long" },
     5         kx   { 415, "Unsupported Media Type" },
     5         kx   { 416, "Requested Range Not Satisfiable" },
     5         kx   { 417, "Expectation Failed" },
     5         kx   { 418, "I'm a teapot" },
     5         kx   { 500, "Internal Server Error" },
     5         kx   { 501, "Not Implemented" },
     5         kx   { 502, "Bad Gateway" },
     5         kx   { 503, "Service Unavailable" },
     5         kx   { 504, "Gateway Timeout" },
     5         kx   { 505, "HTTP Version Not Supported" },
     5         kx   {   0, NULL }
     5         kx };
     5         kx 
     5         kx const char *http_status( int status_code )
     5         kx {
     5         kx   int i = 0, code;
     5         kx 
     5         kx   while( (code = status[i].code) )
     5         kx   {
     5         kx     if( code == status_code ) return status[i].desc;
     5         kx     ++i;
     5         kx   }
     5         kx   return NULL;
     5         kx }
     5         kx 
     5         kx char *fmt( const char *format, ... )
     5         kx {
     5         kx   static char buf[8][1024];
     5         kx   static int bufidx;
     5         kx   int len;
     5         kx   va_list args;
     5         kx 
     5         kx   bufidx++;
     5         kx   bufidx &= 7;
     5         kx 
     5         kx   va_start( args, format );
     5         kx   len = vsnprintf( buf[bufidx], sizeof(buf[bufidx]), format, args );
     5         kx   va_end(args);
     5         kx   if( len > sizeof(buf[bufidx]) ) {
     5         kx     http_fatal( "string truncated: %s", format );
     5         kx   }
     5         kx   return buf[bufidx];
     5         kx }
     5         kx 
     5         kx char *fmtalloc( const char *format, ... )
     5         kx {
     5         kx   struct strbuf sb = STRBUF_INIT;
     5         kx   va_list args;
     5         kx 
     5         kx   va_start( args, format );
     5         kx   strbuf_vaddf( &sb, format, args );
     5         kx   va_end( args );
     5         kx 
     5         kx   return strbuf_detach( &sb, NULL );
     5         kx }
     5         kx 
     5         kx 
     5         kx char *http_date( time_t t )
     5         kx {
     5         kx   static char day[][4] =
     5         kx     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
     5         kx   static char month[][4] =
     5         kx     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     5         kx       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
     5         kx   struct tm *tm = gmtime(&t);
     5         kx   return fmt( "%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
     5         kx               tm->tm_mday, month[tm->tm_mon], 1900 + tm->tm_year,
     5         kx               tm->tm_hour, tm->tm_min, tm->tm_sec );
     5         kx }