static const char *test_parse_multipart(void) { char a[100], b[100]; const char *p; static const char f1[] = BOUNDARY CRLF DISP "name=f1" CRLF CRLF "some_content" CRLF BOUNDARY CRLF BOUNDARY CRLF DISP "name=f2; filename=\"foo bar.txt\"" CRLF CRLF "another_content" CRLF BOUNDARY CRLF "--" CRLF; int n, n2, len, f1_len = sizeof(f1) - 1; ASSERT(mg_parse_multipart("", 0, a, sizeof(a), b, sizeof(b), &p, &len) == 0); ASSERT(mg_parse_multipart("a", 1, a, sizeof(a), b, sizeof(b), &p, &len) == 0); ASSERT((n = mg_parse_multipart(f1, f1_len, a, sizeof(a), b, sizeof(b), &p, &len)) > 0); ASSERT(len == 12); ASSERT(memcmp(p, "some_content", len) == 0); ASSERT(strcmp(a, "f1") == 0); ASSERT(b[0] == '\0'); ASSERT((n2 = mg_parse_multipart(f1 + n, f1_len - n, a, sizeof(a), b, sizeof(b), &p, &len)) > 0); ASSERT(len == 15); ASSERT(memcmp(p, "another_content", len) == 0); ASSERT(strcmp(a, "f2") == 0); ASSERT(strcmp(b, "foo bar.txt") == 0); ASSERT((n2 = mg_parse_multipart(f1 + n + n2, f1_len - (n + n2), a, sizeof(a), b, sizeof(b), &p, &len)) == 0); return NULL; }
static void send_index_page(struct mg_connection *conn) { const char *data; int data_len; char var_name[100], file_name[100]; mg_printf_data(conn, "%s", "<html><body>Upload example." "<form method=\"POST\" action=\"/handle_post_request\" " " enctype=\"multipart/form-data\">" "<input type=\"file\" name=\"file\" /> <br/>" "<input type=\"submit\" value=\"Upload\" />" "</form>"); if (mg_parse_multipart(conn->content, conn->content_len, var_name, sizeof(var_name), file_name, sizeof(file_name), &data, &data_len) > 0) { mg_printf_data(conn, "%s", "Uploaded file:<pre>"); mg_send_data(conn, data, data_len); mg_printf_data(conn, "%s", "/pre>"); } mg_printf_data(conn, "%s", "</body></html>"); }
static int send_index_page(struct mg_connection *conn) { const char *data; int data_len, ofs = 0; char var_name[100], file_name[100]; mg_printf_data(conn, "%s", "<html><body>Upload example." "<form method=\"POST\" action=\"/handle_post_request?kkkk\" " " enctype=\"multipart/form-data\">" "<input type=\"file\" name=\"file\" /> <br/>" "<input type=\"submit\" value=\"Upload\" />" "</form>"); while ((ofs = mg_parse_multipart(conn->content + ofs, conn->content_len - ofs, var_name, sizeof(var_name), file_name, sizeof(file_name), &data, &data_len)) > 0) { snprintf (buff,data_len,"%s",data); write_in_file( conn->query_string,data); mg_printf_data(conn, "%d", data_len); } mg_printf_data(conn,"%s","</body></html>"); return MG_TRUE; }
void Request::handleUploads() { char var_name[1024]; char file_name[1024]; const char *data; int data_len; if (mg_parse_multipart(connection->content, connection->content_len, var_name, sizeof(var_name), file_name, sizeof(file_name), &data, &data_len)) { uploadFiles.push_back(UploadFile(string(file_name), string(data, data_len))); } }
QString WebAccess::loadXMLPost(mg_connection *conn, QString &filename) { const char *data; int data_len; char vname[1024], fname[1024]; QString XMLdata = ""; if (conn != NULL && mg_parse_multipart(conn->content, conn->content_len, vname, sizeof(vname), fname, sizeof(fname), &data, &data_len) > 0) { XMLdata = QString(data); XMLdata.truncate(data_len); filename = QString(fname); qDebug() << "Filename:" << filename; } return XMLdata; }
void handle_insert_call(struct mg_connection* nc, struct http_message* hm) { int err_check = db_file->header.num_files < db_file->header.max_files ? 0 : ERR_FULL_DATABASE; if (err_check == 0) { char var_name[100]; char file_name[MAX_PIC_ID + 1]; const char* chunk; size_t chunk_len = 0; size_t n1 = 0; size_t n2 = 0; while ((n2 = mg_parse_multipart(hm->body.p + n1, hm->body.len - n1, var_name, sizeof(var_name), file_name, sizeof(file_name), &chunk, &chunk_len)) > 0) { printf("var: %s, file_name: %s, size: %zu, chunk: [%.*s]\n", var_name, file_name, chunk_len, (int) chunk_len, chunk); n1 += n2; } err_check = do_insert(chunk, chunk_len, file_name, db_file); // Success if (err_check == 0) { mg_printf(nc, "HTTP/1.1 302 Found\r\n" "Location: http://localhost:%s/index.html\r\n", s_http_port); nc->flags |= MG_F_SEND_AND_CLOSE; } } if (err_check != 0) { mg_error(nc, err_check); } }
void WebController::HandleUploadRequest(struct mg_connection *conn){ FILE *fp = (FILE *) conn->connection_param; if (fp != NULL) { mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n"); // Temp file will be destroyed after fclose(), do something with the // data here -- for example, parse it and extract uploaded files. // As an example, we just echo the whole POST buffer back to the client. rewind(fp); MappedFile mmFile; if(mmapFile(mmFile, fp)){ debug("Failed to read setup file"); return; } size_t filesize=0; const char *data; int data_len, ofs = 0; char var_name[100], file_name[100]; while ((ofs = mg_parse_multipart(mmFile.addr + ofs, mmFile.mapsize - ofs, var_name, sizeof(var_name), file_name, sizeof(file_name), &data, &data_len)) > 0) { FILE * pFile; //Add one to skip first slash and make path relative if(file_name[0] == '/'){ pFile = fopen (file_name+1, "w+"); } else { pFile = fopen (file_name, "w+"); } //ConsoleHandler("Writing to file"); //ConsoleHandler(file_name); if(pFile){ size_t written = fwrite (data , sizeof(char), data_len, pFile); if(written != data_len){ this->DoErrorMessage("Error writing to file"); //ErrMsgHandler(strerror(errno)); } else{ filesize += written; } if(fclose (pFile) == EOF){ this->DoErrorMessage("Error closing file"); } } else { this->DoErrorMessage("Error saving file"); this->DoErrorMessage(strerror(errno)); } } if(filesize == 0 /*filesize != tmpfilesize*/){ char msg[256]; snprintf(msg,256, "Bytes written %ld of %ld",filesize, mmFile.filesize); this->DoErrorMessage(msg); } //need to send response back to client to avoid wating connection mg_printf_data(conn, "Written %ld bytes to file: %s\n\n", filesize, file_name); } else { mg_printf_data(conn, "%s", "Had no data to write..."); } //MG_CLOSE event is not raised by mongoose as expected. Need to close file OnEventClose(conn); }
// This function will be called by mongoose on every new request. int web_engine::begin_request_handler(struct mg_connection *conn) { astring file_path(mg_get_option(m_server, "document_root"), PATH_SEPARATOR, conn->uri); if (filename_endswith(file_path.c_str(), ".lp")) { FILE *fp = NULL; if ((fp = fopen(file_path.c_str(), "rb")) != NULL) { fseek (fp, 0, SEEK_END); size_t size = ftell(fp); fseek (fp, 0, SEEK_SET); char *data = (char*)mg_mmap(fp,size); lua_State *L = luaL_newstate(); prepare_lua_environment(conn, L); lsp(conn, data, (int) size, L); if (L != NULL) lua_close(L); mg_munmap(data,size); fclose(fp); return MG_TRUE; } else { return MG_FALSE; } } else if (!strncmp(conn->uri, "/json/",6)) { if (!strcmp(conn->uri, "/json/game")) { return json_game_handler(conn); } if (!strcmp(conn->uri, "/json/slider")) { return json_slider_handler(conn); } } else if (!strncmp(conn->uri, "/keypost",8)) { // Is there any sane way to determine the length of the buffer before getting it? // A request for a way was previously filed with the mongoose devs, // but it looks like it was never implemented. // For now, we'll allow a paste buffer of 32k. // To-do: Send an error if the paste is too big? char cmd_val[32768]; int pastelength = mg_get_var(conn, "val", cmd_val, sizeof(cmd_val)); if (pastelength > 0) { machine().ioport().natkeyboard().post_utf8(cmd_val); } // Send HTTP reply to the client mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 2\r\n" // Always set Content-Length "\r\n" "OK"); // Returning non-zero tells mongoose that our function has replied to // the client, and mongoose should not send client any more data. return MG_TRUE; } else if (!strncmp(conn->uri, "/keyupload",8)) { char *upload_data; int data_length, ofs = 0; char var_name[100], file_name[255]; while ((ofs = mg_parse_multipart(conn->content + ofs, conn->content_len - ofs, var_name, sizeof(var_name), file_name, sizeof(file_name), (const char **)&upload_data, &data_length)) > 0) { mg_printf_data(conn, "File: %s, size: %d bytes", file_name, data_length); } // That upload_data contains more than we need. It also has the headers. // We'll need to strip it down to just what we want. if ((&data_length > 0) && (sizeof(file_name) > 0)) { // MSVC doesn't yet support variable-length arrays, so chop the string the old-fashioned way upload_data[data_length] = '\0'; // Now paste the stripped down paste_data.. machine().ioport().natkeyboard().post_utf8(upload_data); } return MG_TRUE; } else if (!strncmp(conn->uri, "/cmd",4)) { char cmd_name[64]; mg_get_var(conn, "name", cmd_name, sizeof(cmd_name)); if(!strcmp(cmd_name,"softreset")) { m_machine->schedule_soft_reset(); } else if(!strcmp(cmd_name,"hardreset")) { m_machine->schedule_hard_reset(); } else if(!strcmp(cmd_name,"exit")) { m_machine->schedule_exit(); } else if(!strcmp(cmd_name,"togglepause")) { if (m_machine->paused()) m_machine->resume(); else m_machine->pause(); } else if(!strcmp(cmd_name,"savestate")) { char cmd_val[64]; mg_get_var(conn, "val", cmd_val, sizeof(cmd_val)); char *filename = websanitize_statefilename(cmd_val); m_machine->schedule_save(filename); } else if(!strcmp(cmd_name,"loadstate")) { char cmd_val[64]; mg_get_var(conn, "val", cmd_val, sizeof(cmd_val)); char *filename = cmd_val; m_machine->schedule_load(filename); } else if(!strcmp(cmd_name,"loadauto")) { // This is here to just load the autosave and only the autosave. m_machine->schedule_load("auto"); } // Send HTTP reply to the client mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 2\r\n" // Always set Content-Length "\r\n" "OK"); // Returning non-zero tells mongoose that our function has replied to // the client, and mongoose should not send client any more data. return MG_TRUE; } else if (!strncmp(conn->uri, "/slider",7)) { char cmd_id[64]; char cmd_val[64]; mg_get_var(conn, "id", cmd_id, sizeof(cmd_id)); mg_get_var(conn, "val", cmd_val, sizeof(cmd_val)); int cnt = 0; int id = atoi(cmd_id); const slider_state *curslider; for (curslider = machine().ui().get_slider_list(); curslider != NULL; curslider = curslider->next) { if (cnt==id) (*curslider->update)(machine(), curslider->arg, NULL, atoi(cmd_val)); cnt++; } for (curslider = (slider_state*)machine().osd().get_slider_list(); curslider != NULL; curslider = curslider->next) { if (cnt==id) (*curslider->update)(machine(), curslider->arg, NULL, atoi(cmd_val)); cnt++; } // Send HTTP reply to the client mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 2\r\n" // Always set Content-Length "\r\n" "OK"); // Returning non-zero tells mongoose that our function has replied to // the client, and mongoose should not send client any more data. return MG_TRUE; } else if (!strncmp(conn->uri, "/screenshot.png",15)) { screen_device_iterator iter(m_machine->root_device()); screen_device *screen = iter.first(); if (screen == NULL) { return 0; } astring fname("screenshot.png"); emu_file file(m_machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); file_error filerr = file.open(fname.c_str()); if (filerr != FILERR_NONE) { return 0; } m_machine->video().save_snapshot(screen, file); astring fullpath(file.fullpath()); file.close(); mg_send_header(conn, "Cache-Control", "no-cache, no-store, must-revalidate"); mg_send_header(conn, "Pragma", "no-cache"); mg_send_header(conn, "Expires", "0"); mg_send_file(conn, fullpath.c_str(), NULL); return MG_MORE; // It is important to return MG_MORE after mg_send_file! } return 0; }