diff --git a/src/overpass_api/frontend/cgi-helper.cc b/src/overpass_api/frontend/cgi-helper.cc
index 186e0456c..42fd5b4a8 100644
--- a/src/overpass_api/frontend/cgi-helper.cc
+++ b/src/overpass_api/frontend/cgi-helper.cc
@@ -16,6 +16,7 @@
* along with Overpass_API. If not, see .
*/
+#include
#include
#include
#include
@@ -61,14 +62,21 @@ std::string cgi_get_to_text()
return "";
}
-std::string cgi_post_to_text()
+std::string cgi_post_to_text(std::string::size_type max_input_size)
{
- std::string raw, buf;
- while (!std::cin.eof())
+ std::string raw;
+ const std::streamsize chunk_size = 65536;
+ char chunk[chunk_size];
+
+ while (raw.size() <= max_input_size)
{
- getline(std::cin, buf);
- raw += buf + '\n';
+ std::cin.read(chunk, chunk_size);
+ std::streamsize count = std::cin.gcount();
+ if (count <= 0)
+ break;
+ raw.append(chunk, count);
}
+
return raw;
}
@@ -79,10 +87,8 @@ std::string replace_cgi(const std::string& raw)
while (pos < raw.size())
{
- if (raw[pos] == '%')
+ if (raw[pos] == '%' && pos + 2 < raw.size())
{
- if (pos >= raw.size()+2)
- return (result + raw.substr(0, pos));
char a(hex_digit(raw[pos+1])), b(hex_digit(raw[pos+2]));
if ((a < 16) && (b < 16))
{
@@ -115,8 +121,8 @@ std::map< std::string, std::string > decode_cgi_to_plain(const std::string& raw)
if (delim_pos == std::string::npos)
delim_pos = raw.size();
- std::string::size_type middle_pos = raw.find('=', pos);
- if (middle_pos != std::string::npos && middle_pos < delim_pos)
+ std::string::size_type middle_pos = std::find(raw.begin() + pos, raw.begin() + delim_pos, '=') - raw.begin();
+ if (middle_pos != delim_pos)
{
std::string::size_type end_pos = delim_pos;
while (end_pos > 0 && isspace(raw[end_pos-1]))
diff --git a/src/overpass_api/frontend/cgi-helper.h b/src/overpass_api/frontend/cgi-helper.h
index 983cbd804..a731da91b 100644
--- a/src/overpass_api/frontend/cgi-helper.h
+++ b/src/overpass_api/frontend/cgi-helper.h
@@ -25,7 +25,7 @@
std::string cgi_get_to_text();
-std::string cgi_post_to_text();
+std::string cgi_post_to_text(std::string::size_type max_input_size);
std::map< std::string, std::string > decode_cgi_to_plain(const std::string& raw);
diff --git a/src/overpass_api/frontend/user_interface.cc b/src/overpass_api/frontend/user_interface.cc
index 8b6fe764b..54e973cef 100644
--- a/src/overpass_api/frontend/user_interface.cc
+++ b/src/overpass_api/frontend/user_interface.cc
@@ -29,6 +29,7 @@
#include "cgi-helper.h"
#include "../../expat/expat_justparse_interface.h"
+#include "../data/utils.h"
#include "user_interface.h"
@@ -37,7 +38,7 @@ namespace
std::string autocomplete
(std::string& input, Error_Output* error_output, uint32 max_input_size)
{
- unsigned int pos(0), line_number(1);
+ std::size_t pos(0), line_number(1);
while ((pos < input.size()) && (isspace(input[pos])))
{
if (input[pos] == '\n')
@@ -124,10 +125,10 @@ std::map< std::string, std::string > get_xml_cgi(
char* origin = getenv("HTTP_ORIGIN");
has_origin = ((origin) && strnlen(origin, 1) > 0);
- int line_number(1);
+ std::size_t line_number(1);
// If there is nonempty input from GET method, use GET
std::string input(cgi_get_to_text());
- unsigned int pos(0);
+ std::size_t pos(0);
while ((pos < input.size()) && (isspace(input[pos])))
{
if (input[pos] == '\n')
@@ -159,7 +160,7 @@ std::map< std::string, std::string > get_xml_cgi(
error_output->add_encoding_remark("Only whitespace found from GET method. Trying to retrieve input by POST method.");
}
- input = cgi_post_to_text();
+ input = cgi_post_to_text(max_input_size);
pos = 0;
line_number = 1;
while ((pos < input.size()) && (isspace(input[pos])))
@@ -217,20 +218,44 @@ std::map< std::string, std::string > get_xml_cgi(
}
coords.push_back(lonlat.substr(pos));
- if (coords.size() == 4)
+ bool numeric = coords.size() == 4;
+ for (std::size_t i = 0; numeric && i < coords.size(); ++i)
{
- std::string latlon = coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2];
-
- pos = input.find("(bbox)");
- while (pos != std::string::npos)
- {
- input = input.substr(0, pos) + "(" + latlon + ")" + input.substr(pos + 6);
- pos = input.find("(bbox)");
- }
-
- pos = input.find("[bbox]");
- if (pos != std::string::npos)
- input = input.substr(0, pos) + "[bbox:" + latlon + "]" + input.substr(pos + 6);
+ double value = 0;
+ if (try_double(coords[i], value))
+ coords[i] = to_string(value);
+ else
+ numeric = false;
+ }
+
+ if (numeric)
+ {
+ std::string bbox_global = "[bbox:" + coords[1] + ',' + coords[0] + ',' + coords[3] + ',' + coords[2] + ']';
+ std::string bbox_filter = '(' + coords[1] + ',' + coords[0] + ',' + coords[3] + ',' + coords[2] + ')';
+
+ std::string modified;
+ std::string::size_type last = 0;
+ std::string::size_type paren = input.find("(bbox)");
+ std::string::size_type bracket = input.find("[bbox]");
+ while (paren != std::string::npos || bracket != std::string::npos)
+ {
+ if (bracket < paren)
+ {
+ modified.append(input, last, bracket - last);
+ modified += bbox_global;
+ last = bracket + 6;
+ bracket = std::string::npos;
+ }
+ else
+ {
+ modified.append(input, last, paren - last);
+ modified += bbox_filter;
+ last = paren + 6;
+ paren = input.find("(bbox)", last);
+ }
+ }
+ modified.append(input, last);
+ input.swap(modified);
}
}
}
@@ -253,7 +278,7 @@ std::string get_xml_console(Error_Output* error_output, uint32 max_input_size)
// If there is nonempty input from GET method, use GET
std::string input("");
- input = cgi_post_to_text();
+ input = cgi_post_to_text(max_input_size);
input = autocomplete(input, error_output, max_input_size);
return input;
}
diff --git a/src/overpass_api/output_formats/output_custom_factory.cc b/src/overpass_api/output_formats/output_custom_factory.cc
index a99dbc543..d10e4e48e 100644
--- a/src/overpass_api/output_formats/output_custom_factory.cc
+++ b/src/overpass_api/output_formats/output_custom_factory.cc
@@ -53,6 +53,13 @@ Output_Handler* Output_Custom_Generator::new_output_handler(const std::map< std:
error_output->add_encoding_error("Parameter \"template\" must not contain slashes.");
template_name = "";
}
+ // sanity check for url
+ if (url.find('\r') != std::string::npos || url.find('\n') != std::string::npos)
+ {
+ if (error_output)
+ error_output->add_encoding_error("Parameter \"url\" must not contain line breaks.");
+ url = "";
+ }
return new Output_Custom(redirect_it == input_params.end() || redirect_it->second != "no",
template_name, url);
diff --git a/src/pt_diagrams/processed_input.cc b/src/pt_diagrams/processed_input.cc
index 9d1e0b82f..4ba8438e4 100644
--- a/src/pt_diagrams/processed_input.cc
+++ b/src/pt_diagrams/processed_input.cc
@@ -765,20 +765,20 @@ void start(const char *el, const char **attr)
is_route = true;
if ((key == "route") && (value == "ferry"))
is_route = true;
- if (key == "operates_Mo_Fr")
+ if (key == "operates_Mo_Fr" && value.size() >= 9)
{
for (unsigned int i(0); i < 5; ++i)
relation.opening_hours.push_back(Timespan
(i, atoi(value.substr(0, 2).c_str()), atoi(value.substr(2, 2).c_str()),
i, atoi(value.substr(5, 2).c_str()), atoi(value.substr(7, 2).c_str())));
}
- if (key == "operates_Sa")
+ if (key == "operates_Sa" && value.size() >= 9)
{
relation.opening_hours.push_back(Timespan
(5, atoi(value.substr(0, 2).c_str()), atoi(value.substr(2, 2).c_str()),
5, atoi(value.substr(5, 2).c_str()), atoi(value.substr(7, 2).c_str())));
}
- if (key == "operates_Su")
+ if (key == "operates_Su" && value.size() >= 9)
{
relation.opening_hours.push_back(Timespan
(6, atoi(value.substr(0, 2).c_str()), atoi(value.substr(2, 2).c_str()),