📄 connection.c
字号:
char *semicolon; char *equals; int quotes; hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie"); if (hdr == NULL) return MHD_YES; cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES); if (cpy == NULL) { MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); MHD_excessive_data_handler (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); return MHD_NO; } memcpy (cpy, hdr, strlen (hdr) + 1); pos = cpy; while (pos != NULL) { equals = strstr (pos, "="); if (equals == NULL) break; equals[0] = '\0'; equals++; quotes = 0; semicolon = equals; while ((semicolon[0] != '\0') && ((quotes != 0) || ((semicolon[0] != ';') && (semicolon[0] != ',')))) { if (semicolon[0] == '"') quotes = (quotes + 1) & 1; semicolon++; } if (semicolon[0] == '\0') semicolon = NULL; if (semicolon != NULL) { semicolon[0] = '\0'; semicolon++; } /* remove quotes */ if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"')) { equals[strlen (equals) - 1] = '\0'; equals++; } if (MHD_NO == MHD_connection_add_header (connection, pos, equals, MHD_COOKIE_KIND)) return MHD_NO; pos = semicolon; } return MHD_YES;}/** * Parse the first line of the HTTP HEADER. * * @param connection the connection (updated) * @param line the first line * @return MHD_YES if the line is ok, MHD_NO if it is malformed */static intparse_initial_message_line (struct MHD_Connection *connection, char *line){ char *uri; char *httpVersion; char *args; uri = strstr (line, " "); if (uri == NULL) return MHD_NO; /* serious error */ uri[0] = '\0'; connection->method = line; uri++; while (uri[0] == ' ') uri++; httpVersion = strstr (uri, " "); if (httpVersion != NULL) { httpVersion[0] = '\0'; httpVersion++; } args = strstr (uri, "?"); if (args != NULL) { args[0] = '\0'; args++; parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args); } connection->url = uri; if (httpVersion == NULL) connection->version = ""; else connection->version = httpVersion; return MHD_YES;}/** * This function is designed to parse the input buffer of a given connection. * * Once the header is complete, it should have set the * headers_received, url and method values and set * headersReceived to 1. If no body is expected, it should * also set "bodyReceived" to 1. Otherwise, it should * set "uploadSize" to the expected size of the body. If the * size of the body is unknown, it should be set to -1. */static voidMHD_parse_connection_headers (struct MHD_Connection *connection){ char *last; char *line; char *colon; char *tmp; const char *clen; const char *end; unsigned long long cval; if (connection->bodyReceived == 1) abort (); last = NULL; while (NULL != (line = MHD_get_next_header_line (connection))) { if (last != NULL) { if ((line[0] == ' ') || (line[0] == '\t')) { /* value was continued on the next line, see http://www.jmarshall.com/easy/http/ */ last = MHD_pool_reallocate (connection->pool, last, strlen (last) + 1, strlen (line) + strlen (last) + 1); if (last == NULL) { MHD_excessive_data_handler (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); break; } tmp = line; while ((tmp[0] == ' ') || (tmp[0] == '\t')) tmp++; /* skip whitespace at start of 2nd line */ strcat (last, tmp); continue; /* possibly more than 2 lines... */ } else { if (MHD_NO == MHD_connection_add_header (connection, last, colon, MHD_HEADER_KIND)) return; last = NULL; } } if (connection->url == NULL) { /* line must be request line (first line of header) */ if (MHD_NO == parse_initial_message_line (connection, line)) goto DIE; continue; } /* check if this is the end of the header */ if (strlen (line) == 0) { /* end of header */ connection->headersReceived = 1; clen = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH); if (clen != NULL) { if (1 != sscanf (clen, "%llu", &cval)) { MHD_DLOG (connection->daemon, "Failed to parse `%s' header `%s', closing connection.\n", MHD_HTTP_HEADER_CONTENT_LENGTH, clen); goto DIE; } connection->uploadSize = cval; connection->bodyReceived = cval == 0 ? 1 : 0; } else { if (NULL == MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_TRANSFER_ENCODING)) { /* this request does not have a body */ connection->uploadSize = 0; connection->bodyReceived = 1; } else { connection->uploadSize = -1; /* unknown size */ connection->bodyReceived = 0; } } end = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONNECTION); if ((end != NULL) && (0 == strcasecmp (end, "close"))) { /* other side explicitly requested that we close the connection after this request */ connection->read_close = MHD_YES; } break; } /* line should be normal header line, find colon */ colon = strstr (line, ":"); if (colon == NULL) { /* error in header line, die hard */ MHD_DLOG (connection->daemon, "Received malformed line (no colon), closing connection.\n"); goto DIE; } /* zero-terminate header */ colon[0] = '\0'; colon++; /* advance to value */ while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t'))) colon++; /* we do the actual adding of the connection header at the beginning of the while loop since we need to be able to inspect the *next* header line (in case it starts with a space...) */ last = line; } if ((last != NULL) && (MHD_NO == MHD_connection_add_header (connection, last, colon, MHD_HEADER_KIND))) return; /* error */ MHD_parse_cookie_header (connection); return;DIE: CLOSE (connection->socket_fd); connection->socket_fd = -1;}/** * Find the handler responsible for this request. */static struct MHD_Access_Handler *MHD_find_access_handler (struct MHD_Connection *connection){ struct MHD_Access_Handler *pos; pos = connection->daemon->handlers; while (pos != NULL) { if (0 == strcmp (connection->url, pos->uri_prefix)) return pos; pos = pos->next; } return &connection->daemon->default_handler;}/** * Test if we are able to process the POST data. * This depends on available memory (enough to load * all of the POST data into the pool) and the * content encoding of the POST data. And of course, * this requires that the request is actually a * POST request. * * @return MHD_YES if so */static intMHD_test_post_data (struct MHD_Connection *connection){ const char *encoding; void *buf; if ((connection->method == NULL) || (connection->response != NULL) || (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST))) return MHD_NO; encoding = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_TYPE); if (encoding == NULL) return MHD_NO; if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding)) && (connection->uploadSize != -1)) { buf = MHD_pool_reallocate (connection->pool, connection->read_buffer, connection->read_buffer_size, connection->uploadSize + 1); if (buf == NULL) return MHD_NO; connection->read_buffer_size = connection->uploadSize + 1; connection->read_buffer = buf; return MHD_YES; } return MHD_NO;}/** * Process the POST data here (adding to headers). * * Needs to first check POST encoding and then do * the right thing (TM). The POST data is in the * connection's post_data buffer between the postPos * and postLoc offsets. The POST message maybe * incomplete. The existing buffer (allocated from * the pool) can be used and modified but must then * be properly removed from the struct. * * @return MHD_YES on success, MHD_NO on error (i.e. out of * memory). */static intMHD_parse_post_data (struct MHD_Connection *connection){ const char *encoding; int ret; encoding = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_TYPE); if (encoding == NULL) return MHD_NO; if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding)) { ret = parse_arguments (MHD_POSTDATA_KIND, connection, connection->read_buffer); /* invalidate read buffer for other uses -- in particular, do not give it to the client; if this were to be needed, we would have to make a copy, which would double memory requirements */ connection->read_buffer_size = 0; connection->readLoc = 0; connection->uploadSize = 0; connection->read_buffer = NULL; return ret; } if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding)) { /* this code should never been reached right now, since the test_post_data function would already return MHD_NO; code is here only for future extensions... */ /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */ MHD_DLOG (connection->daemon, "Unsupported multipart encoding of POST data specified, not processing POST data.\n"); return MHD_NO; } /* this should never be reached, just here for error checking */ MHD_DLOG (connection->daemon, "Unknown encoding of POST data specified, not processing POST data.\n"); return MHD_NO;}/** * Call the handler of the application for this * connection. */voidMHD_call_connection_handler (struct MHD_Connection *connection){ struct MHD_Access_Handler *ah; unsigned int processed; if (connection->response != NULL) return; /* already queued a response */ if (connection->headersReceived == 0) abort (); /* bad timing... */ ah = MHD_find_access_handler (connection); processed = connection->readLoc; if (MHD_NO == ah->dh (ah->dh_cls, connection, connection->url, connection->method, connection->version, connection->read_buffer, &processed)) { /* serios internal error, close connection */ MHD_DLOG (connection->daemon, "Internal application error, closing connection.\n"); CLOSE (connection->socket_fd); connection->socket_fd = -1; return; } /* dh left "processed" bytes in buffer for next time... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -