📄 http-core.c
字号:
break; case 403: txt = "Forbidden"; break; case 404: txt = "Not Found"; break; case 405: txt = "Method Not Allowed"; break; case 406: txt = "Not Acceptable"; break; case 407: txt = "Proxy Authentication Required"; break; case 408: txt = "Request Timeout"; break; case 409: txt = "Conflict"; break; case 410: txt = "Gone"; break; case 411: txt = "Length Required"; break; case 412: txt = "Precondition Failed"; break; case 413: txt = "Request Entity Too Large"; break; case 414: txt = "Request-URI Too Long"; break; case 415: txt = "Unsupported Media Type"; break; case 416: txt = "Requested Range Not Satisfiable"; break; case 417: txt = "Expectation Failed"; break; case 500: txt = "Internal Server Error"; break; case 501: txt = "Not Implemented"; break; case 502: txt = "Bad Gateway"; break; case 503: txt = "Service Unavailable"; break; case 504: txt = "Gateway Timeout"; break; case 505: txt = "HTTP Version Not Supported"; break; default: txt = "Bad Request"; } http->response = response; /* Send some standard error message. */ return svz_sock_printf (sock, "<html><body bgcolor=white text=black><br>" "<h1>%d %s</h1>" "<hr noshade><i>%s/%s server at %s port %d, " "please send email to <a href=\"mailto:%s\">%s</a> " "for reporting errors</i>" "</body></html>", response, txt, svz_library, svz_version, cfg->host ? cfg->host : svz_inet_ntoa (sock->local_addr), ntohs (sock->local_port), cfg->admin, cfg->admin);}/* * This function is used to re-initialize a HTTP connection for * Keep-Alive connections. Return -1 if it is not 'Keep'able. */inthttp_keep_alive (svz_socket_t *sock){ if (sock->userflags & HTTP_FLAG_KEEP) { http_free_socket (sock); sock->userflags &= ~HTTP_FLAG; sock->read_socket = svz_tcp_read_socket; sock->check_request = http_check_request; sock->write_socket = http_default_write; sock->send_buffer_fill = 0; sock->idle_func = http_idle;#if ENABLE_DEBUG svz_log (LOG_DEBUG, "http: keeping connection alive\n");#endif return 0; } return -1;}/* * This function is used to check if the connection in SOCK is a * Keep-Alive connection and sends the appropriate HTTP header property. */voidhttp_check_keepalive (svz_socket_t *sock){ http_socket_t *http = sock->data; http_config_t *cfg = sock->cfg; if ((sock->userflags & HTTP_FLAG_KEEP) && http->keepalive > 0) { sock->idle_counter = cfg->timeout; http_add_header ("Connection: Keep-Alive\r\n"); http_add_header ("Keep-Alive: timeout=%d, max=%d\r\n", sock->idle_counter, cfg->keepalive); http->keepalive--; } /* tell HTTP/1.1 clients that the connection is closed after delivery */ else { sock->userflags &= ~HTTP_FLAG_KEEP; http_add_header ("Connection: close\r\n"); }}/* * Create a date format used within the Common Log Format. That is as * follows: [DD/MMM/YYYY:HH:MM:SS +ZZZZ] */char *http_clf_date (time_t t){ static char date[64]; static char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tm *tm; tm = localtime (&t); sprintf (date, "%02d/%s/%04d:%02d:%02d:%02d %c%02ld%02ld", tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, timezone > 0 ? '+' : '-', timezone > 0 ? timezone / 3600 : -timezone / 3600, timezone > 0 ? (timezone / 60) % 60 : -(timezone / 60) % 60); return date;}/* * Produce a ASCTIME date without the trailing '\n' from a given time_t. */char *http_asc_date (time_t t){ static char asc[64]; struct tm * gm_time; gm_time = gmtime (&t); strftime (asc, 64, "%a, %d %b %Y %H:%M:%S GMT", gm_time); return asc;}/* * Extract a date information from a given string and return a * UTC time (time_t) as time() does. */time_thttp_parse_date (char *date){ struct tm parse_time; int n; char _month[4]; char _wkday[10]; time_t ret; static char month[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; switch (date[3]) { /* ASCTIME-Date */ case ' ': sscanf (date, "%3s %3s %2d %02d:%02d:%02d %04d", _wkday, _month, &parse_time.tm_mday, &parse_time.tm_hour, &parse_time.tm_min, &parse_time.tm_sec, &parse_time.tm_year); break; /* RFC1123-Date */ case ',': sscanf (date, "%3s, %02d %3s %04d %02d:%02d:%02d GMT", _wkday, &parse_time.tm_mday, _month, &parse_time.tm_year, &parse_time.tm_hour, &parse_time.tm_min, &parse_time.tm_sec); break; /* RFC850-Date */ default: sscanf (date, "%s, %02d-%3s-%02d %02d:%02d:%02d GMT", _wkday, &parse_time.tm_mday, _month, &parse_time.tm_year, &parse_time.tm_hour, &parse_time.tm_min, &parse_time.tm_sec); parse_time.tm_mon += parse_time.tm_mon >= 70 ? 1900 : 2000; break; } /* find the month identifier */ for (n = 0; n < 12; n++) if (!memcmp (_month, month[n], 3)) parse_time.tm_mon = n; parse_time.tm_isdst = daylight; parse_time.tm_year -= 1900; ret = mktime (&parse_time); ret -= timezone; if (daylight > 0) ret += 3600; return ret;}/* * Parse part of the receive buffer for HTTP request properties * and store it in the socket structure SOCK. Return the amount of * properties found in the request. */inthttp_parse_property (svz_socket_t *sock, char *request, char *end){ int properties, n; char *p; http_socket_t *http; /* get the http socket structure */ http = sock->data; /* reserve data space for the http properties */ http->property = svz_malloc (MAX_HTTP_PROPERTIES * 2 * sizeof (char *)); properties = 0; n = 0; /* find out properties if necessary */ while (SVZ_INT16 (request) != CRLF && properties < MAX_HTTP_PROPERTIES - 1) { /* get property entity identifier */ p = request; while (*p != ':' && p < end) p++; if (p == end) break; http->property[n] = svz_malloc (p - request + 1); strncpy (http->property[n], request, p - request); http->property[n][p - request] = 0; n++; request = p + 2; /* get property entity body */ while (SVZ_INT16 (p) != CRLF && p < end) p++; if (p == end || p <= request) break; http->property[n] = svz_malloc (p - request + 1); strncpy (http->property[n], request, p - request); http->property[n][p - request] = 0; n++; properties++; request = p + 2;#if 0 printf ("http header: {%s} = {%s}\n", http->property[n - 2], http->property[n - 1]);#endif } request += 2; http->property[n] = NULL; return properties;}/* * Find a given property entity in the HTTP request properties. * Return a NULL pointer if not found. */char *http_find_property (http_socket_t *http, char *key){ int n; /* check if there are any properties */ if (http->property == NULL) return NULL; /* search through all the http properties */ n = 0; while (http->property[n]) { if (!svz_strcasecmp (http->property[n], key)) { return http->property[n + 1]; } n += 2; } return NULL;}#define ASC_TO_HEX(c) \ if (c >= '0' && c <= '9') c -= '0'; \ else if (c >= 'a' && c <= 'f') c -= ('a' - 10); \ else if (c >= 'A' && c <= 'F') c -= ('A' - 10);/* * Convert hexadecimal encoded characters within the URI. This is * necessary for some special characters. The URI is a Uniform Resource * Identifier meaning the requested file. */voidhttp_process_uri (char *uri){ char *p; char h, l; /* Test if there is any occurrence of the special character encoding. */ while ((p = strchr (uri, '%')) != NULL) { if ((h = *(p + 1)) != 0 && (l = *(p + 2)) != 0) { /* Convert to byte. */ ASC_TO_HEX (h); ASC_TO_HEX (l); *p = (char) ((h << 4) | l); /* Copy rest of URI. */ uri = ++p; while (*(p + 2)) { *p = *(p + 2); p++; } *p = '\0'; } else break; }}/* * This routine gets all available content types from a given * file which should have kind of "/etc/mime.types"s format. */#define TYPES_LINE_SIZE 1024inthttp_read_types (http_config_t *cfg){ FILE *f; char *line; char *p, *end; char *content; char *suffix; char *content_type; /* create the content type hash table if necessary */ if (cfg->types == NULL) cfg->types = svz_hash_create (4); /* try open the file */ if ((f = svz_fopen (cfg->type_file, "rt")) == NULL) { return -1; } line = svz_malloc (TYPES_LINE_SIZE); /* read all lines within the file */ while ((fgets (line, TYPES_LINE_SIZE, f)) != NULL) { /* delete all trailing newline characters, skip empty lines */ p = line + strlen (line) - 1; while (p != line && (*p == '\r' || *p == '\n')) p--; if (p == line) continue; *(p + 1) = 0; p = line; end = line + strlen (line); /* parse content type */ content = line; while (p < end && (*p != ' ' && *p != '\t')) p++; *p++ = 0; /* parse all file suffixes associated with this content type */ while (p < end) { while (p < end && (*p == ' ' || *p == '\t')) p++; if (p == end) break; suffix = p; while (p < end && (*p != ' ' && *p != '\t')) p++; *p++ = 0; if (strlen (suffix)) { /* * add the given content type to the hash if it does not * contain it already */ if (!svz_hash_get (cfg->types, suffix)) { content_type = svz_malloc (strlen (content) + 1); strcpy (content_type, content); svz_hash_put (cfg->types, suffix, content_type); } } } } svz_fclose (f); svz_free (line); return 0;}/* * This routine delivers a valid content type for a given file. * It falls back to the socket's http configuration default content * type if the suffix could not be found. */char *http_find_content_type (svz_socket_t *sock, char *file){ http_config_t *cfg = sock->cfg; char *suffix = file + strlen (file) - 1; char *type; /* parse file back until a trailing '.' */ while (suffix > file && *suffix != '.') suffix--; if (suffix != file) suffix++; /* find this file suffix in the content type hash */ if ((type = svz_hash_get (cfg->types, suffix)) != NULL) { return type; } return cfg->default_type;}/* * This routine converts a relative file/path name into an * absolute file/path name. The given argument will be reallocated * if necessary. */char *http_absolute_file (char *file){ char *savedir; char *p; char *savefile; char *dir; int have_path = 0; /* find any path separator in the file */ p = file + strlen (file) - 1; while (p > file && *p != '/' && *p != '\\') p--; if (*p == '/' || *p == '\\') { have_path = 1; p++; } /* save the filename within a buffer */ savefile = svz_strdup (p); /* get current work directory */ savedir = svz_getcwd (); /* * If there was no path separator in the filename then just concate * current work directory and filename. */ if (!have_path) { savedir = svz_realloc (savedir, strlen (savedir) + strlen (file) + 2); strcat (savedir, "/"); strcat (savedir, savefile); svz_free (file); return savedir; } /* change to give directory (absolute or relative) */ *p = 0; if (chdir (file) == -1) { *p = '/'; svz_log (LOG_ERROR, "chdir: %s\n", SYS_ERROR);#if ENABLE_DEBUG svz_log (LOG_DEBUG, "cannot change dir: %s\n", file);#endif svz_free (savefile); svz_free (savedir); return file; } *p = '/'; /* get now the current work directory */ dir = svz_getcwd (); /* concate new work directory with given filename */ dir = svz_realloc (dir, strlen (dir) + strlen (savefile) + 2); strcat (dir, "/"); strcat (dir, savefile); svz_free (savefile); svz_free (file); /* change back to the original work directory */ chdir (savedir); svz_free (savedir); return dir;}#else /* ENABLE_HTTP_PROTO */int http_core_dummy; /* Shut compiler warnings up. */#endif /* not ENABLE_HTTP_PROTO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -