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