blob: 8f5114b783579f6476ff61b25e5f0b5f99326ddb [file] [log] [blame]
Ratan Gupta453fed02019-12-14 09:39:47 +05301#pragma once
2#include <app.h>
3#include <tinyxml2.h>
4
5#include <async_resp.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -06006#include <boost/algorithm/string.hpp>
7#include <boost/container/flat_set.hpp>
8#include <filesystem>
9#include <fstream>
10#include <regex>
11#include <sdbusplus/message/types.hpp>
12
13#define MAX_SAVE_AREA_FILESIZE 200000
Ratan Gupta453fed02019-12-14 09:39:47 +053014
15namespace crow
16{
17namespace ibm_mc
18{
Sunitha Harish97b0e432019-11-21 04:59:29 -060019constexpr const char *methodNotAllowedMsg = "Method Not Allowed";
20constexpr const char *resourceNotFoundMsg = "Resource Not Found";
21constexpr const char *contentNotAcceptableMsg = "Content Not Acceptable";
22constexpr const char *internalServerError = "Internal Server Error";
23
24bool createSaveAreaPath(crow::Response &res)
25{
26 // The path /var/lib/obmc will be created by initrdscripts
27 // Create the directories for the save-area files, when we get
28 // first file upload request
29 std::error_code ec;
30 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
31 {
32 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
33 }
34 if (ec)
35 {
36 res.result(boost::beast::http::status::internal_server_error);
37 res.jsonValue["Description"] = internalServerError;
38 BMCWEB_LOG_DEBUG
39 << "handleIbmPost: Failed to prepare save-area directory. ec : "
40 << ec;
41 return false;
42 }
43
44 if (!std::filesystem::is_directory(
45 "/var/lib/obmc/bmc-console-mgmt/save-area", ec))
46 {
47 std::filesystem::create_directory(
48 "/var/lib/obmc/bmc-console-mgmt/save-area", ec);
49 }
50 if (ec)
51 {
52 res.result(boost::beast::http::status::internal_server_error);
53 res.jsonValue["Description"] = internalServerError;
54 BMCWEB_LOG_DEBUG
55 << "handleIbmPost: Failed to prepare save-area directory. ec : "
56 << ec;
57 return false;
58 }
59 return true;
60}
61void handleFilePut(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -050062 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -060063{
64 // Check the content-type of the request
65 std::string_view contentType = req.getHeaderValue("content-type");
66 if (boost::starts_with(contentType, "multipart/form-data"))
67 {
68 BMCWEB_LOG_DEBUG
69 << "This is multipart/form-data. Invalid content for PUT";
70
71 res.result(boost::beast::http::status::not_acceptable);
72 res.jsonValue["Description"] = contentNotAcceptableMsg;
73 return;
74 }
75 else
76 {
77 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue..";
78 }
asmithakarun1c7b07c2019-09-09 03:42:59 -050079
80 BMCWEB_LOG_DEBUG
81 << "handleIbmPut: Request to create/update the save-area file";
82 if (!createSaveAreaPath(res))
Sunitha Harish97b0e432019-11-21 04:59:29 -060083 {
asmithakarun1c7b07c2019-09-09 03:42:59 -050084 res.result(boost::beast::http::status::not_found);
85 res.jsonValue["Description"] = resourceNotFoundMsg;
86 return;
87 }
88 // Create the file
89 std::ofstream file;
90 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
91 loc /= fileID;
Sunitha Harish97b0e432019-11-21 04:59:29 -060092
asmithakarun1c7b07c2019-09-09 03:42:59 -050093 std::string data = std::move(req.body);
94 BMCWEB_LOG_DEBUG << "data capaticty : " << data.capacity();
95 if (data.capacity() > MAX_SAVE_AREA_FILESIZE)
96 {
97 res.result(boost::beast::http::status::bad_request);
98 res.jsonValue["Description"] =
99 "File size exceeds 200KB. Maximum allowed size is 200KB";
100 return;
101 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600102
asmithakarun1c7b07c2019-09-09 03:42:59 -0500103 BMCWEB_LOG_DEBUG << "Creating file " << loc;
104 file.open(loc, std::ofstream::out);
105 if (file.fail())
106 {
107 BMCWEB_LOG_DEBUG << "Error while opening the file for writing";
108 res.result(boost::beast::http::status::internal_server_error);
109 res.jsonValue["Description"] = "Error while creating the file";
110 return;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600111 }
112 else
113 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500114 file << data;
115 BMCWEB_LOG_DEBUG << "save-area file is created";
116 res.jsonValue["Description"] = "File Created";
117 }
118
119 return;
120}
121
122void handleFileGet(crow::Response &res, const std::string &fileID)
123{
124 BMCWEB_LOG_DEBUG << "HandleGet on SaveArea files on path: " << fileID;
125 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area/" +
126 fileID);
127 if (!std::filesystem::exists(loc))
128 {
129 BMCWEB_LOG_ERROR << loc << "Not found";
130 res.result(boost::beast::http::status::not_found);
131 res.jsonValue["Description"] = resourceNotFoundMsg;
132 return;
133 }
134
135 std::ifstream readfile(loc.string());
136 if (!readfile)
137 {
138 BMCWEB_LOG_ERROR << loc.string() << "Not found";
139 res.result(boost::beast::http::status::not_found);
140 res.jsonValue["Description"] = resourceNotFoundMsg;
141 return;
142 }
143
144 std::string contentDispositionParam =
145 "attachment; filename=\"" + fileID + "\"";
146 res.addHeader("Content-Disposition", contentDispositionParam);
147 std::string fileData;
148 fileData = {std::istreambuf_iterator<char>(readfile),
149 std::istreambuf_iterator<char>()};
150 res.jsonValue["Data"] = fileData;
151 return;
152}
153
154void handleFileDelete(crow::Response &res, const std::string &fileID)
155{
156 std::string filePath("/var/lib/obmc/bmc-console-mgmt/save-area/" + fileID);
157 BMCWEB_LOG_DEBUG << "Removing the file : " << filePath << "\n";
158
159 std::ifstream file_open(filePath.c_str());
160 if (static_cast<bool>(file_open))
161 if (remove(filePath.c_str()) == 0)
162 {
163 BMCWEB_LOG_DEBUG << "File removed!\n";
164 res.jsonValue["Description"] = "File Deleted";
165 }
166 else
167 {
168 BMCWEB_LOG_ERROR << "File not removed!\n";
169 res.result(boost::beast::http::status::internal_server_error);
170 res.jsonValue["Description"] = internalServerError;
171 }
172 else
173 {
174 BMCWEB_LOG_ERROR << "File not found!\n";
Sunitha Harish97b0e432019-11-21 04:59:29 -0600175 res.result(boost::beast::http::status::not_found);
176 res.jsonValue["Description"] = resourceNotFoundMsg;
177 }
178 return;
179}
180
181inline void handleFileUrl(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -0500182 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600183{
Sunitha Harish97b0e432019-11-21 04:59:29 -0600184 if (req.method() == "PUT"_method)
185 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500186 handleFilePut(req, res, fileID);
Sunitha Harish97b0e432019-11-21 04:59:29 -0600187 res.end();
188 return;
189 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500190 if (req.method() == "GET"_method)
191 {
192 handleFileGet(res, fileID);
193 res.end();
194 return;
195 }
196 if (req.method() == "DELETE"_method)
197 {
198 handleFileDelete(res, fileID);
199 res.end();
200 return;
201 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600202}
Ratan Gupta453fed02019-12-14 09:39:47 +0530203
204template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
205{
206
207 // allowed only for admin
208 BMCWEB_ROUTE(app, "/ibm/v1/")
209 .requires({"ConfigureComponents", "ConfigureManager"})
210 .methods("GET"_method)(
211 [](const crow::Request &req, crow::Response &res) {
212 res.jsonValue["@odata.type"] =
213 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
214 res.jsonValue["@odata.id"] = "/ibm/v1/";
215 res.jsonValue["Id"] = "IBM Rest RootService";
216 res.jsonValue["Name"] = "IBM Service Root";
217 res.jsonValue["ConfigFiles"] = {
218 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}};
219 res.jsonValue["LockService"] = {
220 {"@odata.id", "/ibm/v1/HMC/LockService"}};
221 res.end();
222 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600223
asmithakarun1c7b07c2019-09-09 03:42:59 -0500224 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<path>")
Sunitha Harish97b0e432019-11-21 04:59:29 -0600225 .requires({"ConfigureComponents", "ConfigureManager"})
asmithakarun1c7b07c2019-09-09 03:42:59 -0500226 .methods("PUT"_method, "GET"_method, "DELETE"_method)(
227 [](const crow::Request &req, crow::Response &res,
228 const std::string &path) { handleFileUrl(req, res, path); });
Ratan Gupta453fed02019-12-14 09:39:47 +0530229}
230
231} // namespace ibm_mc
232} // namespace crow