#include #include #include #include #include #include #include #include #include #define DEFAULT_TMP_FILE_NAME "/tmp/image" #define DEFAULT_DST_FILE_NAME "/images/image" #define BLOCK_SIZE 131072 namespace api { namespace system { namespace update { static int update_progress = 0; static bool compare = false; bool compareFile(std::string tmpfilename, std::string dstfilename) { FILE *tmp = fopen(tmpfilename.c_str(), "r"); FILE *dst = fopen(dstfilename.c_str(), "r"); char tmpbuffer[BLOCK_SIZE]; char dstbuffer[BLOCK_SIZE]; do { size_t tmpread = fread(tmpbuffer, 1, BLOCK_SIZE, tmp); size_t dstread = fread(dstbuffer, 1, BLOCK_SIZE, dst); if (tmpread != dstread || memcmp(tmpbuffer, dstbuffer, tmpread)) { fclose(tmp); fclose(dst); return false; } } while (!feof(tmp) || !feof(dst)); fclose(tmp); fclose(dst); return true; } void upload(const httplib::Request& request, httplib::Response& response) { std::cout << GREEN << request.path << RESET << " " << request.method << std::endl; bool ret = request.has_file("image"); if (!ret) { response.set_content(R"({"required":[token, file]})", JSON_TYPE); } bool has_token = request.has_file("token"); if (!has_token) { response.set_content(ACCESS_REQUIRED_STRING, JSON_TYPE); return; } if (!authenticate(request.get_file_value("token").content)) { response.set_content(R"({"access":"reject"})", JSON_TYPE); return; } const httplib::MultipartFormData& file = request.get_file_value("image"); std::ofstream tmp_image_file(DEFAULT_TMP_FILE_NAME); tmp_image_file << file.content; tmp_image_file.close(); response.set_content(R"({"status":true})", JSON_TYPE); } void update(const httplib::Request& request, httplib::Response& response) { std::cout << GREEN << request.path << RESET << " " << request.method << std::endl; response.set_header("Access-Control-Allow-Origin", "*"); check_body_empty(request, response, ACCESS_REQUIRED_STRING); nlohmann::json json_body = nlohmann::json::parse(request.body); check_body_data(json_body, "token", response, ACCESS_REQUIRED_STRING); if (!authenticate(json_body["token"])) { response.set_content(R"({"access":"reject"})", JSON_TYPE); return; } bool needAutoReboot = json_body["needAutoReboot"]; update_progress = 0; compare = false; int file_image_size = std::filesystem::file_size(DEFAULT_TMP_FILE_NAME); int block_count = file_image_size / BLOCK_SIZE; int remainder = file_image_size % BLOCK_SIZE; int skip = 0; char buffer[BLOCK_SIZE]; std::ifstream tmp(DEFAULT_TMP_FILE_NAME); std::ofstream dst(DEFAULT_DST_FILE_NAME); while (skip < block_count) { tmp.read(buffer, BLOCK_SIZE); dst.write(buffer, BLOCK_SIZE); update_progress = 100 * skip / block_count; skip++; std::cout << update_progress << "% was copied" << std::endl; memset(buffer, 0, BLOCK_SIZE); } if (remainder > 0) { tmp.read(buffer, remainder); dst.write(buffer, remainder); update_progress = 100; std::cout << update_progress << "% was copied" << std::endl; } update_progress = 100; std::cout << update_progress << "% was copied" << std::endl; tmp.close(); dst.close(); compare = compareFile(DEFAULT_TMP_FILE_NAME, DEFAULT_DST_FILE_NAME); if (!compare) { std::cout << "files not equvalents: writing file error." << std::endl; response.set_content(R"({"success":false})", JSON_TYPE); return; } std::remove(DEFAULT_TMP_FILE_NAME); if (needAutoReboot) { std::cout << "reboot" << std::endl; std::system("sleep 2; reboot;"); return; } response.set_content(R"({"success":true})", JSON_TYPE); } void progress(const httplib::Request& request, httplib::Response& response) { std::cout << GREEN << request.path << RESET << " " << request.method << std::endl; std::string responsedata = R"({"progress":)" + std::to_string(update_progress) + "}"; response.set_content(responsedata, JSON_TYPE); } } } }