Mercurial > hg > orthanc
comparison OrthancFramework/Sources/HttpServer/HttpToolbox.cpp @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | Core/HttpServer/HttpToolbox.cpp@94f4a18a79cc |
children | bf7b9edf6b81 |
comparison
equal
deleted
inserted
replaced
4043:6c6239aec462 | 4044:d25f4c0fa160 |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #include "../PrecompiledHeaders.h" | |
35 #include "HttpToolbox.h" | |
36 | |
37 #include <stdio.h> | |
38 #include <string.h> | |
39 #include <iostream> | |
40 | |
41 #include "HttpOutput.h" | |
42 #include "StringHttpOutput.h" | |
43 | |
44 | |
45 static const char* LOCALHOST = "127.0.0.1"; | |
46 | |
47 | |
48 | |
49 namespace Orthanc | |
50 { | |
51 static void SplitGETNameValue(IHttpHandler::GetArguments& result, | |
52 const char* start, | |
53 const char* end) | |
54 { | |
55 std::string name, value; | |
56 | |
57 const char* equal = strchr(start, '='); | |
58 if (equal == NULL || equal >= end) | |
59 { | |
60 name = std::string(start, end - start); | |
61 //value = ""; | |
62 } | |
63 else | |
64 { | |
65 name = std::string(start, equal - start); | |
66 value = std::string(equal + 1, end); | |
67 } | |
68 | |
69 Toolbox::UrlDecode(name); | |
70 Toolbox::UrlDecode(value); | |
71 | |
72 result.push_back(std::make_pair(name, value)); | |
73 } | |
74 | |
75 | |
76 void HttpToolbox::ParseGetArguments(IHttpHandler::GetArguments& result, | |
77 const char* query) | |
78 { | |
79 const char* pos = query; | |
80 | |
81 while (pos != NULL) | |
82 { | |
83 const char* ampersand = strchr(pos, '&'); | |
84 if (ampersand) | |
85 { | |
86 SplitGETNameValue(result, pos, ampersand); | |
87 pos = ampersand + 1; | |
88 } | |
89 else | |
90 { | |
91 // No more ampersand, this is the last argument | |
92 SplitGETNameValue(result, pos, pos + strlen(pos)); | |
93 pos = NULL; | |
94 } | |
95 } | |
96 } | |
97 | |
98 | |
99 void HttpToolbox::ParseGetQuery(UriComponents& uri, | |
100 IHttpHandler::GetArguments& getArguments, | |
101 const char* query) | |
102 { | |
103 const char *questionMark = ::strchr(query, '?'); | |
104 if (questionMark == NULL) | |
105 { | |
106 // No question mark in the string | |
107 Toolbox::SplitUriComponents(uri, query); | |
108 getArguments.clear(); | |
109 } | |
110 else | |
111 { | |
112 Toolbox::SplitUriComponents(uri, std::string(query, questionMark)); | |
113 HttpToolbox::ParseGetArguments(getArguments, questionMark + 1); | |
114 } | |
115 } | |
116 | |
117 | |
118 std::string HttpToolbox::GetArgument(const IHttpHandler::Arguments& getArguments, | |
119 const std::string& name, | |
120 const std::string& defaultValue) | |
121 { | |
122 IHttpHandler::Arguments::const_iterator it = getArguments.find(name); | |
123 if (it == getArguments.end()) | |
124 { | |
125 return defaultValue; | |
126 } | |
127 else | |
128 { | |
129 return it->second; | |
130 } | |
131 } | |
132 | |
133 | |
134 std::string HttpToolbox::GetArgument(const IHttpHandler::GetArguments& getArguments, | |
135 const std::string& name, | |
136 const std::string& defaultValue) | |
137 { | |
138 for (size_t i = 0; i < getArguments.size(); i++) | |
139 { | |
140 if (getArguments[i].first == name) | |
141 { | |
142 return getArguments[i].second; | |
143 } | |
144 } | |
145 | |
146 return defaultValue; | |
147 } | |
148 | |
149 | |
150 | |
151 void HttpToolbox::ParseCookies(IHttpHandler::Arguments& result, | |
152 const IHttpHandler::Arguments& httpHeaders) | |
153 { | |
154 result.clear(); | |
155 | |
156 IHttpHandler::Arguments::const_iterator it = httpHeaders.find("cookie"); | |
157 if (it != httpHeaders.end()) | |
158 { | |
159 const std::string& cookies = it->second; | |
160 | |
161 size_t pos = 0; | |
162 while (pos != std::string::npos) | |
163 { | |
164 size_t nextSemicolon = cookies.find(";", pos); | |
165 std::string cookie; | |
166 | |
167 if (nextSemicolon == std::string::npos) | |
168 { | |
169 cookie = cookies.substr(pos); | |
170 pos = std::string::npos; | |
171 } | |
172 else | |
173 { | |
174 cookie = cookies.substr(pos, nextSemicolon - pos); | |
175 pos = nextSemicolon + 1; | |
176 } | |
177 | |
178 size_t equal = cookie.find("="); | |
179 if (equal != std::string::npos) | |
180 { | |
181 std::string name = Toolbox::StripSpaces(cookie.substr(0, equal)); | |
182 std::string value = Toolbox::StripSpaces(cookie.substr(equal + 1)); | |
183 result[name] = value; | |
184 } | |
185 } | |
186 } | |
187 } | |
188 | |
189 | |
190 void HttpToolbox::CompileGetArguments(IHttpHandler::Arguments& compiled, | |
191 const IHttpHandler::GetArguments& source) | |
192 { | |
193 compiled.clear(); | |
194 | |
195 for (size_t i = 0; i < source.size(); i++) | |
196 { | |
197 compiled[source[i].first] = source[i].second; | |
198 } | |
199 } | |
200 | |
201 | |
202 bool HttpToolbox::SimpleGet(std::string& result, | |
203 IHttpHandler& handler, | |
204 RequestOrigin origin, | |
205 const std::string& uri, | |
206 const IHttpHandler::Arguments& httpHeaders) | |
207 { | |
208 UriComponents curi; | |
209 IHttpHandler::GetArguments getArguments; | |
210 ParseGetQuery(curi, getArguments, uri.c_str()); | |
211 | |
212 StringHttpOutput stream; | |
213 HttpOutput http(stream, false /* no keep alive */); | |
214 | |
215 if (handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Get, curi, | |
216 httpHeaders, getArguments, NULL /* no body for GET */, 0)) | |
217 { | |
218 stream.GetOutput(result); | |
219 return true; | |
220 } | |
221 else | |
222 { | |
223 return false; | |
224 } | |
225 } | |
226 | |
227 | |
228 static bool SimplePostOrPut(std::string& result, | |
229 IHttpHandler& handler, | |
230 RequestOrigin origin, | |
231 HttpMethod method, | |
232 const std::string& uri, | |
233 const void* bodyData, | |
234 size_t bodySize, | |
235 const IHttpHandler::Arguments& httpHeaders) | |
236 { | |
237 IHttpHandler::GetArguments getArguments; // No GET argument for POST/PUT | |
238 | |
239 UriComponents curi; | |
240 Toolbox::SplitUriComponents(curi, uri); | |
241 | |
242 StringHttpOutput stream; | |
243 HttpOutput http(stream, false /* no keep alive */); | |
244 | |
245 if (handler.Handle(http, origin, LOCALHOST, "", method, curi, | |
246 httpHeaders, getArguments, bodyData, bodySize)) | |
247 { | |
248 stream.GetOutput(result); | |
249 return true; | |
250 } | |
251 else | |
252 { | |
253 return false; | |
254 } | |
255 } | |
256 | |
257 | |
258 bool HttpToolbox::SimplePost(std::string& result, | |
259 IHttpHandler& handler, | |
260 RequestOrigin origin, | |
261 const std::string& uri, | |
262 const void* bodyData, | |
263 size_t bodySize, | |
264 const IHttpHandler::Arguments& httpHeaders) | |
265 { | |
266 return SimplePostOrPut(result, handler, origin, HttpMethod_Post, uri, bodyData, bodySize, httpHeaders); | |
267 } | |
268 | |
269 | |
270 bool HttpToolbox::SimplePut(std::string& result, | |
271 IHttpHandler& handler, | |
272 RequestOrigin origin, | |
273 const std::string& uri, | |
274 const void* bodyData, | |
275 size_t bodySize, | |
276 const IHttpHandler::Arguments& httpHeaders) | |
277 { | |
278 return SimplePostOrPut(result, handler, origin, HttpMethod_Put, uri, bodyData, bodySize, httpHeaders); | |
279 } | |
280 | |
281 | |
282 bool HttpToolbox::SimpleDelete(IHttpHandler& handler, | |
283 RequestOrigin origin, | |
284 const std::string& uri, | |
285 const IHttpHandler::Arguments& httpHeaders) | |
286 { | |
287 UriComponents curi; | |
288 Toolbox::SplitUriComponents(curi, uri); | |
289 | |
290 IHttpHandler::GetArguments getArguments; // No GET argument for DELETE | |
291 | |
292 StringHttpOutput stream; | |
293 HttpOutput http(stream, false /* no keep alive */); | |
294 | |
295 return handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Delete, curi, | |
296 httpHeaders, getArguments, NULL /* no body for DELETE */, 0); | |
297 } | |
298 } |