/** * Create a command object based on incoming request details **/ Cmd* CmdManager::dispatch( struct MHD_Connection* connection, const char* url, const char* method ) { if (strcmp(url, "/echo") == 0) { const char *val = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "msg"); if (val) { return new CmdEcho(std::string(val)); } } if (strcmp(url, "/stats") == 0) { return new CmdStats(); } if (strcmp(url, "/env/day-night") == 0) { float target_val = atof(MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "val")); float total_time = atof(MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "time")); return new CmdDayNightAnimate(target_val, total_time); } return NULL; }
static void _put_check_headers(struct MHD_Connection *connection, GHashTable *wanted_headers) { GHashTableIter iter; gpointer key, value; const gchar *rec_value; g_hash_table_iter_init(&iter, wanted_headers); while (g_hash_table_iter_next(&iter, &key, &value)) { rec_value = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, key); g_assert(rec_value != NULL && "Missing required header"); g_assert_cmpstr(value, ==, rec_value); } }
/** * Return the session handle for this connection, or * create one if this is a new user. */ static struct Session * get_session (struct MHD_Connection *connection) { struct Session *ret; const char *cookie; cookie = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, COOKIE_NAME); if (cookie != NULL) { /* find existing session */ ret = sessions; while (NULL != ret) { if (0 == strcmp (cookie, ret->sid)) break; ret = ret->next; } if (NULL != ret) { ret->rc++; return ret; } } /* create fresh session */ ret = calloc (1, sizeof (struct Session)); if (NULL == ret) { fprintf (stderr, "calloc error: %s\n", strerror (errno)); return NULL; } /* not a super-secure way to generate a random session ID, but should do for a simple example... */ snprintf (ret->sid, sizeof (ret->sid), "%X%X%X%X", (unsigned int) random (), (unsigned int) random (), (unsigned int) random (), (unsigned int) random ()); ret->rc++; ret->start = time (NULL); ret->next = sessions; sessions = ret; return ret; }
void RESTRequestState::set_callback_response(RESTContentReaderCallback rsp_writer, const char* content_type) { const char* accept_enc = MHD_lookup_connection_value(get_conn(), MHD_HEADER_KIND, "Accept-Encoding"); bool use_gzip = accept_enc && strstr(accept_enc, "gzip"); set_response(MHD_create_response_from_callback( -1, RESPONSE_BLOCK_SIZE, callback_write, new ContentReaderState(rsp_writer, get_free_callback(), get_callback_data(), use_gzip), callback_free)); MHD_add_response_header(get_response(), "Content-Type", content_type); if (use_gzip) MHD_add_response_header(get_response(), "Content-Encoding", "gzip"); /* libmicrohttpd will call the appropriate callback to free the data instead of us */ set_free_callback(NULL); }
/** * Gets all data from a list of hash obtained from X-Get-Hash-Array HTTP * header. * @param server_struct is the main structure for the server. * @param connection is the connection in MHD * @returns a newlly allocated gchar * string that contains the anwser to be * sent back to the client (hopefully a json string containing * a hash (that is a fake one here), data and size of the data. */ static gchar *get_data_from_a_list_of_hashs(server_struct_t *server_struct, struct MHD_Connection *connection) { const char *header = NULL; gchar *answer = NULL; gchar *hash = NULL; GList *head = NULL; GList *header_hdl = NULL; GList *hash_data_list = NULL; hash_data_t *header_hd = NULL; hash_data_t *hash_data = NULL; backend_t *backend = server_struct->backend; guint size = 0; header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "X-Get-Hash-Array"); header_hdl = make_hash_data_list_from_string((gchar *)header); head = header_hdl; while (header_hdl != NULL) { header_hd = header_hdl->data; hash = hash_to_string(header_hd->hash); hash_data = backend->retrieve_data(server_struct, hash); free_variable(hash); size = size + hash_data->read; hash_data_list = g_list_prepend(hash_data_list, hash_data); header_hdl = g_list_next(header_hdl); } g_list_free_full(head, free_hdt_struct); hash_data_list = g_list_reverse(hash_data_list); head = hash_data_list; hash_data = create_one_hash_data_t_from_hash_data_list(hash_data_list, size); g_list_free_full(head, free_hdt_struct); answer = convert_hash_data_t_to_string(hash_data); free_hash_data_t(hash_data); return answer; }
static int handle_request(void* /*cls*/, MHD_Connection* connection, const char* url, const char* method, const char*, const char*, unsigned int*, void** /*con_cls*/) { if (std::string(method) != "GET") { return report_error(connection, MHD_HTTP_NOT_IMPLEMENTED, "501 Not Implemented"); } if (mp3d_debug_httpd) { MHD_get_connection_values(connection, MHD_HEADER_KIND, dump_key, NULL); MHD_get_connection_values(connection, MHD_COOKIE_KIND, dump_key, NULL); MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, dump_key, NULL); std::cout << "*** " << method << " request for '" << url << "'" << std::endl; } const char* q = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "mp3d_q"); const std::string request_url(url); if (request_url == "/") { std::string page_data; make_main_page(page_data, q); return send_string_response(connection, MHD_HTTP_OK, page_data); } else if (boost::starts_with(request_url, "/static/")) { StringStringMap::const_iterator it = static_file_map.find(request_url); if (it == static_file_map.end()) { return report_error(connection, MHD_HTTP_NOT_FOUND, "404 Not Found"); } return send_string_response(connection, MHD_HTTP_OK, it->second); } else if (boost::starts_with(request_url, "/play/")) { const size_t id = strtoul(request_url.substr(6).c_str(), 0, 10); // FIXME: error checking. play_queue.clear(); play_queue.push_back(all_mp3s[id]); // FIXME: lookup by id (don't assume id == index). return see_other(connection, "/"); } else if (boost::starts_with(request_url, "/add/")) { const size_t id = strtoul(request_url.substr(5).c_str(), 0, 10); // FIXME: error checking. play_queue.push_back(all_mp3s[id]); // FIXME: lookup by id (don't assume id == index). return see_other(connection, "/"); } else if (boost::starts_with(request_url, "/remove/")) { const size_t id = strtoul(request_url.substr(8).c_str(), 0, 10); // FIXME: error checking. play_queue.remove(id); // FIXME: is this set-like behavior the behavior we want? return see_other(connection, "/"); } else { return report_error(connection, MHD_HTTP_NOT_FOUND, "404 Not Found"); } }
static int serveMasterNameXML (const void *cls, const char *mime, struct Session *session, struct MHD_Connection *connection) { int ret; //char *reply; struct MHD_Response *response; const char *pCmd = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "Cmd"); printf("Cmd = %s\n", pCmd); // The XML is filled up by the CommandDispatcher using a static string object. // Since this is a .c file, we cannot use class objects here, so we basically // extract a char point from it. const char *pString; // Dispatch the command CommandDispatcher(&pString, pCmd); //strcpy(pString, MASTER_NAME); //sprintf(pString, reply, String); //free(reply); fprintf(stdout, "%s\n", pString); /* return static form */ response = MHD_create_response_from_buffer (strlen (pString), (void *) pString, MHD_RESPMEM_PERSISTENT); if (NULL == response) return MHD_NO; add_session_cookie (session, response); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_ENCODING, mime); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; }
/** * Performs lookup values for given keys. * For GET requests, we will use the libmicrohttpd's * internal API: MHD_lookup_connection_value(). * For POST requests, we will retrieve the value from * the slinkedl_list that was created and populated by * the post_iterator(). * * @param connection Pointer to the MHD_Connection * @param key The key for which we need to retrieve * the value. * @param con_cls This is a pointer to the slinkedl_list * that was passed back and forth via * several callback between the application * and the libmicrohttpd library. * @param val Pointer to the value that we are looking * for. */ void httpd_lookup_arg(void *connection, const char *key, void *con_cls, str *val) { slinkedl_list_t *list = (slinkedl_list_t*)con_cls; if (val) { if (list==NULL) { val->s = (char *)MHD_lookup_connection_value( (struct MHD_Connection *)connection, MHD_GET_ARGUMENT_KIND, key); if (val->s) val->len = strlen(val->s); else val->len = 0; } else { slinkedl_traverse(list, &httpd_get_val, (void *)key, val); } } else { LM_ERR("NULL holder for requested val\n"); } return; }
static int ahc_echo (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { static int aptr; const char *fmt = cls; const char *val; char *me; struct MHD_Response *response; int ret; if (0 != strcmp (method, "GET")) return MHD_NO; /* unexpected method */ if (&aptr != *ptr) { /* do never respond on first call */ *ptr = &aptr; return MHD_YES; } *ptr = NULL; /* reset when done */ val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "q"); me = malloc (snprintf (NULL, 0, fmt, "q", val) + 1); if (me == NULL) return MHD_NO; sprintf (me, fmt, "q", val); response = MHD_create_response_from_buffer (strlen (me), me, MHD_RESPMEM_MUST_FREE); if (response == NULL) { free (me); return MHD_NO; } ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; }
std::string CWebServer::GetRequestHeaderValue(struct MHD_Connection *connection, enum MHD_ValueKind kind, const std::string &key) { if (connection == NULL) return ""; const char* value = MHD_lookup_connection_value(connection, kind, key.c_str()); if (value == NULL) return ""; if (StringUtils::EqualsNoCase(key, MHD_HTTP_HEADER_CONTENT_TYPE)) { // Work around a bug in firefox (see https://bugzilla.mozilla.org/show_bug.cgi?id=416178) // by cutting of anything that follows a ";" in a "Content-Type" header field std::string strValue(value); size_t pos = strValue.find(';'); if (pos != std::string::npos) strValue = strValue.substr(0, pos); return strValue; } return value; }
/** * @param connection is the connection in MHD * @returns in bytes the value (a guint) of the Content-Length: header */ static guint64 get_content_length(struct MHD_Connection *connection) { const char *length = NULL; guint64 len = DEFAULT_SERVER_BUFFER_SIZE; length = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length"); if (length != NULL) { /** @todo test len and return code for sscanf to validate a correct entry */ if (sscanf(length, "%"G_GUINT64_FORMAT, &len) <= 0) { print_error(__FILE__, __LINE__, _("Could not guess Content-Length header value: %s\n"), strerror(errno)); len = DEFAULT_SERVER_BUFFER_SIZE; } if (len < 0 || len > 4294967296) { len = DEFAULT_SERVER_BUFFER_SIZE; } } return len; }
/** * Return the session handle for this connection, or * create one if this is a new user. */ WebSession * WebServer::getSession (struct MHD_Connection *connection) { WebSession *result = NULL; const char *cookie; cookie = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, COOKIE_NAME); if (cookie != NULL) { for (auto it = _sessions.begin(); it != _sessions.end(); it++) { WebSession *current = *it; if (strcmp (cookie, current->getSID().c_str())) { result = current; break; } } } if (result == NULL) { /* not a super-secure way to generate a random session ID, but should do for a simple example... */ std::string sid; sid += (unsigned int) rand (); sid += (unsigned int) rand (); sid += (unsigned int) rand (); sid += (unsigned int) rand (); WebSession *newSession = new WebSession(sid, 1, time(NULL)); _sessions.push_back(newSession); result = newSession; } return result; }
/** * Callback function used to answer clients's connection (MHD_AccessHandlerCallback) * * @param cls Custom value selected at callback registration time, used to initialize the done flag * * @param connection The client connection * * @param url The url on which the client made its request * * @param method The http method with which the client made its request (Only GET and PUT supported) * * @param version The HTTP version string (i.e. HTTP/1.1) * * @param upload_data Data beeing uploaded when receiving PUT * * @param upload_data_size Size of the data beeing uploaded when receiving PUT * * @param con_cls reference to a pointer, initially set to NULL, that this callback can set to some * address and that will be preserved by MHD for future calls for this request * * @return MHD_YES to pursue the request handling, MHD_NO in case of error with * the request, return value of the send_* functions otherwise */ int answer_to_connection ( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls ) { Service *requested_service; char *xmlbuff = NULL; int ret; int *done = cls; static int aptr; const char *get_arg; struct sockaddr *addr; addr = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr; char IP[16]; inet_ntop(addr->sa_family,addr->sa_data + 2, IP, 16); if( 0 == strcmp (method, MHD_HTTP_METHOD_GET) ) { if ( &aptr != *con_cls ) { /* do never respond on first call */ *con_cls = &aptr; return MHD_YES; } *con_cls = NULL; if( strcmp(url,"/log") == 0 ) { ret = subscribe_to_log_events(connection, con_cls, HPD_IS_UNSECURE_CONNECTION); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } else if( strcmp(url,"/events") == 0 ) { ret = set_up_server_sent_event_connection( connection, HPD_IS_UNSECURE_CONNECTION ); if( ret == MHD_HTTP_NOT_FOUND ) { Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return send_error (connection, MHD_HTTP_NOT_FOUND); } else { Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } } else if( strcmp(url,"/devices") == 0 ) { xmlbuff = get_xml_device_list(); ret = send_xml (connection, xmlbuff); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } else if( ( requested_service = matching_service (service_head, url) ) != NULL ) { get_arg = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "x"); if( get_arg != NULL ) { if( strcmp(get_arg, "1") == 0 ) { pthread_mutex_lock(requested_service->mutex); xmlbuff = extract_service_xml(requested_service); pthread_mutex_unlock(requested_service->mutex); ret = send_xml (connection, xmlbuff); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, "x=1"); return ret; } } get_arg = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "p"); if( get_arg != NULL ) { if( strcmp(get_arg, "1") == 0 ) { ret = subscribe_to_service(connection, requested_service, con_cls, HPD_IS_UNSECURE_CONNECTION); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, "p=1"); return ret; } } pthread_mutex_lock( requested_service->mutex ); ret = requested_service-> get_function( requested_service, requested_service->get_function_buffer, MHD_MAX_BUFFER_SIZE); if( ret != 0 ) requested_service->get_function_buffer[ret] = '\0'; else { pthread_mutex_unlock( requested_service->mutex ); ret = send_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } xmlbuff = get_xml_value (requested_service->get_function_buffer); pthread_mutex_unlock(requested_service->mutex); ret = send_xml(connection, xmlbuff); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } else { ret = send_error(connection, MHD_HTTP_NOT_FOUND); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } } else if( 0 == strcmp(method, MHD_HTTP_METHOD_PUT) ) { if( ( *con_cls ) == NULL ) { if( *upload_data_size == 0 ) { return MHD_YES; /* not ready yet */ } /* Add a space for a '/0' in order to clear the end of the XML */ char *put_data_temp = (char*)malloc((*upload_data_size)*sizeof(char)+1); memcpy(put_data_temp, upload_data, *upload_data_size); put_data_temp[*upload_data_size]='\0'; *con_cls = put_data_temp; *upload_data_size = 0; return MHD_YES; } else { if( ( requested_service = matching_service (service_head, url) ) !=NULL ) { pthread_mutex_lock(requested_service->mutex); if( requested_service->put_function != NULL && *con_cls != NULL ) { char* _value = get_value_from_xml_value (*con_cls); if(_value == NULL) { pthread_mutex_unlock(requested_service->mutex); ret = send_error (connection, MHD_HTTP_BAD_REQUEST); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } free(*con_cls); ret = requested_service-> put_function( requested_service, requested_service->get_function_buffer, MHD_MAX_BUFFER_SIZE, _value ); free(_value); if( ret != 0 ) requested_service->get_function_buffer[ret] = '\0'; else { pthread_mutex_unlock( requested_service->mutex ); ret = send_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } xmlbuff = get_xml_value (requested_service->get_function_buffer); pthread_mutex_unlock(requested_service->mutex); send_event_of_value_change (requested_service, requested_service->get_function_buffer); ret = send_xml (connection, xmlbuff); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } else { pthread_mutex_unlock(requested_service->mutex); ret = send_error(connection, MHD_HTTP_BAD_REQUEST); Log (HPD_LOG_ONLY_REQUESTS, NULL, IP, method, url, NULL); return ret; } } else return send_error (connection, MHD_HTTP_NOT_FOUND); } } return MHD_NO; }
static int ahc_echo (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **unused) { static int ptr; const char *me = cls; struct MHD_Response *response; int ret; const char *hdr; if (0 != strcmp (me, method)) return MHD_NO; /* unexpected method */ if (&ptr != *unused) { *unused = &ptr; return MHD_YES; } *unused = NULL; ret = 0; MHD_get_connection_values (connection, MHD_HEADER_KIND, &kv_cb, &ret); if (ret != 1) abort (); hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "NotFound"); if (hdr != NULL) abort (); hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT); if ((hdr == NULL) || (0 != strcmp (hdr, "*/*"))) abort (); hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST); if ((hdr == NULL) || (0 != strcmp (hdr, "127.0.0.1:21080"))) abort (); MHD_set_connection_value (connection, MHD_HEADER_KIND, "FakeHeader", "NowPresent"); hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "FakeHeader"); if ((hdr == NULL) || (0 != strcmp (hdr, "NowPresent"))) abort (); response = MHD_create_response_from_buffer (strlen (url), (void *) url, MHD_RESPMEM_MUST_COPY); MHD_add_response_header (response, "MyHeader", "MyValue"); hdr = MHD_get_response_header (response, "MyHeader"); if (0 != strcmp ("MyValue", hdr)) abort (); MHD_add_response_header (response, "MyHeader", "MyValueToo"); if (MHD_YES != MHD_del_response_header (response, "MyHeader", "MyValue")) abort (); hdr = MHD_get_response_header (response, "MyHeader"); if (0 != strcmp ("MyValueToo", hdr)) abort (); if (1 != MHD_get_response_headers (response, NULL, NULL)) abort (); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); if (ret == MHD_NO) abort (); return ret; }
/** * http request handle */ inline int http_request_handle (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { #if ENABLE_AUTHENTICATE //check request authenticate(cookie) if (!(strstr(url , AUTHENTICATE_LOGIN_URL))) { if (check_authentication(connection) < 0) return MHD_YES; } #endif if (!(*con_cls)) { //process GET request or first POST request if (!strcmp(method, MHD_HTTP_METHOD_POST)) //POST { next_connection_info *next_connection; next_connection = calloc(sizeof(char), sizeof(next_connection_info)); strcpy(next_connection->url, url); strcpy(next_connection->method, MHD_HTTP_METHOD_POST); next_connection->post_data_len = atoi (MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH)); if (strstr(url, "upload")) { const char *name = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "file_name"); if (!name) { free(next_connection); return MHD_NO; } else strcpy(next_connection->file_name, name); next_connection->post_data = NULL; } else { next_connection->post_data = calloc(sizeof(char), next_connection->post_data_len); if (!next_connection->post_data) return MHD_NO; } *con_cls = (void *)next_connection; } else if (!strcmp(method, MHD_HTTP_METHOD_GET)) //GET process_get_url_requert(url, connection); } else { next_connection_info *next_connection = ((next_connection_info *)(*con_cls)); if (!strcmp(next_connection->method, MHD_HTTP_METHOD_POST)) { if (*upload_data_size) { if (next_connection->post_data_len == *upload_data_size) { if (strstr(next_connection->url, "upload")) upload_Begin_proc(next_connection, (char *)upload_data, *upload_data_size); else memcpy(next_connection->post_data, upload_data, next_connection->post_data_len); *upload_data_size = 0; } else { if (strstr(next_connection->url, "upload")) upload_Other_proc(next_connection, (char *)upload_data, *upload_data_size); else memcpy((next_connection->post_data + next_connection->offset), upload_data, *upload_data_size); next_connection->offset += *upload_data_size; *upload_data_size = 0; } } else { url_to_api(url, connection, true, next_connection->post_data, next_connection->post_data_len, next_connection->file_name); if (next_connection->post_data) { free(next_connection->post_data); free(next_connection); } } } else return_404(connection); } return MHD_YES; }
const char *crest_req_get_header(struct crest_req *req, const char *key) { return MHD_lookup_connection_value(req->conn, MHD_HEADER_KIND, key); }
const char* RESTRequestState::get_qsargv(const char* key) const { return MHD_lookup_connection_value(conn_, MHD_GET_ARGUMENT_KIND, key); }
static int url_handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { char *me; struct MHD_Response *response; int ret; std::map<std::string, std::string> url_args; std::string respdata; // HTTP access control (CORS) // https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control // some times a preflight check is required which uses the OPTIONS HTTP method to check for permission to // call cross-domain requests if (0 == strcmp(method, MHD_HTTP_METHOD_OPTIONS)) return sendAccessControl(connection, url, method, version); // we only need to deal with GET requests /* FIXME -- don't need this since the HTTP options/preflight will ensure non-supported methods are rejected? if (0 != strcmp(method, MHD_HTTP_METHOD_GET)) return MHD_NO;*/ // set up out connection information on the first pass through. if (NULL == *con_cls) { struct connection_info *con_info; con_info = (connection_info*) malloc (sizeof (struct connection_info)); if (NULL == con_info) return MHD_NO; static int idCounter = 1; con_info->id = idCounter++; // FIXME: for some reason this line causes segfaults under linux? //con_info->url = std::string(url ? url : ""); con_info->data = NULL; con_info->biomapsId = NULL; con_info->dataSize = 0; if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { std::cout << "Setting up con_cls for POST: " << con_info->id << std::endl; std::cout << " - with url: " << url << std::endl; const char* tmp = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-type"); std::string contentType(tmp ? tmp : ""); if (contentType.find(JSON_CONTENT_TYPE) == std::string::npos) { std::cerr << "Error creating POST processor?! Unhandled content type: " << MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-type") << std::endl; free (con_info); return MHD_NO; } con_info->connectiontype = POST; } else con_info->connectiontype = GET; *con_cls = (void *) con_info; return MHD_YES; } // intercept POST requests for now to test stuff if (0 == strcmp(method, MHD_HTTP_METHOD_POST)) { // post recieved, do stuff. struct connection_info *con_info = (connection_info*)(*con_cls); std::cout << "Received a POST for connection: " << con_info->id << std::endl; if (*upload_data_size != 0) { std::cout << "Processed some data: " << *upload_data_size << std::endl; //std::cout << "Data: " << upload_data << std::endl; con_info->data = (char*)realloc(con_info->data, con_info->dataSize + *upload_data_size); memcpy(con_info->data + con_info->dataSize, upload_data, *upload_data_size); con_info->dataSize += *upload_data_size; //std::string bob(upload_data, *upload_data_size); //con_info->data += bob.c_str(); //std::cout << "con_info->data: " << con_info->data << std::endl; *upload_data_size = 0; // set to 0 to indicate all data considered/handled. return MHD_YES; } else { } } else if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) { if (MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, get_url_args, &url_args) < 0) { return MHD_NO; } API api; respdata = api.executeAPI(url, url_args); } if (respdata == "BAD RESPONSE") { return send_bad_response(connection); } //val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "q"); me = (char *) malloc(respdata.size() + 1); if (me == 0) return MHD_NO; strncpy(me, respdata.c_str(), respdata.size() + 1); response = MHD_create_response_from_buffer(strlen(me), me, MHD_RESPMEM_MUST_FREE); if (response == 0) { free(me); return MHD_NO; } /*it = url_args.find("type"); if (it != url_args.end() && strcasecmp(it->second.c_str(), "xml") == 0) type = typexml;*/ MHD_add_response_header(response, "Content-Type", "application/json"); MHD_add_response_header(response, "Content-Range", "items 0-5/5"); MHD_add_response_header(response, "Access-Control-Allow-Origin", "*"); // need to make sure we always expose the (non-simple) headers that we use MHD_add_response_header(response, "Access-Control-Expose-Headers", "Content-Range"); //MHD_add_response_header(response, "OurHeader", type); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; }
int http_cb_request (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { (void)cls; (void)url; (void)upload_data; (void)upload_data_size; int ret; struct Proxy *proxy; struct SPDY_Headers spdy_headers; bool with_body = false; struct HTTP_URI *http_uri; const char *header_value; if (NULL == ptr || NULL == *ptr) return MHD_NO; http_uri = (struct HTTP_URI *)*ptr; if(NULL == http_uri->proxy) { //first call for this request if (0 != strcmp (method, MHD_HTTP_METHOD_GET) && 0 != strcmp (method, MHD_HTTP_METHOD_POST)) { free(http_uri->uri); free(http_uri); PRINT_INFO2("unexpected method %s", method); return MHD_NO; } if(NULL == (proxy = au_malloc(sizeof(struct Proxy)))) { free(http_uri->uri); free(http_uri); PRINT_INFO("No memory"); return MHD_NO; } ++glob_opt.responses_pending; proxy->id = rand(); proxy->http_active = true; proxy->http_connection = connection; http_uri->proxy = proxy; return MHD_YES; } proxy = http_uri->proxy; if(proxy->spdy_error || proxy->http_error) return MHD_NO; // handled at different place TODO? leaks? if(proxy->spdy_active) { if(0 == strcmp (method, MHD_HTTP_METHOD_POST)) { PRINT_INFO("POST processing"); int rc= spdylay_session_resume_data(proxy->spdy_connection->session, proxy->stream_id); PRINT_INFO2("rc is %i stream is %i", rc, proxy->stream_id); proxy->spdy_connection->want_io |= WANT_WRITE; if(0 == *upload_data_size) { PRINT_INFO("POST http EOF"); proxy->receiving_done = true; return MHD_YES; } if(!copy_buffer(upload_data, *upload_data_size, &proxy->received_body, &proxy->received_body_size)) { //TODO handle it better? PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); return MHD_NO; } *upload_data_size = 0; return MHD_YES; } //already handled PRINT_INFO("unnecessary call to http_cb_request"); return MHD_YES; } //second call for this request PRINT_INFO2("received request for '%s %s %s'", method, http_uri->uri, version); proxy->url = http_uri->uri; header_value = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH); with_body = 0 == strcmp (method, MHD_HTTP_METHOD_POST) && (NULL == header_value || 0 != strcmp ("0", header_value)); PRINT_INFO2("body will be sent %i", with_body); ret = parse_uri(&glob_opt.uri_preg, proxy->url, &proxy->uri); if(ret != 0) DIE("parse_uri failed"); proxy->http_uri = http_uri; spdy_headers.num = MHD_get_connection_values (connection, MHD_HEADER_KIND, NULL, NULL); if(NULL == (spdy_headers.nv = au_malloc(((spdy_headers.num + 5) * 2 + 1) * sizeof(char *)))) DIE("no memory"); spdy_headers.nv[0] = ":method"; spdy_headers.nv[1] = method; spdy_headers.nv[2] = ":path"; spdy_headers.nv[3] = proxy->uri->path_and_more; spdy_headers.nv[4] = ":version"; spdy_headers.nv[5] = (char *)version; spdy_headers.nv[6] = ":scheme"; spdy_headers.nv[7] = proxy->uri->scheme; spdy_headers.nv[8] = ":host"; spdy_headers.nv[9] = NULL; //nv[14] = NULL; spdy_headers.cnt = 10; MHD_get_connection_values (connection, MHD_HEADER_KIND, &http_cb_iterate, &spdy_headers); spdy_headers.nv[spdy_headers.cnt] = NULL; if(NULL == spdy_headers.nv[9]) spdy_headers.nv[9] = proxy->uri->host_and_port; if(0 != spdy_request(spdy_headers.nv, proxy, with_body)) { free(spdy_headers.nv); //free_proxy(proxy); return MHD_NO; } free(spdy_headers.nv); proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 4096, &http_cb_response, proxy, &http_cb_response_done); if (NULL == proxy->http_response) DIE("no response"); if(MHD_NO == MHD_add_response_header (proxy->http_response, "Proxy-Connection", "keep-alive")) PRINT_INFO("SPDY_name_value_add failed: "); if(MHD_NO == MHD_add_response_header (proxy->http_response, "Connection", "Keep-Alive")) PRINT_INFO("SPDY_name_value_add failed: "); if(MHD_NO == MHD_add_response_header (proxy->http_response, "Keep-Alive", "timeout=5, max=100")) PRINT_INFO("SPDY_name_value_add failed: "); proxy->spdy_active = true; return MHD_YES; }
int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method, const char* version, const char* data, size_t* size, void** con_cls) { #ifdef PLATFORM_OSX pthread_setname_np("http"); #else prctl(PR_SET_NAME, "http"); #endif if (*con_cls == NULL) { ConnectionInfo *con_info = create_connection_info(); if (g_strcmp0(method, "POST") == 0 && g_strcmp0(url, "/send") == 0) { con_info->stbbr_op = STBBR_OP_SEND; } else if (g_strcmp0(method, "POST") == 0 && g_strcmp0(url, "/for") == 0) { con_info->stbbr_op = STBBR_OP_FOR; } else if (g_strcmp0(method, "POST") == 0 && g_strcmp0(url, "/verify") == 0) { con_info->stbbr_op = STBBR_OP_VERIFY; } else { con_info->stbbr_op = STBBR_OP_UNKNOWN; return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); } *con_cls = (void*) con_info; return MHD_YES; } ConnectionInfo *con_info = (ConnectionInfo*) *con_cls; if (*size != 0) { g_string_append_len(con_info->body, data, *size); *size = 0; return MHD_YES; } const char *id = NULL; const char *query = NULL; int res = 0; switch (con_info->stbbr_op) { case STBBR_OP_SEND: server_send(con_info->body->str); return send_response(conn, NULL, MHD_HTTP_OK); case STBBR_OP_FOR: id = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "id"); query = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "query"); if (id && query) { return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); } if (id) { prime_for_id(id, con_info->body->str); return send_response(conn, NULL, MHD_HTTP_CREATED); } if (query) { prime_for_query(query, con_info->body->str); return send_response(conn, NULL, MHD_HTTP_CREATED); } return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); case STBBR_OP_VERIFY: res = verify_any(con_info->body->str, TRUE); if (res) { return send_response(conn, "true", MHD_HTTP_OK); } else { return send_response(conn, "false", MHD_HTTP_OK); } default: return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); } }
/** * Main request handler. */ static int access_handler_callback (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { static int dummy; static const struct Entry map[] = { { "prefix", "prefix" }, { "name", "name" }, { "suffix", "suffix" }, { "street", "street" }, { "city", "city" }, { "phone", "phone" }, { "fax", "fax" }, { "email", "email"}, { "homepage", "homepage" }, { "orga", "orga"}, { "departmenti18n", "departmentde"}, { "departmenten", "departmenten"}, { "subdepartmenti18n", "subdepartmentde"}, { "subdepartmenten", "subdepartmenten"}, { "jobtitlei18n", "jobtitlegerman"}, { "jobtitleen", "jobtitleenglish"}, { "subdepartmenten", "subdepartmenten"}, { NULL, NULL } }; if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request to HTTP server\n"), method); return MHD_NO; } if (NULL == *con_cls) { (*con_cls) = &dummy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); return MHD_YES; /* send 100 continue */ } if (0 == strcasecmp (url, "/")) return MHD_queue_response (connection, MHD_HTTP_OK, main_response); if (0 == strcasecmp (url, "/submit.pdf")) { unsigned int i; char *p; char *tmp; char *deffile; struct GNUNET_CRYPTO_EcdsaPublicKey pub; size_t slen; FILE *f; struct stat st; struct MHD_Response *response; int fd; int ret; const char *gpg_fp = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gpgfingerprint"); const char *gns_nick = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnsnick"); const char *gnskey = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); if ( (NULL == gnskey) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (gnskey, strlen (gnskey), &pub))) { return MHD_queue_response (connection, MHD_HTTP_OK, invalid_gnskey_response); } tmp = GNUNET_DISK_mkdtemp (gnskey); if (NULL == tmp) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); return MHD_NO; } GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex"); f = FOPEN (deffile, "w"); if (NULL == f) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } for (i=0; NULL != map[i].formname; i++) { const char *val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, map[i].formname); if (NULL != val) FPRINTF (f, "\\def\\%s{%s}\n", map[i].texname, val); else FPRINTF (f, "\\def\\%s{}\n", map[i].texname); } if (NULL != gpg_fp) { char *gpg1; char *gpg2; slen = strlen (gpg_fp); gpg1 = GNUNET_strndup (gpg_fp, slen / 2); gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]); FPRINTF (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2); GNUNET_free (gpg2); GNUNET_free (gpg1); } FPRINTF (f, "\\def\\gns{%s/%s}\n", gnskey, (NULL == gns_nick) ? "" : gns_nick); FCLOSE (f); GNUNET_asprintf (&p, "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", tmp, resfile); GNUNET_free (deffile); ret = system (p); if (WIFSIGNALED (ret) || (0 != WEXITSTATUS(ret))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p); GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf"); fd = OPEN (deffile, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } GNUNET_break (0 == STAT (deffile, &st)); if (NULL == (response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/pdf"); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return ret; } return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, not_found_response); }
int web_main(void * _ed, struct MHD_Connection * con, const char * url, const char * method, const char * version, const char *upload_data, size_t * upload_data_size, void ** con_cls){ UNUSED(url); UNUSED(version); UNUSED(upload_data); UNUSED(upload_data_size); UNUSED(method); UNUSED(con_cls); UNUSED(_ed); const char * file = "page.html"; bool style_loc = strcmp((char *) url + 1, "style.css") == 0; if(style_loc) file = "style.css"; else if(0 == strcmp((char *) url + 1, (char *) "favicon.png")) file = "favicon.png"; char fnamebuffer[100]; logd("'%s' %s %s %i\n", url, method, version, upload_data_size); logd("File: %s\n", file); if(url == strstr(url, "/sharesinfo")){ // Send back json code describing all the available shares. file = "shareinfo_data"; dirscan dir = scan_directories("shareinfo"); FILE * outfile = fopen(file, "w"); fprintf(outfile, "["); for(size_t i = 0; i < dir.cnt; i++){ logd("looking in: %s\n", dir.files[i]); char fnamebuffer2[100]; sprintf(fnamebuffer2, "shareinfo/%s", dir.files[i]); void * rdbuffer = read_file_to_string(fnamebuffer2); ASSERT(rdbuffer != NULL); void *ptr = rdbuffer; char * dirname = udpc_unpack_string(&ptr); char * name = udpc_unpack_string(&ptr); char * user = udpc_unpack_string(&ptr); fprintf(outfile, "{\"path\": \"%s\", \"name\":\"%s\", \"user\":\"%s\"}%s\n",dirname, name, user, (i == dir.cnt -1) ? "" : ","); dealloc(rdbuffer); } fprintf(outfile, "]"); fclose(outfile); dirscan_clean(&dir); }else if(url == strstr(url,"/shares/")){ // fetch the active shares item inside the shares folder char * shareid = (char *) url + strlen("/shares/"); logd("Shareid: %s\n", shareid); char * shareinfo_filename = fmtstr("shareinfo/%s", shareid); void * buffer = read_file_to_string(shareinfo_filename); if(buffer == NULL) goto error; void * bufptr = buffer; char * dir = udpc_unpack_string(&bufptr); char * name = udpc_unpack_string(&bufptr); char * user = udpc_unpack_string(&bufptr); service_descriptor sd; if(!udpc_get_service_descriptor(user, &sd)){ logd("Unable to parse service name: '%s'\n", user); dealloc(buffer); goto error; } logd("path: %s, name: %s, user: %s\n", dir, name, user); update_dirfile(dir, name, user); sprintf(fnamebuffer, "shares/%s.json", name); dealloc(buffer); logd("Sending: %s\n", fnamebuffer); file = fnamebuffer; } if(strcmp(url, "/add_share") == 0){ const char * path = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "path"); const char * name = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "name"); const char * user = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "user"); logd("path: %s, name: %s, user: %s\n", path, name, user); if(path == NULL || name == NULL || user == NULL){ goto error; } service_descriptor sd; if(!udpc_get_service_descriptor(user, &sd)){ logd("Unable to parse service name: '%s'\n", user); goto error; } logd("Service descriptor seems ok \n"); ensure_directory("shareinfo/"); char * sharepath = fmtstr("shareinfo/%s", name); struct stat filest; stat(sharepath, &filest); dealloc(sharepath); if(S_ISREG(filest.st_mode)){ logd("File exists!\n"); }else{ struct stat dirst; stat(path, &dirst); if(!S_ISDIR(dirst.st_mode)){ logd("Dir does not exist.. creating a new one..\n"); int path_len = strlen(path); if(path[path_len] !='/'){ char * npath = fmtstr("%s/", path); ensure_directory(npath); dealloc(npath); }else{ ensure_directory(path); } } logd("Updating dirfile!\n"); update_dirfile(path, name, user); logd("Done..\n"); } const char * r = "\"OK\""; struct MHD_Response * response = MHD_create_response_from_data(strlen(r), (void *) r, 0, MHD_NO); int ret = MHD_queue_response(con, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; } size_t filesize = 0; void * pg = read_file_to_buffer(file, &filesize); struct MHD_Response * response = MHD_create_response_from_data(filesize, pg, 1, MHD_NO); int ret = MHD_queue_response(con, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; error:; const char * error_str = "<html><body>400</body></html>"; response = MHD_create_response_from_data(strlen(error_str) + 1, (void *) error_str, 0, MHD_NO); ret = MHD_queue_response(con, MHD_HTTP_BAD_REQUEST, response); MHD_destroy_response(response); return ret; }
int request_handler (void * dbv, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { static int con_cls0; struct MHD_Response* response; int ret; char* result; sqlite3* db = (sqlite3*) dbv; #ifdef DEBUG fprintf (stderr, "%s %s %s\n", method, url, version); #endif // Unexpected method if (0 != strcmp(method, "GET")){ if(0 == strcmp(method, "OPTIONS")) return options200(connection); else return http400(connection); } // Do never respond on first call if (&con_cls0 != *con_cls) { *con_cls = &con_cls0; return MHD_YES; } *con_cls = NULL; // reset when done if (strcmp(url, "/last") == 0) { const char* count_s = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "count"); if (count_s == NULL) return http400(connection); int count = atoi(count_s); if (count <= 0) return http400(connection); ret = base_load_last(db, (unsigned int)count, &result); if (ret != 0) return http400(connection); } else if (strcmp(url, "/between") == 0) { const char* from_s = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "from"); const char* to_s = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "to"); if ((from_s == NULL) || (to_s == NULL)) return http400(connection); ret = base_load_between(db, from_s, to_s, &result); if (ret != 0) return http400(connection); } else return http400(connection); response = MHD_create_response_from_buffer (strlen (result), (void *) result, MHD_RESPMEM_MUST_COPY); MHD_add_response_header (response, CORS_HEADER, CORS_ORIGIN); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; }
/** * Create a PostProcessor. * * A PostProcessor can be used to (incrementally) * parse the data portion of a POST request. * * @param connection the connection on which the POST is * happening (used to determine the POST format) * @param buffer_size maximum number of bytes to use for * internal buffering (used only for the parsing, * specifically the parsing of the keys). A * tiny value (256-1024) should be sufficient. * Do NOT use 0. * @param ikvi iterator to be called with the parsed data * @param cls first argument to ikvi * @return NULL on error (out of memory, unsupported encoding), * otherwise a PP handle */ struct MHD_PostProcessor * MHD_create_post_processor (struct MHD_Connection *connection, size_t buffer_size, MHD_PostDataIterator ikvi, void *cls) { struct MHD_PostProcessor *ret; const char *encoding; const char *boundary; size_t blen; if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL)) mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); encoding = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_TYPE); if (encoding == NULL) return NULL; boundary = NULL; if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding, strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) { if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) return NULL; boundary = &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; /* Q: should this be "strcasestr"? */ boundary = strstr (boundary, "boundary="); if (NULL == boundary) return NULL; /* failed to determine boundary */ boundary += strlen ("boundary="); blen = strlen (boundary); if ((blen == 0) || (blen * 2 + 2 > buffer_size)) return NULL; /* (will be) out of memory or invalid boundary */ if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') ) { /* remove enclosing quotes */ ++boundary; blen -= 2; } } else blen = 0; buffer_size += 4; /* round up to get nice block sizes despite boundary search */ /* add +1 to ensure we ALWAYS have a zero-termination at the end */ if (NULL == (ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1))) return NULL; memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1); ret->connection = connection; ret->ikvi = ikvi; ret->cls = cls; ret->encoding = encoding; ret->buffer_size = buffer_size; ret->state = PP_Init; ret->blen = blen; ret->boundary = boundary; ret->skip_rn = RN_Inactive; return ret; }
int RudeTweaker::HttpHandler(void * cls, struct MHD_Connection * connection, const char * url, const char * method, const char * version, const char * upload_data, unsigned int * upload_data_size, void ** ptr) { static int dummy; struct MHD_Response * response; int ret; if (&dummy != *ptr) { /* The first time only the headers are valid, do not respond in the first round... */ *ptr = &dummy; return MHD_YES; } *ptr = NULL; /* clear context pointer */ if(url) printf("URL: %s\n", url); if(upload_data) printf("Data: %s\n", upload_data); strcpy(text, "<html><head><title>Rude Tweaker</title></head>\r\n"); strcat(text, "\n"); strcat(text, "\n"); for(tTweakerList::iterator i = m_tweaks.begin(); i != m_tweaks.end(); ++i) { RudeTweak *it = *i; const int kItemLen = 512; char item[kItemLen]; char value[kItemLen]; const char *invalue = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, it->m_name); if(invalue) printf("Value: %s\n", invalue); switch(it->m_type) { case kBool: if(invalue) { int parsedvalue = 0; int results = sscanf(invalue, "%d", &parsedvalue); if(results == 1) *((bool *) it->m_data) = parsedvalue; } snprintf(value, kItemLen, "%d", *((bool *) it->m_data)); break; case kFloat: if(invalue) sscanf(invalue, "%f", ((float *) it->m_data)); snprintf(value, kItemLen, "%f", *((float *) it->m_data)); break; } snprintf(item, kItemLen, "<form method=\"get\">%s: <input type=\"text\" name=\"%s\" value=\"%s\"></form><br>\n", it->m_name, it->m_name, value); strcat(text, item); } strcat(text, "<br><a href=\"/\">Refresh</a>\n"); int textlen = strlen(text); RUDE_ASSERT(textlen < sizeof(text), "Tweaker exceeded text buffer bounds (%d / %d)", textlen, sizeof(text)); //printf(text); response = MHD_create_response_from_data(strlen(text), text, MHD_NO, MHD_NO); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; }