diff --git a/src/PortalTask.h b/src/PortalTask.h index 23c6635..f50ef23 100644 --- a/src/PortalTask.h +++ b/src/PortalTask.h @@ -227,12 +227,8 @@ protected: // restore sensors settings if (!requestDoc[FPSTR(S_SENSORS)].isNull()) { for (auto sensor : requestDoc[FPSTR(S_SENSORS)].as()) { - if (!isDigit(sensor.key().c_str())) { - continue; - } - - int sensorId = atoi(sensor.key().c_str()); - if (sensorId < 0 || sensorId > 255 || !Sensors::isValidSensorId(sensorId)) { + uint8_t sensorId; + if (!Sensors::parseId(sensor.key().c_str(), sensorId)) { continue; } @@ -420,12 +416,8 @@ protected: } const auto& id = request->getParam("id")->value(); - if (!isDigit(id.c_str())) { - return request->send(400); - } - - uint8_t sensorId = id.toInt(); - if (!Sensors::isValidSensorId(sensorId)) { + uint8_t sensorId; + if (!Sensors::parseId(id.c_str(), sensorId)) { return request->send(404); } @@ -451,12 +443,8 @@ protected: } auto& id = request->getParam("id")->value(); - if (!isDigit(id.c_str())) { - return request->send(400); - } - - uint8_t sensorId = id.toInt(); - if (!Sensors::isValidSensorId(sensorId)) { + uint8_t sensorId; + if (!Sensors::parseId(id.c_str(), sensorId)) { return request->send(404); } diff --git a/src/Sensors.h b/src/Sensors.h index fd40a1f..d694a18 100644 --- a/src/Sensors.h +++ b/src/Sensors.h @@ -1,4 +1,6 @@ #pragma once +#include +#include class Sensors { protected: @@ -121,10 +123,26 @@ public: return maxSensors > 1 ? (maxSensors - 1) : 0; } - static inline bool isValidSensorId(const uint8_t id) { + template + static bool isValidSensorId(const T id) { return id >= 0 && id <= getMaxSensorId(); } + static bool parseId(const char* value, uint8_t& sensorId) { + if (!isDigit(value)) { + return false; + } + + errno = 0; + const unsigned long parsed = strtoul(value, nullptr, 10); + if (errno == ERANGE || !isValidSensorId(parsed)) { + return false; + } + + sensorId = static_cast(parsed); + return true; + } + static inline bool isValidValueId(const uint8_t id) { return id >= (uint8_t) ValueType::TEMPERATURE && id <= (uint8_t) ValueType::RSSI; } @@ -499,6 +517,22 @@ public: static uint8_t bluetoothRssiToQuality(int rssi) { return constrain(map(rssi, -110, -50, 0, 100), 0, 100);; } + +private: + static constexpr bool isDigit(const char* value) { + if (value == nullptr || *value == '\0') { + return false; + } + + while (*value != '\0') { + if (*value < '0' || *value > '9') { + return false; + } + value++; + } + + return true; + } }; uint8_t Sensors::maxSensors = 0; diff --git a/src/utils.h b/src/utils.h index 9553bd8..499670b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -70,12 +70,6 @@ time_t mkgmtime(const struct tm *ptm) { return secs; } -inline bool isDigit(const char* ptr) { - char* endPtr; - auto tmp = strtol(ptr, &endPtr, 10); - return *endPtr == 0; -} - inline float liter2gallon(float value) { return value / 4.546091879f; }