-static char empty_string[1] = "";
-
-enum afb_method get_method(const char *method)
-{
- switch (method[0] & ~' ') {
- case 'C':
- return afb_method_connect;
- case 'D':
- return afb_method_delete;
- case 'G':
- return afb_method_get;
- case 'H':
- return afb_method_head;
- case 'O':
- return afb_method_options;
- case 'P':
- switch (method[1] & ~' ') {
- case 'A':
- return afb_method_patch;
- case 'O':
- return afb_method_post;
- case 'U':
- return afb_method_put;
- }
- break;
- case 'T':
- return afb_method_trace;
- }
- return afb_method_none;
-}
-
-#if !defined(MHD_HTTP_METHOD_PATCH)
-#define MHD_HTTP_METHOD_PATCH "PATCH"
-#endif
-const char *get_method_name(enum afb_method method)
-{
- switch (method) {
- case afb_method_get:
- return MHD_HTTP_METHOD_GET;
- case afb_method_post:
- return MHD_HTTP_METHOD_POST;
- case afb_method_head:
- return MHD_HTTP_METHOD_HEAD;
- case afb_method_connect:
- return MHD_HTTP_METHOD_CONNECT;
- case afb_method_delete:
- return MHD_HTTP_METHOD_DELETE;
- case afb_method_options:
- return MHD_HTTP_METHOD_OPTIONS;
- case afb_method_patch:
- return MHD_HTTP_METHOD_PATCH;
- case afb_method_put:
- return MHD_HTTP_METHOD_PUT;
- case afb_method_trace:
- return MHD_HTTP_METHOD_TRACE;
- default:
- return NULL;
- }
-}
-
-/* a valid subpath is a relative path not looking deeper than root using .. */
-static int validsubpath(const char *subpath)
-{
- int l = 0, i = 0;
-
- while (subpath[i]) {
- switch (subpath[i++]) {
- case '.':
- if (!subpath[i])
- break;
- if (subpath[i] == '/') {
- i++;
- break;
- }
- if (subpath[i++] == '.') {
- if (!subpath[i]) {
- if (--l < 0)
- return 0;
- break;
- }
- if (subpath[i++] == '/') {
- if (--l < 0)
- return 0;
- break;
- }
- }
- default:
- while (subpath[i] && subpath[i] != '/')
- i++;
- l++;
- case '/':
- break;
- }
- }
- return 1;
-}
-
-/*
- * Removes the 'prefix' of 'length' frome the tail of 'request'
- * if and only if the prefix exists and is terminated by a leading
- * slash
- */
-int afb_req_unprefix(struct afb_req *request, const char *prefix, size_t length)
-{
- /* check the prefix ? */
- if (length > request->lentail || (request->tail[length] && request->tail[length] != '/')
- || memcmp(prefix, request->tail, length))
- return 0;
-
- /* removes successives / */
- while (length < request->lentail && request->tail[length + 1] == '/')
- length++;
-
- /* update the tail */
- request->lentail -= length;
- request->tail += length;
- return 1;
-}
-
-int afb_req_valid_tail(struct afb_req *request)
-{
- return validsubpath(request->tail);
-}
-
-void afb_req_reply_error(struct afb_req *request, unsigned int status)
-{
- char *buffer;
- int length;
- struct MHD_Response *response;
-
- length = asprintf(&buffer, "<html><body>error %u</body></html>", status);
- if (length > 0)
- response = MHD_create_response_from_buffer((unsigned)length, buffer, MHD_RESPMEM_MUST_FREE);
- else {
- buffer = "<html><body>error</body></html>";
- response = MHD_create_response_from_buffer(strlen(buffer), buffer, MHD_RESPMEM_PERSISTENT);
- }
- if (!MHD_queue_response(request->connection, status, response))
- fprintf(stderr, "Failed to reply error code %u", status);
- MHD_destroy_response(response);
-}
-
-int afb_request_redirect_to(struct afb_req *request, const char *url)
-{
- struct MHD_Response *response;
-
- response = MHD_create_response_from_buffer(0, empty_string, MHD_RESPMEM_PERSISTENT);
- MHD_add_response_header(response, "Location", url);
- MHD_queue_response(request->connection, MHD_HTTP_MOVED_PERMANENTLY, response);
- MHD_destroy_response(response);
- if (verbose)
- fprintf(stderr, "redirect from [%s] to [%s]\n", request->url, url);
- return 1;
-}