// A handler for the /authorize endpoint. // Login page form sends user name and password to this endpoint. static void authorize(struct mg_connection *conn, const struct mg_request_info *request_info) { char user[32], password[32], referer[256]; if(!strcmp(request_info->request_method, "POST")) { char post_data[1024]; int post_data_len = mg_read(conn, post_data, sizeof(post_data)); mg_get_var(post_data, post_data_len, "user", user, sizeof(user)); mg_get_var(post_data, post_data_len, "password", password, sizeof(password)); mg_get_var(post_data, post_data_len, "referer", referer, sizeof(referer)); } else { // Fetch user name and password. get_qsvar(request_info, "user", user, sizeof(user)); get_qsvar(request_info, "password", password, sizeof(password)); get_qsvar(request_info, "ref", referer, sizeof(referer)); } /* Referer url must begin with '/' */ if((referer[0] != '/') || (strcmp(referer, AUTHORIZE_URL) == 0)) strcpy(referer, "/"); if(ntop->checkUserPassword(user, password)) { set_cookie(conn, user, referer); } else { // Authentication failure, redirect to login. redirect_to_login(conn, request_info); } }
static void *callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { const int buf_max = 1000; char result[buf_max] = "none"; if (event == MG_NEW_REQUEST) { //const char* uri = request_info->uri; // get query args char cmd[32]; char timeoutStr[5]; int timeout; char str[256]; get_qsvar(request_info, "cmd", cmd, sizeof(cmd)); get_qsvar(request_info, "str", str, sizeof(str)); get_qsvar(request_info, "timeout", timeoutStr, sizeof(timeoutStr)); timeout = timeoutStr[0] == '\0' ? 5000 : atoi(timeoutStr); if( ! cmd[0] ) { // cmd is empty /// do something useful here } else { if( strcasecmp(cmd, "read")==0 ) { serialport_flush(fd); serialport_read_until(fd, str, '\n', buf_max, timeout); sprintf(result, "read:\n%s\n",str); // debug } else if( strcasecmp(cmd, "send")==0 ) { serialport_write(fd, str); sprintf(result, "send:\n%s\n",str); } else if( strcasecmp(cmd, "sendline")==0 ) { sprintf(str, "%s\r\n ", str); serialport_write(fd, str); sprintf(result, "sendline:\n%s",str); } else { sprintf(result, "uknown cmd '%s'",cmd); } } printf("result:%s\n",result); // Echo requested URI back to the client mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n\r\n" "%s" "\n", result ); return ""; // Mark as processed } else { return NULL; } }
// A handler for the /authorize endpoint. // Login page form sends user name and password to this endpoint. static void authorize(struct mg_connection *conn, const struct mg_request_info *request_info) { char user[32], password[32], referer[256]; if(!strcmp(request_info->request_method, "POST")) { char post_data[1024]; int post_data_len = mg_read(conn, post_data, sizeof(post_data)); mg_get_var(post_data, post_data_len, "user", user, sizeof(user)); mg_get_var(post_data, post_data_len, "password", password, sizeof(password)); mg_get_var(post_data, post_data_len, "referer", referer, sizeof(referer)); } else { // Fetch user name and password. get_qsvar(request_info, "user", user, sizeof(user)); get_qsvar(request_info, "password", password, sizeof(password)); get_qsvar(request_info, "ref", referer, sizeof(referer)); } /* Referer url must begin with '/' */ if((referer[0] != '/') || (strcmp(referer, AUTHORIZE_URL) == 0)) strcpy(referer, "/"); if(ntop->checkUserPassword(user, password)) { char key[256], session_id[64], random[64]; // Authentication success: // 1. create new session // 2. set session ID token in the cookie // // The most secure way is to stay HTTPS all the time. However, just to // show the technique, we redirect to HTTP after the successful // authentication. The danger of doing this is that session cookie can // be stolen and an attacker may impersonate the user. // Secure application must use HTTPS all the time. snprintf(random, sizeof(random), "%d", rand()); generate_session_id(session_id, random, user); // ntop->getTrace()->traceEvent(TRACE_ERROR, "==> %s\t%s", random, session_id); /* http://en.wikipedia.org/wiki/HTTP_cookie */ mg_printf(conn, "HTTP/1.1 302 Found\r\n" "Set-Cookie: session=%s; path=/; max-age=%u; HttpOnly\r\n" // Session ID "Set-Cookie: user=%s; path=/; max-age=%u; HttpOnly\r\n" // Set user, needed by Javascript code "Location: %s%s\r\n\r\n", session_id, HTTP_SESSION_DURATION, user, HTTP_SESSION_DURATION, ntop->getPrefs()->get_http_prefix(), referer); /* Save session in redis */ snprintf(key, sizeof(key), "sessions.%s", session_id); ntop->getRedis()->set(key, user, HTTP_SESSION_DURATION); ntop->getTrace()->traceEvent(TRACE_INFO, "[HTTP] Set session sessions.%s", session_id); } else { // Authentication failure, redirect to login. redirect_to_login(conn, request_info); } }
// 13. DOWNLOADING static void proc_cmd_downloading(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_downloading_mode[50]; get_qsvar(request_info, "mode", str_downloading_mode, sizeof(str_downloading_mode)); logger_remotem("DOWNLOADING: received status %s", str_downloading_mode); if ((strstr(str_downloading_mode, "started") == 0) && (strstr(str_downloading_mode, "stopped") == 0)) { logger_remotem("DOWNLOADING: error unknown mode requested %s", str_downloading_mode); mg_printf(conn, "HTTP/1.0 200 OK\r\n\nerrno=1\r\nmode=%s\r\nno such mode\r\n", str_downloading_mode); } else { if (strstr(str_downloading_mode, "started") != NULL) { strcpy(downloading_status, "Downloading"); logger_remotem("Upload started send UPS to uC"); write_command_to_serial_port("UPS\r\n"); sleep(1); } mg_printf(conn, "HTTP/1.0 200 OK\r\n\nerrno=0\r\nmode=%s\r\n", str_downloading_mode); if (strstr(str_downloading_mode, "stopped") != NULL) { logger_remotem("Upload stopped send UPD to uC"); strcpy(downloading_status, "Idle"); write_command_to_serial_port("UPD\r\n"); sleep(1); } } }
// A handler for the /ajax/send_message endpoint. static void ajax_send_message(struct mg_connection *conn, const struct mg_request_info *request_info) { struct message *message; struct session *session; char text[sizeof(message->text) - 1]; int is_jsonp; mg_printf(conn, "%s", ajax_reply_start); is_jsonp = handle_jsonp(conn, request_info); get_qsvar(request_info, "text", text, sizeof(text)); if (text[0] != '\0') { // We have a message to store. Write-lock the ringbuffer, // grab the next message and copy data into it. pthread_rwlock_wrlock(&rwlock); message = new_message(); // TODO(lsm): JSON-encode all text strings session = get_session(conn); assert(session != NULL); my_strlcpy(message->text, text, sizeof(text)); my_strlcpy(message->user, session->user, sizeof(message->user)); pthread_rwlock_unlock(&rwlock); } mg_printf(conn, "%s", text[0] == '\0' ? "false" : "true"); if (is_jsonp) { mg_printf(conn, "%s", ")"); } }
// 7. FORMAT_DEVICE static void proc_cmd_format_device(struct mg_connection* conn, const struct mg_request_info* request_info) { DIR *ptr_dir; struct dirent *stu_dirent; char str_path[200]; char str_full_path[200]; char str_dir[200]; // // True formatting of the file system not implemented at this time // We will simply delete all files from the path to simulate this action // get_qsvar(request_info, "path", str_path, sizeof(str_path)); logger_remotem("FORMAT Device: %s", str_path); sprintf(str_dir, "%s%s", ODI_HOME, str_path); ptr_dir = opendir(str_dir); while ((stu_dirent = readdir(ptr_dir))) { if (strcmp(stu_dirent->d_name, ".") == 0 || strcmp(stu_dirent->d_name, "..") == 0 || stu_dirent->d_type == DT_DIR) { continue; } sprintf(str_full_path, "%s/%s", str_dir, stu_dirent->d_name); logger_remotem("Deleting file: %s %d", str_full_path, remove(str_full_path)); } mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=0\r\n"); logger_remotem("FORMAT Device: complete"); }
// 2. PUT_FILE static void proc_cmd_put_file(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_path[200]; char str_target_dir[200]; get_qsvar(request_info, "path", str_path, sizeof(str_path)); if (strcmp(str_path, CONF_DIRECTORY) != 0 && strcmp(str_path, DATA_DIRECTORY) != 0) { logger_remotem(" put_file path not valid = %s; switch to %s", str_path, UPLOAD_DIRECTORY); sprintf(str_path, "%s", UPLOAD_DIRECTORY); } sprintf(str_target_dir, "%s%s", ODI_HOME, str_path); memset(str_path, 0, 200); logger_remotem("PUT_FILE: path - %s", str_target_dir); FILE* fp = mg_upload(conn, str_target_dir, str_path, sizeof(str_path)); if (fp != NULL) { fclose(fp); logger_remotem("Upload success: put_file path - %s", str_path); } else { logger_remotem("PUT_FILE : Failed to send."); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nPut file failed\r\nerrno=%d\r\n", PUT_FILE_FAILED); return; } mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=0\r\n"); }
// 16. Remote command static void proc_command(struct mg_connection* conn, const struct mg_request_info* request_info) { char cmd[20]; char ret[100]; get_qsvar(request_info, "cmd", cmd, sizeof(cmd)); logger_remotem("proc_command=%s", cmd); if (strstr(cmd, "PLANB")) { char size[20]; get_qsvar(request_info, "size", size, sizeof(size)); int sz = atoi(size); set_planb_size(sz); strcpy(ret, size); } else if (strstr(cmd, "TIO")) { struct statvfs stat_buf; unsigned long long_free_blk; unsigned long long_data_size; char message[14]; statvfs(ODI_DATA, &stat_buf); long_free_blk = stat_buf.f_bavail * stat_buf.f_bsize / 1024000; long_data_size = stat_buf.f_blocks * stat_buf.f_bsize / 1024000; // for free size get time 35MB per minute logger_remotem("proc_recording_time: size=%u free=%u", long_data_size, long_free_blk); float fminutes = (float)long_free_blk / (float)35; int hour = fminutes / 60; int minutes = (int)fminutes - (hour * 60); int seconds = (fminutes - (minutes + hour * 60)) * 60.; sprintf(message, "TM%.2d:%.2d:%.2d\r\n", hour, minutes, seconds); strcpy(ret, message); get_command(message); } else { strcat(cmd, "\r\n"); strcpy(ret, get_command(cmd)); } mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "%s\r\n", ret); }
// ###################################################################### void *BeoWebServer::HTTPRequestCallback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { if (event == MG_NEW_REQUEST) { // Echo requested URI back to the client std::string uri(request_info->uri); std::string method(request_info->request_method); if (uri == "/image.jpg") { std::vector<byte> imgData = webserverStatic->getJpgImg(); mg_write(conn, &imgData[0], imgData.size()); LINFO("JPG Image Size %d",(int)imgData.size()); } else if(uri == "/cmd") { int tran = 0,rot = 0; char trans[5],rots[5]; get_qsvar(request_info, "trans", trans, sizeof(trans)); get_qsvar(request_info, "rot", rots, sizeof(rots)); tran = trans[0] == '\0' ? 0 : atoi(trans); rot = rots[0] == '\0' ? 0 : atoi(rots); LINFO("Trans speed is %d rot %d",tran,rot); webserverStatic->updateMotor(tran/100.0,rot/100.0); mg_printf(conn,"Trans speed %d Rot speed %d",tran,rot); } else if(uri == "/imu") { mg_printf(conn,"%s",webserverStatic->itsImuString.c_str()); } else if(uri == "/motor") { mg_printf(conn,"%s",webserverStatic->itsMotorString.c_str()); } else if(uri == "/lrf") { mg_printf(conn,"%s",webserverStatic->itsLrfString.c_str()); } else if(uri == "/gps") { mg_printf(conn,"%s",webserverStatic->itsGpsString.c_str()); } else { return NULL; } return (void *)""; // Mark as processed } else { return NULL; } }
// If "callback" param is present in query string, this is JSONP call. // Return 1 in this case, or 0 if "callback" is not specified. // Wrap an output in Javascript function call. static int handle_jsonp(struct mg_connection *conn, const struct mg_request_info *request_info) { char cb[64]; get_qsvar(request_info, "callback", cb, sizeof(cb)); if (cb[0] != '\0') { mg_printf(conn, "%s(", cb); } return cb[0] == '\0' ? 0 : 1; }
// A handler for the /authorize endpoint. // Login page form sends user name and password to this endpoint. struct session* authorize_ex(struct mg_connection *conn, const struct mg_request_info *request_info) { char user[MAX_USER_LEN], password[MAX_USER_LEN]; struct session *session; if (session = if_authorized(conn, request_info)) return session; // Fetch user name and password. get_qsvar(request_info, "user", user, sizeof(user)); get_qsvar(request_info, "password", password, sizeof(password)); if (check_password(user, password) && (session = new_session()) != NULL) { my_strlcpy(session->user, user, sizeof(session->user)); snprintf(session->random, sizeof(session->random), "%d", rand()); generate_session_id(session->session_id, session->random, session->user); return session; } return 0; }
// A handler for the /authorize endpoint. // Login page form sends user name and password to this endpoint. int authorize(struct mg_connection *conn, const struct mg_request_info *request_info) { char user[MAX_USER_LEN], password[MAX_USER_LEN]; struct session *session; // Fetch user name and password. get_qsvar(request_info, "user", user, sizeof(user)); get_qsvar(request_info, "password", password, sizeof(password)); if (check_password(user, password) && (session = new_session()) != NULL) { // Authentication success: // 1. create new session // 2. set session ID token in the cookie // 3. remove original_url from the cookie - not needed anymore // 4. redirect client back to the original URL // // The most secure way is to stay HTTPS all the time. However, just to // show the technique, we redirect to HTTP after the successful // authentication. The danger of doing this is that session cookie can // be stolen and an attacker may impersonate the user. // Secure application must use HTTPS all the time. my_strlcpy(session->user, user, sizeof(session->user)); snprintf(session->random, sizeof(session->random), "%d", rand()); generate_session_id(session->session_id, session->random, session->user); mg_printf(conn, "HTTP/1.1 302 Found\r\n" "Set-Cookie: session=%s; max-age=3600; http-only\r\n" // Session ID "Set-Cookie: user=%s\r\n"// Set user, needed by Javascript code "Set-Cookie: original_url=/; max-age=0\r\n"// Delete original_url "Location: /\r\n\r\n", session->session_id, session->user); return 1; } else { // Authentication failure, redirect to login. redirect_to_login(conn, request_info); return 0; } }
// 6. GET_DRIVE_INFO static void proc_cmd_get_drive_info(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_path[200]; char str_drive[200]; get_qsvar(request_info, "path", str_path, sizeof(str_path)); sprintf(str_drive, "/odi%s", str_path); logger_remotem("GET_DRIVE_INFO: %s", str_drive); unsigned long* drive_info = getDriveInfo(str_drive); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\n" "filesystem_size=%lu\r\n" "free_blocks=%lu\r\n" "errno=0\r\n", drive_info[0], drive_info[1]); }
// 4. GET_FILE static void proc_cmd_get_file(struct mg_connection *conn, const struct mg_request_info *request_info) { char str_file_path[200]; char str_full_path[200]; memset(str_file_path, 0, 200); memset(str_full_path, 0, 200); get_qsvar(request_info, "path", str_file_path, sizeof(str_file_path)); if (str_file_path == NULL || strlen(str_file_path) == 0) { logger_remotem("GET_FILE FAILED: no path entered"); mg_printf( conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "errno=%d\r\n", INPUT_PARAM_NOT_SPECIFIED); return; } char* str_file_name = basename(str_file_path); if ((my_str_cmp(str_file_path, UPLOAD_DIRECTORY) && my_str_cmp(str_file_path, CONF_DIRECTORY) && my_str_cmp(str_file_path, LOG_DIRECTORY) && my_str_cmp(str_file_path, DATA_DIRECTORY)) || (strlen(str_file_name) == 0)) { logger_remotem("GET_FILE FAILED: wrong path %s", str_file_path); mg_printf( conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "errno=%d\r\n", INPUT_PARAM_NOT_SPECIFIED); return; } sprintf(str_full_path, "%s%s", ODI_HOME, str_file_path); logger_remotem("GET_FILE STARTED: %s, client=%s", str_full_path, ip2s(request_info->remote_ip)); mg_send_file(conn, str_full_path); logger_remotem("GET_FILE COMPLETE, clearing caches: %s", str_full_path); system("echo 3 > /proc/sys/vm/drop_caches"); }
// A handler for the /ajax/get_messages endpoint. // Return a list of messages with ID greater than requested. static void ajax_get_messages(struct mg_connection *conn, const struct mg_request_info *request_info) { char last_id[32], *json; int is_jsonp; mg_printf(conn, "%s", ajax_reply_start); is_jsonp = handle_jsonp(conn, request_info); get_qsvar(request_info, "last_id", last_id, sizeof(last_id)); if ((json = messages_to_json(strtoul(last_id, NULL, 10))) != NULL) { mg_printf(conn, "[%s]", json); free(json); } if (is_jsonp) { mg_printf(conn, "%s", ")"); } }
// 9. LOAD_SOFTWARE_UPGRADE static void proc_cmd_load_sw_upgrade(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_command[200]; char str_path[200]; get_qsvar(request_info, "path", str_path, sizeof(str_path)); sprintf(str_command, "%s/%s %s > %s/firmware_upgrade 2>&1", ODI_BIN, SW_UPGRADE_COMMAND, str_path, ODI_LOG); // send uC Mess RFS logger_remotem("FIRMWARE UPGRADE send RFS to uC"); write_command_to_serial_port("RFS\r\n"); strcpy(downloading_status, "Upgrading"); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=0\r\n"); system(str_command); logger_remotem("Load sw upgrade: SUCCESS %s", str_command); write_command_to_serial_port("RFD\r\n"); logger_remotem("FIRMWARE UPGRADE: completed, execute reboot"); system(REBOOT_COMMAND); }
// This function will be called by mongoose on every new request. int web_engine::begin_request_handler(struct mg_connection *conn) { const struct mg_request_info *request_info = mg_get_request_info(conn); if (!strncmp(request_info->uri, "/json/",6)) { if (!strcmp(request_info->uri, "/json/game")) { return json_game_handler(conn); } if (!strcmp(request_info->uri, "/json/slider")) { return json_slider_handler(conn); } } else if (!strncmp(request_info->uri, "/cmd",4)) { char cmd_name[64]; get_qsvar(request_info, "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]; get_qsvar(request_info, "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]; get_qsvar(request_info, "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 1; } else if (!strncmp(request_info->uri, "/slider",7)) { char cmd_id[64]; char cmd_val[64]; get_qsvar(request_info, "id", cmd_id, sizeof(cmd_id)); get_qsvar(request_info, "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 1; } else if (!strncmp(request_info->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); if (filerr != FILERR_NONE) { return 0; } m_machine->video().save_snapshot(screen, file); astring fullpath(file.fullpath()); file.close(); mg_send_file(conn,fullpath); return 1; } return 0; }
// 8. LOAD_CONFIG_FILE // test: HTTP://192.168.1.155/cgi-bin/Flash2AppREMOTEM_load_config_file.cgi?path=/upload/input.xml static void proc_cmd_load_config_file(struct mg_connection* conn, const struct mg_request_info* request_info) { char configXmlPath[200]; char inputXmlPath[200]; char str_file_path[200]; char *address = 0, *netmask = 0, *gateway = 0; int dhcp = 0; char* broadcast_xml_field; char*rec_pre_xml_field; int found = 0; int isNetUpdate = 0; get_qsvar(request_info, "path", str_file_path, sizeof(str_file_path)); if (strlen(str_file_path) == 0) { mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=%d\r\n", INPUT_PARAM_NOT_SPECIFIED); return; } sprintf(inputXmlPath, "%s%s", ODI_HOME, str_file_path); sprintf(configXmlPath, "%s", ODI_CONFIG_XML); logger_remotem("load_config_file: merge XML Config File: from %s to %s", inputXmlPath, ODI_CONFIG_XML); struct my_file xmlfile = MY_STRUCT_FILE_INITIALIZER; if (!my_file_stat(inputXmlPath, &xmlfile)) { logger_remotem("No Input Config file to Load %s", inputXmlPath); send_http_error(conn, 404, "No Input Config file to Load ", "%s not found", inputXmlPath); goto leave; } if (!my_file_stat(ODI_CONFIG_XML, &xmlfile)) { logger_remotem("No destination Config file to Merge %s", ODI_CONFIG_XML); send_http_error(conn, 404, "No original config file to compare for merge ", "%s not found", ODI_CONFIG_XML); goto leave; } // read network file logger_remotem("Start merge XML Config File: %s", inputXmlPath); xmlDocPtr inputXmlDocumentPointer = xmlParseFile(inputXmlPath); if (inputXmlDocumentPointer == 0) { logger_remotem("LOAD_CONFIG_FILE: input XML not well formed %s", inputXmlPath); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nInputXML file is not well-formed.\r\n"); return; } xmlDocPtr configXmlDocumentPointer = xmlParseFile(ODI_CONFIG_XML); if (configXmlDocumentPointer == 0) { logger_remotem("LOAD_CONFIG_FILE: config XML not well formed %s", ODI_CONFIG_XML); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nConfiguration XML file is not well-formed.\r\n"); return; } // doc check xmlNodePtr cur = xmlDocGetRootElement(inputXmlDocumentPointer); if (cur == NULL) { logger_remotem("LOAD_CONFIG_FILE: input XML is empty"); xmlFreeDoc(configXmlDocumentPointer); xmlFreeDoc(inputXmlDocumentPointer); goto leave; } // config-meta check if (xmlStrcmp(cur->name, (const xmlChar*)"config-metadata")) { logger_remotem("LOAD_CONFIG_FILE: config-metadata tag not found"); xmlFreeDoc(configXmlDocumentPointer); xmlFreeDoc(inputXmlDocumentPointer); goto leave; } xmlNodePtr destParent = xmlDocGetRootElement(configXmlDocumentPointer); //node not found if (destParent == NULL) { logger_remotem("LOAD_CONFIG_FILE: empty doc"); xmlFreeDoc(configXmlDocumentPointer); xmlFreeDoc(inputXmlDocumentPointer); goto leave; } if (xmlStrcmp(destParent->name, (const xmlChar*)"config-metadata")) { logger_remotem("LOAD_CONFIG_FILE: root node != config-metadata"); xmlFreeDoc(configXmlDocumentPointer); xmlFreeDoc(inputXmlDocumentPointer); goto leave; } destParent = destParent->xmlChildrenNode; while (destParent) { if ((!xmlStrcmp(destParent->name, (const xmlChar*)"config"))) { found = 1; //Parse child content for field that need reboot xmlNodePtr info = destParent->xmlChildrenNode; while (info != NULL) { if (!xmlStrcmp(info->name, (const xmlChar*)"remotem_broadcast_ip")) { // logger_info("Tag 1: %s", info->name); // logger_info("Content: %s", (char *)xmlNodeGetContent(info)); broadcast_xml_field = (char*)xmlNodeGetContent(info); } else if (!xmlStrcmp(info->name, (const xmlChar *) "rec_pre")) { // logger_info("Tag 2: %s", info->name); // logger_info("Content: %s", (char *)xmlNodeGetContent(info)); rec_pre_xml_field = (char*)xmlNodeGetContent(info); } info = info->next; } break; } destParent = destParent->next; } if (!found) { logger_remotem("LOAD_CONFIG_FILE: config tag not found in %s", configXmlPath); xmlFreeDoc(configXmlDocumentPointer); xmlFreeDoc(inputXmlDocumentPointer); goto leave; } cur = cur->xmlChildrenNode; xmlNodePtr child = NULL; char *new_date = 0, *new_time = 0, *new_tz = 0; char str_comm[200]; unsigned int config_change_reboot = 0; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar*)"config"))) { child = cur->xmlChildrenNode; while (child != NULL) { if (!(xmlStrcmp(child->name, (const xmlChar*)"text"))) { ; } else if (!(xmlStrcmp(child->name, (const xmlChar*)"dvr_id"))) { // cannot change DVR ID ; } else if (!(xmlStrcmp(child->name, (const xmlChar*)"dts_date"))) { new_date = (char*)xmlNodeGetContent(child); if (strlen(new_date) == 10) // Check for valid date { logger_remotem("LOAD_CONFIG_FILE: setting date %s", new_date); modifytree(&destParent, child); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"dts_time"))) { new_time = (char*)xmlNodeGetContent(child); if (strlen(new_time) == 8) // Check for valid time { logger_remotem("LOAD_CONFIG_FILE: setting time %s", new_time); modifytree(&destParent, child); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"dvr_name"))) { char* str = (char*)xmlNodeGetContent(child); if (strlen(str) > 1) { logger_remotem("LOAD_CONFIG_FILE: setting dvr_name %s", str); modifytree(&destParent, child); set_dvr_name(str); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"ops_carnum"))) { char* str = (char*)xmlNodeGetContent(child); if (strlen(str) > 1) // Check for valid time { logger_remotem("LOAD_CONFIG_FILE: setting ops_carnum %s", str); modifytree(&destParent, child); set_dvr_name(str); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"usb_login"))) { char* str = (char*)xmlNodeGetContent(child); if (strlen(str) > 1) // Check for valid time { logger_remotem("LOAD_CONFIG_FILE: setting usb_login %s", str); modifytree(&destParent, child); set_assignable(str); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"dts_tz"))) { new_tz = (char*)xmlNodeGetContent(child); modifytree(&destParent, child); char ptr[strlen(new_tz) + 1]; int i, j = 0; for (i = 0; new_tz[i] != ' '; i++) { // skip till space } i++; // move up from the space for (i; new_tz[i] != '\0'; i++) { ptr[j++] = new_tz[i]; } ptr[j] = '\0'; memset(str_comm, 0, 200); sprintf(str_comm, "export TZ=%s", ptr); system(str_comm); } else if (!(xmlStrcmp(child->name, (const xmlChar*)"eth_dhcp"))) { isNetUpdate = 1; if (!(xmlStrcmp((const xmlChar*)xmlNodeGetContent(child), (const xmlChar*)"true"))) { dhcp = 1; logger_remotem("LOAD_CONFIG_FILE: change to DHCP"); } else { dhcp = 0; logger_remotem("LOAD_CONFIG_FILE: DHCP is static"); } modifytree(&destParent, child); } else if (!(xmlStrcmp(child->name, (const xmlChar*)"eth_addr"))) { address = (char *)xmlNodeGetContent(child); if (address != NULL && strlen(address) > 7) { isNetUpdate = 1; modifytree(&destParent, child); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"eth_mask"))) { netmask = (char*)xmlNodeGetContent(child); if (netmask != NULL && strlen(netmask) > 7) { isNetUpdate = 1; modifytree(&destParent, child); } } else if (!(xmlStrcmp(child->name, (const xmlChar*)"eth_gate"))) { gateway = (char*)xmlNodeGetContent(child); if (gateway != NULL && strlen(gateway) > 7) { isNetUpdate = 1; modifytree(&destParent, child); } // Set flag for config update item need to reboot to apply change } else if (!(xmlStrcmp(child->name, (const xmlChar*)"remotem_broadcast_ip"))) { logger_info("New: %s Old: %s", xmlNodeGetContent(child), broadcast_xml_field); if (strcmp((char*)xmlNodeGetContent(child), broadcast_xml_field)) { config_change_reboot = 1; } modifytree(&destParent, child); } else if (!(xmlStrcmp(child->name, (const xmlChar*)"rec_pre"))) { if (rec_pre_xml_field == NULL) { config_change_reboot = 1; } else if (strcmp((char*)xmlNodeGetContent(child), rec_pre_xml_field)) { if (strncmp(get_hw_version(), "3", 1)) // Only update when >= v4.0 { config_change_reboot = 1; } } modifytree(&destParent, child); } else { if (modifytree(&destParent, child) == -1) { logger_remotem("LOAD_CONFIG_FILE: %s doesn't contain %s tag", configXmlPath, (char*)child->name); } } child = child->next; } } cur = cur->next; } // end while loop until NULL all elements processed if (new_date == NULL && new_time == NULL) { logger_remotem("%s: date and time are null", __FUNCTION__); } else { set_sys_clock(new_date, new_time); } mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=0\r\n"); if (isNetUpdate) { update_network(dhcp, address, netmask, gateway); } logger_remotem("LOAD_CONFIG_FILE: saving new config, size=%d", xmlSaveFileEnc(configXmlPath, configXmlDocumentPointer, "UTF-8")); leave: if (inputXmlDocumentPointer) { xmlFreeDoc(inputXmlDocumentPointer); } if (configXmlDocumentPointer) { xmlFreeDoc(configXmlDocumentPointer); } if (config_change_reboot == 1) { logger_info("Config item change need system reboot"); // write_command_to_serial_port("RST\r\n"); // sleep(1); system("reboot"); } }
// 5. DELETE_FILE static void proc_cmd_delete_file(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_file_path[200]; char str_full_path[200]; // Get file name from the request get_qsvar(request_info, "path", str_file_path, sizeof(str_file_path)); sprintf(str_full_path, "%s%s", ODI_HOME, str_file_path); char* str_file_name = basename(str_file_path); if (str_file_path == NULL || strlen(str_file_path) == 0 || (strlen(str_file_name) == 0)) { logger_remotem("DELETE_FILE: path variable is null."); mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "errno=%d\r\n", INPUT_PARAM_NOT_SPECIFIED); return; } if (my_str_cmp(str_file_path, CONF_DIRECTORY) == 0 || my_str_cmp(str_file_path, LOG_DIRECTORY) == 0 || is_valid_file_path(str_full_path) == 0) { // error : : Input parameter not specified. logger_remotem("DELETE_FILE: invalid file path %s.", str_file_path); mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "errno=%d\r\n", FILE_NOT_ALLOWED_DELETE); return; } struct my_file file = MY_STRUCT_FILE_INITIALIZER; if (!my_file_stat(str_full_path, &file)) { logger_remotem("DELETE_FILE: File not found %s.", str_full_path); send_http_error(conn, 404, "Not Found", "%s", "File not found"); return; } else if (!file.modification_time) { logger_remotem("DELETE_FILE: IO error %s, errno %s", str_full_path, strerror(errno)); send_http_error(conn, 500, http_500_error, "remove(%s): %s", str_file_path, strerror(errno)); return; } else if (remove(str_full_path) != 0) { logger_remotem("DELETE_FILE: File Locked %s, errno %s", str_full_path, strerror(errno)); send_http_error(conn, 423, "Locked", "remove(%s): %s", str_file_path, strerror(errno)); return; } mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\nerrno=0\r\n"); logger_remotem("DELETE_FILE: SUCCESS path %s", str_file_path); system("sync;sync"); }
// 1. LIST_DIRECTORY static void proc_cmd_list_directory(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_path[20]; char str_date[20]; int date_filtered = 0; int log_dir = -1; get_qsvar(request_info, "path", str_path, sizeof(str_path)); //Get date range in number to filter later get_qsvar(request_info, "date", str_date, sizeof(str_date)); date_filtered = strtol(str_date, NULL, 10); //check if list log directory, only return *.log files if (NULL != strstr(str_path, (char *)LOG_DIRECTORY)) log_dir = 1; if (strcmp(str_path, UPLOAD_DIRECTORY) != 0 && strcmp(str_path, CONF_DIRECTORY) != 0 && strcmp(str_path, LOG_DIRECTORY) != 0 && strcmp(str_path, DATA_DIRECTORY) != 0) { // error : : Input parameter not specified. logger_remotem("list_directory FAILED path - %s", str_path); mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "errno=%d\r\n", INPUT_PARAM_NOT_SPECIFIED); return; } // Get file list char str_dir[50]; sprintf(str_dir, "%s%s", ODI_HOME, str_path); DIR* ptr_dir; struct dirent* stu_dirent; int int_items; char str_file_path[100]; char buff[20]; int_items = 0; ptr_dir = opendir(str_dir); if (ptr_dir == NULL) { mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "items=0\r\n" "errno=0\r\n"); return; } pthread_rwlock_rdlock(&rwlock); // Get count for malloc int vc = 2; while ((stu_dirent = readdir(ptr_dir))) { if (strcmp(stu_dirent->d_name, ".") == 0 || strcmp(stu_dirent->d_name, "..") == 0 || stu_dirent->d_type == DT_DIR) { continue; } else { vc++; } } closedir(ptr_dir); struct stat statbuf; char* str_ret_cont = (char*)malloc(vc * 100); memset(str_ret_cont, vc * 100, 0); struct tm tmi; ptr_dir = opendir(str_dir); int int_pos = 0; while ((stu_dirent = readdir(ptr_dir))) { if (strcmp(stu_dirent->d_name, ".") == 0 || strcmp(stu_dirent->d_name, "..") == 0 || stu_dirent->d_type == DT_DIR) { continue; } else { if (log_dir == -1) //other then /log directory return everything { sprintf(str_ret_cont + int_pos, "file.%d=%s/%s\r\n", int_items, str_path, stu_dirent->d_name); int_pos = strlen(str_ret_cont); sprintf(str_file_path, "%s/%s", str_dir, stu_dirent->d_name); if (stat(str_file_path, &statbuf) == -1) { sprintf(str_ret_cont + int_pos, "size.%d=0\r\n", int_items); int_pos = strlen(str_ret_cont); time_t now = time(NULL); strftime(buff, 20, "%Y%m%d-%H%M%S", localtime_r(&now, &tmi)); sprintf(str_ret_cont + int_pos, "date.%d=%s\r\n", int_items, buff); int_pos = strlen(str_ret_cont); } else { sprintf(str_ret_cont + int_pos, "size.%d=%u\r\n", int_items, (unsigned int)statbuf.st_size); int_pos = strlen(str_ret_cont); strftime(buff, 20, "%Y%m%d-%H%M%S", localtime_r(&(statbuf.st_mtime), &tmi)); sprintf(str_ret_cont + int_pos, "date.%d=%s\r\n", int_items, buff); int_pos = strlen(str_ret_cont); } int_items++; } else //only return log files { if (NULL != strstr(stu_dirent->d_name, "status")) //log file header name match { // Get file status sprintf(str_file_path, "%s/%s", str_dir, stu_dirent->d_name); stat(str_file_path, &statbuf); int current_date, file_date; char str_file_date[8]; // Get file date from file name strncpy((char*)&str_file_date[0], (char*)(stu_dirent->d_name + 7), 8); //strlen of "status_" file_date = strtol(str_file_date, NULL, 10); // Get current mon/date value to compare for current log file print time_t t = time(NULL); struct tm local = *localtime_r(&t, &tmi); current_date = (local.tm_year + 1900) * 10000 + (local.tm_mon + 1) * 100 + local.tm_mday; // Get file status stat(str_file_path, &statbuf); if (date_filtered > 0 && file_date >= date_filtered) //print filtered date { // File name sprintf(str_ret_cont + int_pos, "file.%d=%s/%s\r\n", int_items, str_path, stu_dirent->d_name); int_pos = strlen(str_ret_cont); sprintf(str_file_path, "%s/%s", str_dir, stu_dirent->d_name); // File size sprintf(str_ret_cont + int_pos, "size.%d=%u\r\n", int_items, (unsigned int)statbuf.st_size); int_pos = strlen(str_ret_cont); // File date strftime(buff, 20, "%Y%m%d-%H%M%S", localtime_r(&(statbuf.st_mtime), &tmi)); sprintf(str_ret_cont + int_pos, "date.%d=%s\r\n", int_items, buff); int_pos = strlen(str_ret_cont); int_items++; } else if (date_filtered <= 0 && current_date == file_date) { // File name sprintf(str_ret_cont + int_pos, "file.%d=%s/%s\r\n", int_items, str_path, stu_dirent->d_name); int_pos = strlen(str_ret_cont); sprintf(str_file_path, "%s/%s", str_dir, stu_dirent->d_name); // File size sprintf(str_ret_cont + int_pos, "size.%d=%u\r\n", int_items, statbuf.st_size); int_pos = strlen(str_ret_cont); // File date strftime(buff, 20, "%Y%m%d-%H%M%S", localtime_r(&(statbuf.st_mtime), &tmi)); sprintf(str_ret_cont + int_pos, "date.%d=%s\r\n", int_items, buff); int_pos = strlen(str_ret_cont); int_items++; } } } } } closedir(ptr_dir); pthread_rwlock_unlock(&rwlock); sprintf(str_ret_cont + int_pos, "items=%d\r\nerrno=0\r\n", int_items); mg_printf(conn, "HTTP/1.0 200 OK\r\n" "Content-Type: text/plain;charset=iso-8859-1\r\n\r\n" "%s\r\n", str_ret_cont); free(str_ret_cont); logger_remotem("List_directory completed path: %s, count=%d", str_path, int_items); }