File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / keyvalue.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 10:32:47 2013 UTC (10 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_35p0, v1_4_35, v1_4_33, HEAD
1.4.33

    1: #include "server.h"
    2: #include "keyvalue.h"
    3: #include "log.h"
    4: 
    5: #include <stdlib.h>
    6: #include <string.h>
    7: #include <stdio.h>
    8: 
    9: static keyvalue http_versions[] = {
   10: 	{ HTTP_VERSION_1_1, "HTTP/1.1" },
   11: 	{ HTTP_VERSION_1_0, "HTTP/1.0" },
   12: 	{ HTTP_VERSION_UNSET, NULL }
   13: };
   14: 
   15: static keyvalue http_methods[] = {
   16: 	{ HTTP_METHOD_GET, "GET" },
   17: 	{ HTTP_METHOD_HEAD, "HEAD" },
   18: 	{ HTTP_METHOD_POST, "POST" },
   19: 	{ HTTP_METHOD_PUT, "PUT" },
   20: 	{ HTTP_METHOD_DELETE, "DELETE" },
   21: 	{ HTTP_METHOD_CONNECT, "CONNECT" },
   22: 	{ HTTP_METHOD_OPTIONS, "OPTIONS" },
   23: 	{ HTTP_METHOD_TRACE, "TRACE" },
   24: 	{ HTTP_METHOD_ACL, "ACL" },
   25: 	{ HTTP_METHOD_BASELINE_CONTROL, "BASELINE-CONTROL" },
   26: 	{ HTTP_METHOD_BIND, "BIND" },
   27: 	{ HTTP_METHOD_CHECKIN, "CHECKIN" },
   28: 	{ HTTP_METHOD_CHECKOUT, "CHECKOUT" },
   29: 	{ HTTP_METHOD_COPY, "COPY" },
   30: 	{ HTTP_METHOD_LABEL, "LABEL" },
   31: 	{ HTTP_METHOD_LINK, "LINK" },
   32: 	{ HTTP_METHOD_LOCK, "LOCK" },
   33: 	{ HTTP_METHOD_MERGE, "MERGE" },
   34: 	{ HTTP_METHOD_MKACTIVITY, "MKACTIVITY" },
   35: 	{ HTTP_METHOD_MKCALENDAR, "MKCALENDAR" },
   36: 	{ HTTP_METHOD_MKCOL, "MKCOL" },
   37: 	{ HTTP_METHOD_MKREDIRECTREF, "MKREDIRECTREF" },
   38: 	{ HTTP_METHOD_MKWORKSPACE, "MKWORKSPACE" },
   39: 	{ HTTP_METHOD_MOVE, "MOVE" },
   40: 	{ HTTP_METHOD_ORDERPATCH, "ORDERPATCH" },
   41: 	{ HTTP_METHOD_PATCH, "PATCH" },
   42: 	{ HTTP_METHOD_PROPFIND, "PROPFIND" },
   43: 	{ HTTP_METHOD_PROPPATCH, "PROPPATCH" },
   44: 	{ HTTP_METHOD_REBIND, "REBIND" },
   45: 	{ HTTP_METHOD_REPORT, "REPORT" },
   46: 	{ HTTP_METHOD_SEARCH, "SEARCH" },
   47: 	{ HTTP_METHOD_UNBIND, "UNBIND" },
   48: 	{ HTTP_METHOD_UNCHECKOUT, "UNCHECKOUT" },
   49: 	{ HTTP_METHOD_UNLINK, "UNLINK" },
   50: 	{ HTTP_METHOD_UNLOCK, "UNLOCK" },
   51: 	{ HTTP_METHOD_UPDATE, "UPDATE" },
   52: 	{ HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" },
   53: 	{ HTTP_METHOD_VERSION_CONTROL, "VERSION-CONTROL" },
   54: 
   55: 	{ HTTP_METHOD_UNSET, NULL }
   56: };
   57: 
   58: static keyvalue http_status[] = {
   59: 	{ 100, "Continue" },
   60: 	{ 101, "Switching Protocols" },
   61: 	{ 102, "Processing" }, /* WebDAV */
   62: 	{ 200, "OK" },
   63: 	{ 201, "Created" },
   64: 	{ 202, "Accepted" },
   65: 	{ 203, "Non-Authoritative Information" },
   66: 	{ 204, "No Content" },
   67: 	{ 205, "Reset Content" },
   68: 	{ 206, "Partial Content" },
   69: 	{ 207, "Multi-status" }, /* WebDAV */
   70: 	{ 300, "Multiple Choices" },
   71: 	{ 301, "Moved Permanently" },
   72: 	{ 302, "Found" },
   73: 	{ 303, "See Other" },
   74: 	{ 304, "Not Modified" },
   75: 	{ 305, "Use Proxy" },
   76: 	{ 306, "(Unused)" },
   77: 	{ 307, "Temporary Redirect" },
   78: 	{ 400, "Bad Request" },
   79: 	{ 401, "Unauthorized" },
   80: 	{ 402, "Payment Required" },
   81: 	{ 403, "Forbidden" },
   82: 	{ 404, "Not Found" },
   83: 	{ 405, "Method Not Allowed" },
   84: 	{ 406, "Not Acceptable" },
   85: 	{ 407, "Proxy Authentication Required" },
   86: 	{ 408, "Request Timeout" },
   87: 	{ 409, "Conflict" },
   88: 	{ 410, "Gone" },
   89: 	{ 411, "Length Required" },
   90: 	{ 412, "Precondition Failed" },
   91: 	{ 413, "Request Entity Too Large" },
   92: 	{ 414, "Request-URI Too Long" },
   93: 	{ 415, "Unsupported Media Type" },
   94: 	{ 416, "Requested Range Not Satisfiable" },
   95: 	{ 417, "Expectation Failed" },
   96: 	{ 422, "Unprocessable Entity" }, /* WebDAV */
   97: 	{ 423, "Locked" }, /* WebDAV */
   98: 	{ 424, "Failed Dependency" }, /* WebDAV */
   99: 	{ 426, "Upgrade Required" }, /* TLS */
  100: 	{ 500, "Internal Server Error" },
  101: 	{ 501, "Not Implemented" },
  102: 	{ 502, "Bad Gateway" },
  103: 	{ 503, "Service Not Available" },
  104: 	{ 504, "Gateway Timeout" },
  105: 	{ 505, "HTTP Version Not Supported" },
  106: 	{ 507, "Insufficient Storage" }, /* WebDAV */
  107: 
  108: 	{ -1, NULL }
  109: };
  110: 
  111: static keyvalue http_status_body[] = {
  112: 	{ 400, "400.html" },
  113: 	{ 401, "401.html" },
  114: 	{ 403, "403.html" },
  115: 	{ 404, "404.html" },
  116: 	{ 411, "411.html" },
  117: 	{ 416, "416.html" },
  118: 	{ 500, "500.html" },
  119: 	{ 501, "501.html" },
  120: 	{ 503, "503.html" },
  121: 	{ 505, "505.html" },
  122: 
  123: 	{ -1, NULL }
  124: };
  125: 
  126: 
  127: const char *keyvalue_get_value(keyvalue *kv, int k) {
  128: 	int i;
  129: 	for (i = 0; kv[i].value; i++) {
  130: 		if (kv[i].key == k) return kv[i].value;
  131: 	}
  132: 	return NULL;
  133: }
  134: 
  135: int keyvalue_get_key(keyvalue *kv, const char *s) {
  136: 	int i;
  137: 	for (i = 0; kv[i].value; i++) {
  138: 		if (0 == strcmp(kv[i].value, s)) return kv[i].key;
  139: 	}
  140: 	return -1;
  141: }
  142: 
  143: keyvalue_buffer *keyvalue_buffer_init(void) {
  144: 	keyvalue_buffer *kvb;
  145: 
  146: 	kvb = calloc(1, sizeof(*kvb));
  147: 
  148: 	return kvb;
  149: }
  150: 
  151: int keyvalue_buffer_append(keyvalue_buffer *kvb, int key, const char *value) {
  152: 	size_t i;
  153: 	if (kvb->size == 0) {
  154: 		kvb->size = 4;
  155: 
  156: 		kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
  157: 
  158: 		for(i = 0; i < kvb->size; i++) {
  159: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  160: 		}
  161: 	} else if (kvb->used == kvb->size) {
  162: 		kvb->size += 4;
  163: 
  164: 		kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
  165: 
  166: 		for(i = kvb->used; i < kvb->size; i++) {
  167: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  168: 		}
  169: 	}
  170: 
  171: 	kvb->kv[kvb->used]->key = key;
  172: 	kvb->kv[kvb->used]->value = strdup(value);
  173: 
  174: 	kvb->used++;
  175: 
  176: 	return 0;
  177: }
  178: 
  179: void keyvalue_buffer_free(keyvalue_buffer *kvb) {
  180: 	size_t i;
  181: 
  182: 	for (i = 0; i < kvb->size; i++) {
  183: 		if (kvb->kv[i]->value) free(kvb->kv[i]->value);
  184: 		free(kvb->kv[i]);
  185: 	}
  186: 
  187: 	if (kvb->kv) free(kvb->kv);
  188: 
  189: 	free(kvb);
  190: }
  191: 
  192: 
  193: s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
  194: 	s_keyvalue_buffer *kvb;
  195: 
  196: 	kvb = calloc(1, sizeof(*kvb));
  197: 
  198: 	return kvb;
  199: }
  200: 
  201: int s_keyvalue_buffer_append(s_keyvalue_buffer *kvb, const char *key, const char *value) {
  202: 	size_t i;
  203: 	if (kvb->size == 0) {
  204: 		kvb->size = 4;
  205: 		kvb->used = 0;
  206: 
  207: 		kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
  208: 
  209: 		for(i = 0; i < kvb->size; i++) {
  210: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  211: 		}
  212: 	} else if (kvb->used == kvb->size) {
  213: 		kvb->size += 4;
  214: 
  215: 		kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
  216: 
  217: 		for(i = kvb->used; i < kvb->size; i++) {
  218: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  219: 		}
  220: 	}
  221: 
  222: 	kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
  223: 	kvb->kv[kvb->used]->value = strdup(value);
  224: 
  225: 	kvb->used++;
  226: 
  227: 	return 0;
  228: }
  229: 
  230: void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
  231: 	size_t i;
  232: 
  233: 	for (i = 0; i < kvb->size; i++) {
  234: 		if (kvb->kv[i]->key) free(kvb->kv[i]->key);
  235: 		if (kvb->kv[i]->value) free(kvb->kv[i]->value);
  236: 		free(kvb->kv[i]);
  237: 	}
  238: 
  239: 	if (kvb->kv) free(kvb->kv);
  240: 
  241: 	free(kvb);
  242: }
  243: 
  244: 
  245: httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
  246: 	httpauth_keyvalue_buffer *kvb;
  247: 
  248: 	kvb = calloc(1, sizeof(*kvb));
  249: 
  250: 	return kvb;
  251: }
  252: 
  253: int httpauth_keyvalue_buffer_append(httpauth_keyvalue_buffer *kvb, const char *key, const char *realm, httpauth_type type) {
  254: 	size_t i;
  255: 	if (kvb->size == 0) {
  256: 		kvb->size = 4;
  257: 
  258: 		kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
  259: 
  260: 		for(i = 0; i < kvb->size; i++) {
  261: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  262: 		}
  263: 	} else if (kvb->used == kvb->size) {
  264: 		kvb->size += 4;
  265: 
  266: 		kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
  267: 
  268: 		for(i = kvb->used; i < kvb->size; i++) {
  269: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  270: 		}
  271: 	}
  272: 
  273: 	kvb->kv[kvb->used]->key = strdup(key);
  274: 	kvb->kv[kvb->used]->realm = strdup(realm);
  275: 	kvb->kv[kvb->used]->type = type;
  276: 
  277: 	kvb->used++;
  278: 
  279: 	return 0;
  280: }
  281: 
  282: void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
  283: 	size_t i;
  284: 
  285: 	for (i = 0; i < kvb->size; i++) {
  286: 		if (kvb->kv[i]->key) free(kvb->kv[i]->key);
  287: 		if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
  288: 		free(kvb->kv[i]);
  289: 	}
  290: 
  291: 	if (kvb->kv) free(kvb->kv);
  292: 
  293: 	free(kvb);
  294: }
  295: 
  296: 
  297: const char *get_http_version_name(int i) {
  298: 	return keyvalue_get_value(http_versions, i);
  299: }
  300: 
  301: const char *get_http_status_name(int i) {
  302: 	return keyvalue_get_value(http_status, i);
  303: }
  304: 
  305: const char *get_http_method_name(http_method_t i) {
  306: 	return keyvalue_get_value(http_methods, i);
  307: }
  308: 
  309: const char *get_http_status_body_name(int i) {
  310: 	return keyvalue_get_value(http_status_body, i);
  311: }
  312: 
  313: int get_http_version_key(const char *s) {
  314: 	return keyvalue_get_key(http_versions, s);
  315: }
  316: 
  317: http_method_t get_http_method_key(const char *s) {
  318: 	return (http_method_t)keyvalue_get_key(http_methods, s);
  319: }
  320: 
  321: 
  322: 
  323: 
  324: pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
  325: 	pcre_keyvalue_buffer *kvb;
  326: 
  327: 	kvb = calloc(1, sizeof(*kvb));
  328: 
  329: 	return kvb;
  330: }
  331: 
  332: int pcre_keyvalue_buffer_append(server *srv, pcre_keyvalue_buffer *kvb, const char *key, const char *value) {
  333: #ifdef HAVE_PCRE_H
  334: 	size_t i;
  335: 	const char *errptr;
  336: 	int erroff;
  337: 	pcre_keyvalue *kv;
  338: #endif
  339: 
  340: 	if (!key) return -1;
  341: 
  342: #ifdef HAVE_PCRE_H
  343: 	if (kvb->size == 0) {
  344: 		kvb->size = 4;
  345: 		kvb->used = 0;
  346: 
  347: 		kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
  348: 
  349: 		for(i = 0; i < kvb->size; i++) {
  350: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  351: 		}
  352: 	} else if (kvb->used == kvb->size) {
  353: 		kvb->size += 4;
  354: 
  355: 		kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
  356: 
  357: 		for(i = kvb->used; i < kvb->size; i++) {
  358: 			kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
  359: 		}
  360: 	}
  361: 
  362: 	kv = kvb->kv[kvb->used];
  363: 	if (NULL == (kv->key = pcre_compile(key,
  364: 					  0, &errptr, &erroff, NULL))) {
  365: 
  366: 		log_error_write(srv, __FILE__, __LINE__, "SS",
  367: 			"rexexp compilation error at ", errptr);
  368: 		return -1;
  369: 	}
  370: 
  371: 	if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
  372: 			errptr != NULL) {
  373: 		return -1;
  374: 	}
  375: 
  376: 	kv->value = buffer_init_string(value);
  377: 
  378: 	kvb->used++;
  379: 
  380: 	return 0;
  381: #else
  382: 	UNUSED(kvb);
  383: 	UNUSED(value);
  384: 
  385: 	return -1;
  386: #endif
  387: }
  388: 
  389: void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
  390: #ifdef HAVE_PCRE_H
  391: 	size_t i;
  392: 	pcre_keyvalue *kv;
  393: 
  394: 	for (i = 0; i < kvb->size; i++) {
  395: 		kv = kvb->kv[i];
  396: 		if (kv->key) pcre_free(kv->key);
  397: 		if (kv->key_extra) pcre_free(kv->key_extra);
  398: 		if (kv->value) buffer_free(kv->value);
  399: 		free(kv);
  400: 	}
  401: 
  402: 	if (kvb->kv) free(kvb->kv);
  403: #endif
  404: 
  405: 	free(kvb);
  406: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>