From 4175fe56fd5117fde451ea3c68eaec0b6630c6b8 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 28 Jul 2020 17:18:42 +0200 Subject: [PATCH] fix standalone (use make run) --- lib_standalone/Arduino.cpp | 69 +- lib_standalone/Arduino.h | 32 - lib_standalone/AsyncMqttClient.h | 204 ++--- lib_standalone/AsyncTCP.h | 193 +---- lib_standalone/ESP8266React.h | 50 +- lib_standalone/ESPAsyncWebServer.h | 415 +--------- lib_standalone/SecuritySettingsService.cpp | 141 ++++ lib_standalone/SecuritySettingsService.h | 116 +++ lib_standalone/WString.cpp | 907 ++------------------- lib_standalone/WString.h | 285 ++----- src/EMSESPDevicesService.cpp | 2 + src/system.cpp | 8 +- src/test/test.cpp | 2 +- 13 files changed, 520 insertions(+), 1904 deletions(-) create mode 100644 lib_standalone/SecuritySettingsService.cpp create mode 100644 lib_standalone/SecuritySettingsService.h diff --git a/lib_standalone/Arduino.cpp b/lib_standalone/Arduino.cpp index b2bf854ac..4e25c2cc6 100644 --- a/lib_standalone/Arduino.cpp +++ b/lib_standalone/Arduino.cpp @@ -37,6 +37,7 @@ static bool __output_pins[256]; static int __output_level[256]; int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) { + memset(__output_pins, 0, sizeof(__output_pins)); memset(__output_level, 0, sizeof(__output_level)); @@ -111,71 +112,3 @@ int digitalRead(uint8_t pin) { return LOW; } } - - - - -/* - * Copy string src to buffer dst of size dsize. At most dsize-1 - * chars will be copied. Always NUL terminates (unless dsize == 0). - * Returns strlen(src); if retval >= dsize, truncation occurred. - * - * https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c - */ -size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) { - const char * osrc = src; - size_t nleft = dsize; - - /* Copy as many bytes as will fit. */ - if (nleft != 0) { - while (--nleft != 0) { - if ((*dst++ = *src++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src. */ - if (nleft == 0) { - if (dsize != 0) - *dst = '\0'; /* NUL-terminate dst */ - while (*src++) - ; - } - - return (src - osrc - 1); /* count does not include NUL */ -} - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - * - * https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcat.c - */ -size_t strlcat(char * dst, const char * src, size_t siz) { - char * d = dst; - const char * s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return (dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return (dlen + (s - src)); /* count does not include NUL */ -} diff --git a/lib_standalone/Arduino.h b/lib_standalone/Arduino.h index 459fba0d8..fbefdc5f7 100644 --- a/lib_standalone/Arduino.h +++ b/lib_standalone/Arduino.h @@ -136,34 +136,6 @@ class Stream : public Print { virtual int peek() = 0; }; -/* -class String { - public: - String(const char * data = "") - : data_(data) { - } - - long toInt() const { - return std::stol(data_); - } - - const char * c_str() const { - return data_.c_str(); - } - - bool equals(String comp) { - return (data_ == comp.c_str()); - } - - bool isEmpty() { - return data_.empty(); - } - - private: - std::string data_; -}; -*/ - class NativeConsole : public Stream { public: void begin(unsigned long baud __attribute__((unused))) { @@ -225,10 +197,6 @@ void yield(void); void setup(void); void loop(void); - -size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize); -size_t strlcat(char * dst, const char * src, size_t siz); - #include "WString.h" #endif diff --git a/lib_standalone/AsyncMqttClient.h b/lib_standalone/AsyncMqttClient.h index 60751f0f9..73a1058ea 100644 --- a/lib_standalone/AsyncMqttClient.h +++ b/lib_standalone/AsyncMqttClient.h @@ -5,139 +5,115 @@ #include enum class AsyncMqttClientDisconnectReason : int8_t { - TCP_DISCONNECTED = 0, + TCP_DISCONNECTED = 0, - MQTT_UNACCEPTABLE_PROTOCOL_VERSION = 1, - MQTT_IDENTIFIER_REJECTED = 2, - MQTT_SERVER_UNAVAILABLE = 3, - MQTT_MALFORMED_CREDENTIALS = 4, - MQTT_NOT_AUTHORIZED = 5, + MQTT_UNACCEPTABLE_PROTOCOL_VERSION = 1, + MQTT_IDENTIFIER_REJECTED = 2, + MQTT_SERVER_UNAVAILABLE = 3, + MQTT_MALFORMED_CREDENTIALS = 4, + MQTT_NOT_AUTHORIZED = 5, - ESP8266_NOT_ENOUGH_SPACE = 6, + ESP8266_NOT_ENOUGH_SPACE = 6, - TLS_BAD_FINGERPRINT = 7 + TLS_BAD_FINGERPRINT = 7 }; struct AsyncMqttClientMessageProperties { - uint8_t qos; - bool dup; - bool retain; + uint8_t qos; + bool dup; + bool retain; }; namespace AsyncMqttClientInternals { -// user callbacks -typedef std::function OnConnectUserCallback; + +typedef std::function OnConnectUserCallback; typedef std::function OnDisconnectUserCallback; -typedef std::function OnSubscribeUserCallback; -typedef std::function OnUnsubscribeUserCallback; -typedef std::function OnMessageUserCallback; +typedef std::function OnSubscribeUserCallback; +typedef std::function OnUnsubscribeUserCallback; +typedef std::function OnMessageUserCallback; typedef std::function OnPublishUserCallback; -}; +}; // namespace AsyncMqttClientInternals class AsyncMqttClient { - public: - AsyncMqttClient(); - ~AsyncMqttClient(); + public: + AsyncMqttClient(); + ~AsyncMqttClient(); - AsyncMqttClient& setKeepAlive(uint16_t keepAlive); - AsyncMqttClient& setClientId(const char* clientId); - AsyncMqttClient& setCleanSession(bool cleanSession); - AsyncMqttClient& setMaxTopicLength(uint16_t maxTopicLength); - AsyncMqttClient& setCredentials(const char* username, const char* password = nullptr); - AsyncMqttClient& setWill(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0) { return *this; } - AsyncMqttClient& setServer(IPAddress ip, uint16_t port); - AsyncMqttClient& setServer(const char* host, uint16_t port); + AsyncMqttClient & setKeepAlive(uint16_t keepAlive); + AsyncMqttClient & setClientId(const char * clientId); + AsyncMqttClient & setCleanSession(bool cleanSession); + AsyncMqttClient & setMaxTopicLength(uint16_t maxTopicLength); + AsyncMqttClient & setCredentials(const char * username, const char * password = nullptr); + AsyncMqttClient & setWill(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0) { + return *this; + } + AsyncMqttClient & setServer(IPAddress ip, uint16_t port); + AsyncMqttClient & setServer(const char * host, uint16_t port); - AsyncMqttClient& onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback) { return *this; } - AsyncMqttClient& onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback) { return *this; } - AsyncMqttClient& onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback) { return *this; } - AsyncMqttClient& onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback) { return *this; } - AsyncMqttClient& onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback) { return *this; } - AsyncMqttClient& onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback) { return *this; } + AsyncMqttClient & onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback) { + return *this; + } + AsyncMqttClient & onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback) { + return *this; + } + AsyncMqttClient & onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback) { + return *this; + } + AsyncMqttClient & onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback) { + return *this; + } + AsyncMqttClient & onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback) { + return *this; + } + AsyncMqttClient & onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback) { + return *this; + } - bool connected() const { return false; } - void connect() {} - void disconnect(bool force = false) {} - uint16_t subscribe(const char* topic, uint8_t qos) {return 0;} - uint16_t unsubscribe(const char* topic) {return 0;} - uint16_t publish(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0) {return 0;} + bool connected() const { + return false; + } + void connect() { + } + void disconnect(bool force = false) { + } + uint16_t subscribe(const char * topic, uint8_t qos) { + return 0; + } + uint16_t unsubscribe(const char * topic) { + return 0; + } + uint16_t publish(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0) { + return 0; + } - const char* getClientId() {return "12";} + const char * getClientId() { + return "12"; + } - private: -// AsyncClient _client; - - bool _connected; - bool _connectPacketNotEnoughSpace; - bool _disconnectOnPoll; - bool _tlsBadFingerprint; - uint32_t _lastClientActivity; - uint32_t _lastServerActivity; - uint32_t _lastPingRequestTime; - char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456 - IPAddress _ip; - const char* _host; - bool _useIp; - uint16_t _port; - uint16_t _keepAlive; - bool _cleanSession; - const char* _clientId; - const char* _username; - const char* _password; - const char* _willTopic; - const char* _willPayload; - uint16_t _willPayloadLength; - uint8_t _willQos; - bool _willRetain; - -// std::vector _onConnectUserCallbacks; -// std::vector _onDisconnectUserCallbacks; -// std::vector _onSubscribeUserCallbacks; -// std::vector _onUnsubscribeUserCallbacks; -// std::vector _onMessageUserCallbacks; -// std::vector _onPublishUserCallbacks; - -// AsyncMqttClientInternals::ParsingInformation _parsingInformation; -// AsyncMqttClientInternals::Packet* _currentParsedPacket; -// uint8_t _remainingLengthBufferPosition; -// char _remainingLengthBuffer[4]; - -// uint16_t _nextPacketId; - -// std::vector _pendingPubRels; - -// std::vector _toSendAcks; - -// void _clear(); -// void _freeCurrentParsedPacket(); - - // TCP -// void _onConnect(AsyncClient* client); -// void _onDisconnect(AsyncClient* client); -// static void _onError(AsyncClient* client, int8_t error); -// void _onTimeout(AsyncClient* client, uint32_t time); -// static void _onAck(AsyncClient* client, size_t len, uint32_t time); -// void _onData(AsyncClient* client, char* data, size_t len); -// void _onPoll(AsyncClient* client); - -// // MQTT -// void _onPingResp(); -// void _onConnAck(bool sessionPresent, uint8_t connectReturnCode); -// void _onSubAck(uint16_t packetId, char status); -// void _onUnsubAck(uint16_t packetId); -// void _onMessage(char* topic, char* payload, uint8_t qos, bool dup, bool retain, size_t len, size_t index, size_t total, uint16_t packetId); -// void _onPublish(uint16_t packetId, uint8_t qos); -// void _onPubRel(uint16_t packetId); -// void _onPubAck(uint16_t packetId); -// void _onPubRec(uint16_t packetId); -// void _onPubComp(uint16_t packetId); - -// bool _sendPing(); -// void _sendAcks(); -// bool _sendDisconnect(); - -// uint16_t _getNextPacketId(); + private: + bool _connected; + bool _connectPacketNotEnoughSpace; + bool _disconnectOnPoll; + bool _tlsBadFingerprint; + uint32_t _lastClientActivity; + uint32_t _lastServerActivity; + uint32_t _lastPingRequestTime; + char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456 + IPAddress _ip; + const char * _host; + bool _useIp; + uint16_t _port; + uint16_t _keepAlive; + bool _cleanSession; + const char * _clientId; + const char * _username; + const char * _password; + const char * _willTopic; + const char * _willPayload; + uint16_t _willPayloadLength; + uint8_t _willQos; + bool _willRetain; }; #endif \ No newline at end of file diff --git a/lib_standalone/AsyncTCP.h b/lib_standalone/AsyncTCP.h index 3b82e964d..c06bbd0a5 100644 --- a/lib_standalone/AsyncTCP.h +++ b/lib_standalone/AsyncTCP.h @@ -1,212 +1,29 @@ -/* - Asynchronous TCP library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ #include "Arduino.h" #include -//If core is not defined, then we are running in Arduino or PIO -#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE -#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core -#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event -#endif - class AsyncClient; -#define ASYNC_MAX_ACK_TIME 5000 -#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) -#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. - -typedef std::function AcConnectHandler; -typedef std::function AcAckHandler; -typedef std::function AcErrorHandler; -typedef std::function AcDataHandler; -typedef std::function AcPacketHandler; -typedef std::function AcTimeoutHandler; - struct tcp_pcb; struct ip_addr; class AsyncClient { public: - AsyncClient(tcp_pcb* pcb = 0); + AsyncClient(tcp_pcb * pcb = 0); ~AsyncClient(); - - AsyncClient & operator=(const AsyncClient &other); - AsyncClient & operator+=(const AsyncClient &other); - - bool operator==(const AsyncClient &other); - - bool operator!=(const AsyncClient &other) { - return !(*this == other); - } - bool connect(IPAddress ip, uint16_t port); - bool connect(const char* host, uint16_t port); - void close(bool now = false); - void stop(); - int8_t abort(); - bool free(); - - bool canSend();//ack is not pending - size_t space();//space available in the TCP window - size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending - bool send();//send all data added with the method above - - //write equals add()+send() - size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true - - uint8_t state(); - bool connecting(); - bool connected(); - bool disconnecting(); - bool disconnected(); - bool freeable();//disconnected or disconnecting - - uint16_t getMss(); - - uint32_t getRxTimeout(); - void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds - - uint32_t getAckTimeout(); - void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds - - void setNoDelay(bool nodelay); - bool getNoDelay(); - - uint32_t getRemoteAddress(); - uint16_t getRemotePort(); - uint32_t getLocalAddress(); - uint16_t getLocalPort(); - - //compatibility - IPAddress remoteIP(); - uint16_t remotePort(); - IPAddress localIP(); - uint16_t localPort(); - - void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect - void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected - void onAck(AcAckHandler cb, void* arg = 0); //ack received - void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error - void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) - void onPacket(AcPacketHandler cb, void* arg = 0); //data received - void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout - void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected - - void ackPacket(struct pbuf * pb);//ack pbuf from onPacket - size_t ack(size_t len); //ack data that you have not acked using the method below - void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData - - const char * errorToString(int8_t error); - const char * stateToString(); - - //Do not use any of the functions below! - static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); - static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); - static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); - static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); - static void _s_error(void *arg, int8_t err); - static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); - static int8_t _s_connected(void* arg, void* tpcb, int8_t err); - static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); - - int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); - tcp_pcb * pcb(){ return _pcb; } - - protected: - tcp_pcb* _pcb; - int8_t _closed_slot; - - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - AcConnectHandler _discard_cb; - void* _discard_cb_arg; - AcAckHandler _sent_cb; - void* _sent_cb_arg; - AcErrorHandler _error_cb; - void* _error_cb_arg; - AcDataHandler _recv_cb; - void* _recv_cb_arg; - AcPacketHandler _pb_cb; - void* _pb_cb_arg; - AcTimeoutHandler _timeout_cb; - void* _timeout_cb_arg; - AcConnectHandler _poll_cb; - void* _poll_cb_arg; - - bool _pcb_busy; - uint32_t _pcb_sent_at; - bool _ack_pcb; - uint32_t _rx_ack_len; - uint32_t _rx_last_packet; - uint32_t _rx_since_timeout; - uint32_t _ack_timeout; - uint16_t _connect_port; - - int8_t _close(); - int8_t _connected(void* pcb, int8_t err); - void _error(int8_t err); - int8_t _poll(tcp_pcb* pcb); - int8_t _sent(tcp_pcb* pcb, uint16_t len); - int8_t _fin(tcp_pcb* pcb, int8_t err); - int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); - void _dns_found(struct ip_addr *ipaddr); - - public: - AsyncClient* prev; - AsyncClient* next; }; class AsyncServer { public: - AsyncServer(IPAddress addr, uint16_t port) : _port(port), _addr("poep") {}; - - AsyncServer(uint16_t port) : _port(port) {}; - - ~AsyncServer() {}; - void onClient(AcConnectHandler cb, void* arg); - void begin(); - void end(); - void setNoDelay(bool nodelay); - bool getNoDelay(); - uint8_t status(); - - //Do not use any of the functions below! - static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); - static int8_t _s_accepted(void *arg, AsyncClient* client); + AsyncServer(uint16_t port) + : _port(port){}; + ~AsyncServer(){}; protected: uint16_t _port; - IPAddress _addr; - bool _noDelay; - tcp_pcb* _pcb; - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - - int8_t _accept(tcp_pcb* newpcb, int8_t err); - int8_t _accepted(AsyncClient* client); }; -#endif /* ASYNCTCP_H_ */ +#endif diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 7c40f4ea5..718a32b67 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -4,32 +4,31 @@ #include #include #include -#include +#include #include #include -#include +#include +#include #include class DummySettings { public: - uint8_t tx_mode; - uint8_t ems_bus_id; - bool system_heartbeat; - int8_t syslog_level; // uuid::log::Level - uint32_t syslog_mark_interval; - String syslog_host; - uint8_t master_thermostat; - bool shower_timer; - bool shower_alert; - - uint16_t publish_time; // seconds - uint8_t mqtt_format; // 1=single, 2=nested, 3=ha, 4=custom - uint8_t mqtt_qos; - - String hostname; - String jwtSecret; - String ssid; - String password; + uint8_t tx_mode = 1; + uint8_t ems_bus_id = 0x0B; + bool system_heartbeat = false; + int8_t syslog_level = 1; // uuid::log::Level + uint32_t syslog_mark_interval = 0; + String syslog_host = "192.168.1.4"; + uint8_t master_thermostat = 0; + bool shower_timer = false; + bool shower_alert = false; + uint16_t publish_time = 10; // seconds + uint8_t mqtt_format = 1; // 1=single, 2=nested, 3=ha, 4=custom + uint8_t mqtt_qos = 0; + String hostname = "ems-esp"; + String jwtSecret = "ems-esp"; + String ssid = "ems-esp"; + String password = "ems-esp"; static void read(DummySettings & settings, JsonObject & root){}; static void read(DummySettings & settings){}; @@ -56,13 +55,14 @@ class DummySettingsService : public StatefulService { class ESP8266React { public: ESP8266React(AsyncWebServer * server, FS * fs) - : _settings(server, fs, nullptr){}; + : _settings(server, fs, nullptr) + , _securitySettingsService(server, fs){}; void begin(){}; void loop(){}; SecurityManager * getSecurityManager() { - return nullptr; + return &_securitySettingsService; } AsyncMqttClient * getMqttClient() { @@ -82,8 +82,10 @@ class ESP8266React { } private: - DummySettingsService _settings; - AsyncMqttClient * _mqttClient; + DummySettingsService _settings; + SecuritySettingsService _securitySettingsService; + + AsyncMqttClient * _mqttClient; }; class EMSESPSettingsService { diff --git a/lib_standalone/ESPAsyncWebServer.h b/lib_standalone/ESPAsyncWebServer.h index 5a0ce867b..35a848485 100644 --- a/lib_standalone/ESPAsyncWebServer.h +++ b/lib_standalone/ESPAsyncWebServer.h @@ -7,22 +7,11 @@ #include #include -#define DEBUGF(...) //Serial.printf(__VA_ARGS__) - class AsyncWebServer; class AsyncWebServerRequest; class AsyncWebServerResponse; -class AsyncWebHeader; -class AsyncWebParameter; -class AsyncWebRewrite; -class AsyncWebHandler; -class AsyncStaticWebHandler; -class AsyncCallbackWebHandler; -class AsyncResponseStream; class AsyncJsonResponse; - - typedef enum { HTTP_GET = 0b00000001, HTTP_POST = 0b00000010, @@ -34,151 +23,17 @@ typedef enum { HTTP_ANY = 0b01111111, } WebRequestMethod; -//if this value is returned when asked for data, packet will not be sent and you will be asked for data again -#define RESPONSE_TRY_AGAIN 0xFFFFFFFF - typedef uint8_t WebRequestMethodComposite; typedef std::function ArDisconnectHandler; -/* - * PARAMETER :: Chainable object to hold GET/POST and FILE parameters - * */ - -class AsyncWebParameter { - private: - String _name; - String _value; - size_t _size; - bool _isForm; - bool _isFile; - - public: - AsyncWebParameter(const String & name, const String & value, bool form = false, bool file = false, size_t size = 0) - : _name(name) - , _value(value) - , _size(size) - , _isForm(form) - , _isFile(file) { - } - const String & name() const { - return _name; - } - const String & value() const { - return _value; - } - size_t size() const { - return _size; - } - bool isPost() const { - return _isForm; - } - bool isFile() const { - return _isFile; - } -}; - -/* - * HEADER :: Chainable object to hold the headers - * */ - -class AsyncWebHeader { - private: - String _name; - String _value; - - public: - AsyncWebHeader(const String & name, const String & value) - : _name(name) - , _value(value) { - } - AsyncWebHeader(const String & data) - : _name() - , _value() { - } - ~AsyncWebHeader() { - } - const String & name() const { - return _name; - } - const String & value() const { - return _value; - } - String toString() const { - return _value; - } -}; - -/* - * REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect - * */ - -typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType; - -typedef std::function AwsResponseFiller; -typedef std::function AwsTemplateProcessor; - class AsyncWebServerRequest { friend class AsyncWebServer; friend class AsyncCallbackWebHandler; private: - AsyncClient * _client; - AsyncWebServer * _server; - AsyncWebHandler * _handler; - AsyncWebServerResponse * _response; - ArDisconnectHandler _onDisconnectfn; - - String _temp; - uint8_t _parseState; - - uint8_t _version; + AsyncClient * _client; + AsyncWebServer * _server; WebRequestMethodComposite _method; - String _url; - String _host; - String _contentType; - String _boundary; - String _authorization; - RequestedConnectionType _reqconntype; - void _removeNotInterestingHeaders(); - bool _isDigest; - bool _isMultipart; - bool _isPlainPost; - bool _expectingContinue; - size_t _contentLength; - size_t _parsedLength; - - uint8_t _multiParseState; - uint8_t _boundaryPosition; - size_t _itemStartIndex; - size_t _itemSize; - String _itemName; - String _itemFilename; - String _itemType; - String _itemValue; - uint8_t * _itemBuffer; - size_t _itemBufferIndex; - bool _itemIsFile; - - void _onPoll(); - void _onAck(size_t len, uint32_t time); - void _onError(int8_t error); - void _onTimeout(uint32_t time); - void _onDisconnect(){}; - void _onData(void * buf, size_t len); - - void _addParam(AsyncWebParameter *); - void _addPathParam(const char * param); - - bool _parseReqHead(); - bool _parseReqHeader(); - void _parseLine(); - void _parsePlainPostChar(uint8_t data); - void _parseMultipartPostByte(uint8_t data, bool last); - void _addGetParams(const String & params); - - void _handleUploadStart(); - void _handleUploadByte(uint8_t data, bool last); - void _handleUploadEnd(); public: void * _tempObject; @@ -189,157 +44,30 @@ class AsyncWebServerRequest { AsyncClient * client() { return _client; } - uint8_t version() const { - return _version; - } + WebRequestMethodComposite method() const { return _method; } - const String & url() const { - return _url; - } - const String & host() const { - return _host; - } - const String & contentType() const { - return _contentType; - } - size_t contentLength() const { - return _contentLength; - } - bool multipart() const { - return _isMultipart; - } - const char * methodToString() const; - const char * requestedConnTypeToString() const; - RequestedConnectionType requestedConnType() const { - return _reqconntype; - } - bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED); - void onDisconnect(ArDisconnectHandler fn){}; - //hash is the string representation of: - // base64(user:pass) for basic or - // user:realm:md5(user:realm:pass) for digest - bool authenticate(const char * hash); - bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false); - void requestAuthentication(const char * realm = NULL, bool isDigest = true); - - void setHandler(AsyncWebHandler * handler) { - _handler = handler; - } - void addInterestingHeader(const String & name); - - void redirect(const String & url); + void addInterestingHeader(const String & name){}; void send(AsyncWebServerResponse * response){}; void send(AsyncJsonResponse * response){}; void send(int code, const String & contentType = String(), const String & content = String()){}; - void send(Stream & stream, const String & contentType, size_t len, AwsTemplateProcessor callback = nullptr); - void send(const String & contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); - void sendChunked(const String & contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); - void send_P(int code, const String & contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback = nullptr); - void send_P(int code, const String & contentType, PGM_P content, AwsTemplateProcessor callback = nullptr); + AsyncWebServerResponse * beginResponse(int code, const String & contentType = String(), const String & content = String()) { + // AsyncWebServerResponse *a = new AsyncWebServerResponse() + return nullptr; + } - AsyncWebServerResponse * beginResponse(int code, const String & contentType = String(), const String & content = String()); - AsyncWebServerResponse * beginResponse(Stream & stream, const String & contentType, size_t len, AwsTemplateProcessor callback = nullptr); - AsyncWebServerResponse * beginResponse(const String & contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); - AsyncWebServerResponse * beginChunkedResponse(const String & contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); - AsyncResponseStream * beginResponseStream(const String & contentType, size_t bufferSize = 1460); - AsyncWebServerResponse * beginResponse_P(int code, const String & contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback = nullptr); - AsyncWebServerResponse * beginResponse_P(int code, const String & contentType, PGM_P content, AwsTemplateProcessor callback = nullptr); - - size_t headers() const; // get header count - bool hasHeader(const String & name) const; // check if header exists - bool hasHeader(const __FlashStringHelper * data) const; // check if header exists - - AsyncWebHeader * getHeader(const String & name) const; - AsyncWebHeader * getHeader(const __FlashStringHelper * data) const; - AsyncWebHeader * getHeader(size_t num) const; - - size_t params() const; // get arguments count - bool hasParam(const String & name, bool post = false, bool file = false) const; - bool hasParam(const __FlashStringHelper * data, bool post = false, bool file = false) const; - - AsyncWebParameter * getParam(const String & name, bool post = false, bool file = false) const; - AsyncWebParameter * getParam(const __FlashStringHelper * data, bool post, bool file) const; - AsyncWebParameter * getParam(size_t num) const; - - size_t args() const { - return params(); - } // get arguments count - const String & arg(const String & name) const; // get request argument value by name - const String & arg(const __FlashStringHelper * data) const; // get request argument value by F(name) - const String & arg(size_t i) const; // get request argument value by number - const String & argName(size_t i) const; // get request argument name by number - bool hasArg(const char * name) const; // check if argument exists - bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists - - const String & pathArg(size_t i) const; - - const String & header(const char * name) const; // get request header value by name - const String & header(const __FlashStringHelper * data) const; // get request header value by F(name) - const String & header(size_t i) const; // get request header value by number - const String & headerName(size_t i) const; // get request header name by number - String urlDecode(const String & text) const; + size_t headers() const; // get header count + size_t params() const; // get arguments count }; -/* - * FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server) - * */ - typedef std::function ArRequestFilterFunction; -bool ON_STA_FILTER(AsyncWebServerRequest * request); - -bool ON_AP_FILTER(AsyncWebServerRequest * request); - -/* - * REWRITE :: One instance can be handle any Request (done by the Server) - * */ - -class AsyncWebRewrite { - protected: - String _from; - String _toUrl; - String _params; - ArRequestFilterFunction _filter; - - public: - AsyncWebRewrite(const char * from, const char * to) - : _from(from) - , _toUrl(to) - , _params(String()) - , _filter(NULL) { - } - virtual ~AsyncWebRewrite() { - } - AsyncWebRewrite & setFilter(ArRequestFilterFunction fn) { - _filter = fn; - return *this; - } - bool filter(AsyncWebServerRequest * request) const { - return _filter == NULL || _filter(request); - } - const String & from(void) const { - return _from; - } - const String & toUrl(void) const { - return _toUrl; - } - const String & params(void) const { - return _params; - } -}; - -/* - * HANDLER :: One instance can be attached to any Request (done by the Server) - * */ - class AsyncWebHandler { protected: - ArRequestFilterFunction _filter; String _username; String _password; @@ -348,18 +76,7 @@ class AsyncWebHandler { : _username("") , _password("") { } - AsyncWebHandler & setFilter(ArRequestFilterFunction fn) { - _filter = fn; - return *this; - } - AsyncWebHandler & setAuthentication(const char * username, const char * password) { - _username = String(username); - _password = String(password); - return *this; - }; - bool filter(AsyncWebServerRequest * request) { - return _filter == NULL || _filter(request); - } + virtual ~AsyncWebHandler() { } virtual bool canHandle(AsyncWebServerRequest * request __attribute__((unused))) { @@ -380,142 +97,42 @@ class AsyncWebHandler { size_t index __attribute__((unused)), size_t total __attribute__((unused))) { } + virtual bool isRequestHandlerTrivial() { return true; } }; -/* - * RESPONSE :: One instance is created for each Request (attached by the Handler) - * */ - -typedef enum { RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED } WebResponseState; - class AsyncWebServerResponse { - protected: - int _code; - String _contentType; - size_t _contentLength; - bool _sendContentLength; - bool _chunked; - size_t _headLength; - size_t _sentLength; - size_t _ackedLength; - size_t _writtenLength; - WebResponseState _state; - const char * _responseCodeToString(int code); - public: AsyncWebServerResponse(); virtual ~AsyncWebServerResponse(); - virtual void setCode(int code); - virtual void setContentLength(size_t len); - virtual void setContentType(const String & type); - virtual void addHeader(const String & name, const String & value); - virtual String _assembleHead(uint8_t version); - virtual bool _started() const; - virtual bool _finished() const; - virtual bool _failed() const; - virtual bool _sourceValid() const; - virtual void _respond(AsyncWebServerRequest * request); - virtual size_t _ack(AsyncWebServerRequest * request, size_t len, uint32_t time); }; -/* - * SERVER :: One instance - * */ - typedef std::function ArRequestHandlerFunction; typedef std::function ArUploadHandlerFunction; typedef std::function ArBodyHandlerFunction; class AsyncWebServer { protected: - AsyncServer _server; - AsyncCallbackWebHandler * _catchAllHandler; + AsyncServer _server; public: - // proddy AsyncWebServer(uint16_t port) : _server(port){}; - // , _rewrites(LinkedList([](AsyncWebRewrite* r){ delete r; })) - // , _handlers(LinkedList([](AsyncWebHandler* h){ delete h; })) - ~AsyncWebServer(){}; void begin(){}; void end(); -#if ASYNC_TCP_SSL_ENABLED - void onSslFileRequest(AcSSlFileHandler cb, void * arg); - void beginSecure(const char * cert, const char * private_key_file, const char * password); -#endif - - AsyncWebRewrite & addRewrite(AsyncWebRewrite * rewrite); - bool removeRewrite(AsyncWebRewrite * rewrite); - AsyncWebRewrite & rewrite(const char * from, const char * to); - - AsyncWebHandler & addHandler(AsyncWebHandler * handler); - bool removeHandler(AsyncWebHandler * handler); - - /* - - AsyncCallbackWebHandler & on(const char * uri, ArRequestHandlerFunction onRequest) { - AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler(); + AsyncWebHandler & addHandler(AsyncWebHandler * handler) { return *handler; - }; - AsyncCallbackWebHandler & on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest) { - AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler(); - return handler; - }; - AsyncCallbackWebHandler & on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload) { - AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler(); - return *handler; - }; - AsyncCallbackWebHandler & - on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody) { - AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler(); - return *handler; - }; - */ + } void on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){}; - void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned - void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads - void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request) - - void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody - - void _handleDisconnect(AsyncWebServerRequest * request); - void _attachHandler(AsyncWebServerRequest * request); - void _rewriteRequest(AsyncWebServerRequest * request); }; -// class DefaultHeaders { -// headers_t _headers; -// DefaultHeaders() -// public: - -// void addHeader(const String& name, const String& value){ -// _headers.add(new AsyncWebHeader(name, value)); -// } - -// DefaultHeaders(DefaultHeaders const &) = delete; -// DefaultHeaders &operator=(DefaultHeaders const &) = delete; -// static DefaultHeaders &Instance() { -// static DefaultHeaders instance; -// return instance; -// } -// }; - -// #include "WebResponseImpl.h" -// #include "WebHandlerImpl.h" -// #include "AsyncWebSocket.h" -// #include "AsyncEventSource.h" - -typedef std::function ArJsonRequestHandlerFunction; - -#endif /* _AsyncWebServer_H_ */ +#endif diff --git a/lib_standalone/SecuritySettingsService.cpp b/lib_standalone/SecuritySettingsService.cpp new file mode 100644 index 000000000..08ba401d8 --- /dev/null +++ b/lib_standalone/SecuritySettingsService.cpp @@ -0,0 +1,141 @@ +#include + +#if FT_ENABLED(FT_SECURITY) + +SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : + _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this), + _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE), + _jwtHandler(FACTORY_JWT_SECRET) { + addUpdateHandler([&](const String& originId) { configureJWTHandler(); }, false); +} + +void SecuritySettingsService::begin() { + _fsPersistence.readFromFS(); + configureJWTHandler(); +} + +Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) { + AsyncWebHeader* authorizationHeader = request->getHeader(AUTHORIZATION_HEADER); + if (authorizationHeader) { + String value = authorizationHeader->value(); + if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) { + value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN); + return authenticateJWT(value); + } + } else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) { + AsyncWebParameter* tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER); + String value = tokenParamater->value(); + return authenticateJWT(value); + } + return Authentication(); +} + +void SecuritySettingsService::configureJWTHandler() { + _jwtHandler.setSecret(_state.jwtSecret); +} + +Authentication SecuritySettingsService::authenticateJWT(String& jwt) { + DynamicJsonDocument payloadDocument(MAX_JWT_SIZE); + _jwtHandler.parseJWT(jwt, payloadDocument); + if (payloadDocument.is()) { + JsonObject parsedPayload = payloadDocument.as(); + String username = parsedPayload["username"]; + for (User _user : _state.users) { + if (_user.username == username && validatePayload(parsedPayload, &_user)) { + return Authentication(_user); + } + } + } + return Authentication(); +} + +Authentication SecuritySettingsService::authenticate(const String& username, const String& password) { + for (User _user : _state.users) { + if (_user.username == username && _user.password == password) { + return Authentication(_user); + } + } + return Authentication(); +} + +inline void populateJWTPayload(JsonObject& payload, User* user) { + payload["username"] = user->username; + payload["admin"] = user->admin; + payload["version"] = EMSESP_APP_VERSION; // proddy added +} + +boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) { + DynamicJsonDocument jsonDocument(MAX_JWT_SIZE); + JsonObject payload = jsonDocument.to(); + populateJWTPayload(payload, user); + return payload == parsedPayload; +} + +String SecuritySettingsService::generateJWT(User* user) { + DynamicJsonDocument jsonDocument(MAX_JWT_SIZE); + JsonObject payload = jsonDocument.to(); + populateJWTPayload(payload, user); + return _jwtHandler.buildJWT(payload); +} + +ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) { + return [this, predicate](AsyncWebServerRequest* request) { + Authentication authentication = authenticateRequest(request); + return predicate(authentication); + }; +} + +ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, + AuthenticationPredicate predicate) { + return [this, onRequest, predicate](AsyncWebServerRequest* request) { + Authentication authentication = authenticateRequest(request); + if (!predicate(authentication)) { + request->send(401); + return; + } + onRequest(request); + }; +} + +ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, + AuthenticationPredicate predicate) { + return [this, onRequest, predicate](AsyncWebServerRequest* request, JsonVariant& json) { + Authentication authentication = authenticateRequest(request); + if (!predicate(authentication)) { + request->send(401); + return; + } + onRequest(request, json); + }; +} + +#else + +User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true); + +SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : SecurityManager() { +} +SecuritySettingsService::~SecuritySettingsService() { +} + +ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) { + return [this, predicate](AsyncWebServerRequest* request) { return true; }; +} + +// Return the admin user on all request - disabling security features +Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) { + return Authentication(ADMIN_USER); +} + +// Return the function unwrapped +ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, + AuthenticationPredicate predicate) { + return onRequest; +} + +ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, + AuthenticationPredicate predicate) { + return onRequest; +} + +#endif diff --git a/lib_standalone/SecuritySettingsService.h b/lib_standalone/SecuritySettingsService.h new file mode 100644 index 000000000..801e44a3e --- /dev/null +++ b/lib_standalone/SecuritySettingsService.h @@ -0,0 +1,116 @@ +#ifndef SecuritySettingsService_h +#define SecuritySettingsService_h + +#include +#include +#include +#include + +#include "../../src/version.h" // added by proddy + +#ifndef FACTORY_ADMIN_USERNAME +#define FACTORY_ADMIN_USERNAME "admin" +#endif + +#ifndef FACTORY_ADMIN_PASSWORD +#define FACTORY_ADMIN_PASSWORD "admin" +#endif + +#ifndef FACTORY_GUEST_USERNAME +#define FACTORY_GUEST_USERNAME "guest" +#endif + +#ifndef FACTORY_GUEST_PASSWORD +#define FACTORY_GUEST_PASSWORD "guest" +#endif + +#define SECURITY_SETTINGS_FILE "/config/securitySettings.json" +#define SECURITY_SETTINGS_PATH "/rest/securitySettings" + +#if FT_ENABLED(FT_SECURITY) + +class SecuritySettings { + public: + String jwtSecret; + std::list users; + + static void read(SecuritySettings& settings, JsonObject& root) { + // secret + root["jwt_secret"] = settings.jwtSecret; + + // users + JsonArray users = root.createNestedArray("users"); + for (User user : settings.users) { + JsonObject userRoot = users.createNestedObject(); + userRoot["username"] = user.username; + userRoot["password"] = user.password; + userRoot["admin"] = user.admin; + } + } + + static StateUpdateResult update(JsonObject& root, SecuritySettings& settings) { + // secret + settings.jwtSecret = root["jwt_secret"] | FACTORY_JWT_SECRET; + + // users + settings.users.clear(); + if (root["users"].is()) { + for (JsonVariant user : root["users"].as()) { + settings.users.push_back(User(user["username"], user["password"], user["admin"])); + } + } else { + settings.users.push_back(User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true)); + settings.users.push_back(User(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false)); + } + return StateUpdateResult::CHANGED; + } +}; + +class SecuritySettingsService : public StatefulService, public SecurityManager { + public: + SecuritySettingsService(AsyncWebServer* server, FS* fs); + + void begin(); + + // Functions to implement SecurityManager + Authentication authenticate(const String& username, const String& password); + Authentication authenticateRequest(AsyncWebServerRequest* request); + String generateJWT(User* user); + ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); + ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); + ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate); + + private: + HttpEndpoint _httpEndpoint; + FSPersistence _fsPersistence; + ArduinoJsonJWT _jwtHandler; + + void configureJWTHandler(); + + /* + * Lookup the user by JWT + */ + Authentication authenticateJWT(String& jwt); + + /* + * Verify the payload is correct + */ + boolean validatePayload(JsonObject& parsedPayload, User* user); +}; + +#else + +class SecuritySettingsService : public SecurityManager { + public: + SecuritySettingsService(AsyncWebServer* server, FS* fs); + ~SecuritySettingsService(); + + // minimal set of functions to support framework with security settings disabled + Authentication authenticateRequest(AsyncWebServerRequest* request); + ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); + ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); + ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate); +}; + +#endif // end FT_ENABLED(FT_SECURITY) +#endif // end SecuritySettingsService_h diff --git a/lib_standalone/WString.cpp b/lib_standalone/WString.cpp index 5fd02b086..ef3e571cc 100644 --- a/lib_standalone/WString.cpp +++ b/lib_standalone/WString.cpp @@ -1,863 +1,68 @@ -/* - WString.cpp - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ +#include #include "WString.h" -/*********************************************/ -/* Constructors */ -/*********************************************/ +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + * + * https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c + */ +size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) { + const char * osrc = src; + size_t nleft = dsize; -char * itoa(signed short value, char * result, const unsigned int base) { - // check that the base if valid - if (base < 2 || base > 36) { - *result = '\0'; - return result; - } - - char * ptr = result, *ptr1 = result, tmp_char; - signed short tmp_value; - - do { - tmp_value = value; - value /= base; - *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)]; - } while (value); - - // Apply negative sign - if (tmp_value < 0) { - *ptr++ = '-'; - } - - *ptr-- = '\0'; - while (ptr1 < ptr) { - tmp_char = *ptr; - *ptr-- = *ptr1; - *ptr1++ = tmp_char; - } - - return result; -} - -char* ltoa(long value, char* result, int base) { - return itoa((int)value, result, base); -} - -char* ultoa(unsigned long value, char* result, int base) { - return itoa((unsigned int)value, result, base); -} - -char * dtostrf(double number, signed char width, unsigned char prec, char *s) { - bool negative = false; - - char* out = s; - - int fillme = width; // how many cells to fill for the integer part - if (prec > 0) { - fillme -= (prec+1); - } - - // Handle negative numbers - if (number < 0.0) { - negative = true; - fillme--; - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - // I optimized out most of the divisions - double rounding = 2.0; - for (unsigned int i = 0; i < prec; ++i) - rounding *= 10.0; - rounding = 1.0 / rounding; - - number += rounding; - - // Figure out how big our number really is - double tenpow = 1.0; - int digitcount = 1; - double nextpow; - while (number >= (nextpow = (10.0 * tenpow))) { - tenpow = nextpow; - digitcount++; - } - - // minimal compensation for possible lack of precision (#7087 addition) - // number *= 1 + std::numeric_limits::epsilon(); - - number /= tenpow; - fillme -= digitcount; - - // Pad unused cells with spaces - while (fillme-- > 0) { - *out++ = ' '; - } - - // Handle negative sign - if (negative) *out++ = '-'; - - // Print the digits, and if necessary, the decimal point - digitcount += prec; - int8_t digit = 0; - while (digitcount-- > 0) { - digit = (int8_t)number; - if (digit > 9) digit = 9; // insurance - *out++ = (char)('0' | digit); - if ((digitcount == prec) && (prec > 0)) { - *out++ = '.'; + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; } - number -= digit; - number *= 10.0; } - // make sure the string is terminated - *out = 0; - return s; -} + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } -String::String(const char *cstr) -{ - init(); - if (cstr) copy(cstr, strlen(cstr)); -} - -String::String(const String &value) -{ - init(); - *this = value; -} - -String::String(const __FlashStringHelper *pstr) -{ - init(); - *this = pstr; -} - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -String::String(String &&rval) -{ - init(); - move(rval); -} -String::String(StringSumHelper &&rval) -{ - init(); - move(rval); -} -#endif - -String::String(char c) -{ - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; -} - -String::String(unsigned char value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned char)]; - itoa(value, buf, base); - *this = buf; -} - -String::String(int value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(int)]; - itoa(value, buf, base); - *this = buf; -} - -String::String(unsigned int value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned int)]; - itoa(value, buf, base); - *this = buf; -} - -String::String(long value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(long)]; - ltoa(value, buf, base); - *this = buf; -} - -String::String(unsigned long value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned long)]; - ultoa(value, buf, base); - *this = buf; -} - -String::String(float value, unsigned char decimalPlaces) -{ - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::String(double value, unsigned char decimalPlaces) -{ - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::~String() -{ - free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 0; -} - -void String::invalidate(void) -{ - if (buffer) free(buffer); - buffer = NULL; - capacity = len = 0; -} - -unsigned char String::reserve(unsigned int size) -{ - if (buffer && capacity >= size) return 1; - if (changeBuffer(size)) { - if (len == 0) buffer[0] = 0; - return 1; - } - return 0; -} - -unsigned char String::changeBuffer(unsigned int maxStrLen) -{ - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); - if (newbuffer) { - buffer = newbuffer; - capacity = maxStrLen; - return 1; - } - return 0; -} - -/*********************************************/ -/* Copy and Move */ -/*********************************************/ - -String & String::copy(const char *cstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; + return (src - osrc - 1); /* count does not include NUL */ } /* -String & String::copy(const char *pstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy_P(buffer, pstr); - return *this; + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + * + * https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcat.c + */ +size_t strlcat(char * dst, const char * src, size_t siz) { + char * d = dst; + const char * s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return (dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return (dlen + (s - src)); /* count does not include NUL */ } -*/ - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -void String::move(String &rhs) -{ - if (buffer) { - if (rhs && capacity >= rhs.len) { - strcpy(buffer, rhs.buffer); - len = rhs.len; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; -} -#endif - -String & String::operator = (const String &rhs) -{ - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; -} - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -String & String::operator = (String &&rval) -{ - if (this != &rval) move(rval); - return *this; -} - -String & String::operator = (StringSumHelper &&rval) -{ - if (this != &rval) move(rval); - return *this; -} -#endif - -String & String::operator = (const char *cstr) -{ - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; -} - -String & String::operator = (const __FlashStringHelper *pstr) -{ - // if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - // else invalidate(); - - return *this; -} - -/*********************************************/ -/* concat */ -/*********************************************/ - -unsigned char String::concat(const String &s) -{ - return concat(s.buffer, s.len); -} - -unsigned char String::concat(const char *cstr, unsigned int length) -{ - unsigned int newlen = len + length; - if (!cstr) return 0; - if (length == 0) return 1; - if (!reserve(newlen)) return 0; - strcpy(buffer + len, cstr); - len = newlen; - return 1; -} - -unsigned char String::concat(const char *cstr) -{ - if (!cstr) return 0; - return concat(cstr, strlen(cstr)); -} - -unsigned char String::concat(char c) -{ - char buf[2]; - buf[0] = c; - buf[1] = 0; - return concat(buf, 1); -} - -unsigned char String::concat(unsigned char num) -{ - char buf[1 + 3 * sizeof(unsigned char)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(int num) -{ - char buf[2 + 3 * sizeof(int)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned int num) -{ - char buf[1 + 3 * sizeof(unsigned int)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(long num) -{ - char buf[2 + 3 * sizeof(long)]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned long num) -{ - char buf[1 + 3 * sizeof(unsigned long)]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(float num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); -} - -unsigned char String::concat(double num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); -} - -unsigned char String::concat(const __FlashStringHelper * str) -{ - if (!str) return 0; - int length = strlen_P((const char *) str); - if (length == 0) return 1; - unsigned int newlen = len + length; - if (!reserve(newlen)) return 0; - strcpy_P(buffer + len, (const char *) str); - len = newlen; - return 1; -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, float num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, double num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) a.invalidate(); - return a; -} - -/*********************************************/ -/* Comparison */ -/*********************************************/ - -int String::compareTo(const String &s) const -{ - if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, s.buffer); -} - -unsigned char String::isEmpty() const { - return (len == 0); -} - -unsigned char String::equals(const String &s2) const -{ - return (len == s2.len && compareTo(s2) == 0); -} - -unsigned char String::equals(const char *cstr) const -{ - if (len == 0) return (cstr == NULL || *cstr == 0); - if (cstr == NULL) return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; -} - -unsigned char String::operator<(const String &rhs) const -{ - return compareTo(rhs) < 0; -} - -unsigned char String::operator>(const String &rhs) const -{ - return compareTo(rhs) > 0; -} - -unsigned char String::operator<=(const String &rhs) const -{ - return compareTo(rhs) <= 0; -} - -unsigned char String::operator>=(const String &rhs) const -{ - return compareTo(rhs) >= 0; -} - -unsigned char String::equalsIgnoreCase( const String &s2 ) const -{ - if (this == &s2) return 1; - if (len != s2.len) return 0; - if (len == 0) return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while (*p1) { - if (tolower(*p1++) != tolower(*p2++)) return 0; - } - return 1; -} - -unsigned char String::startsWith( const String &s2 ) const -{ - if (len < s2.len) return 0; - return startsWith(s2, 0); -} - -unsigned char String::startsWith( const String &s2, unsigned int offset ) const -{ - if (offset > len - s2.len || !buffer || !s2.buffer) return 0; - return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; -} - -unsigned char String::endsWith( const String &s2 ) const -{ - if ( len < s2.len || !buffer || !s2.buffer) return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; -} - -/*********************************************/ -/* Character Access */ -/*********************************************/ - -char String::charAt(unsigned int loc) const -{ - return operator[](loc); -} - -void String::setCharAt(unsigned int loc, char c) -{ - if (loc < len) buffer[loc] = c; -} - -char & String::operator[](unsigned int index) -{ - static char dummy_writable_char; - if (index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; -} - -char String::operator[]( unsigned int index ) const -{ - if (index >= len || !buffer) return 0; - return buffer[index]; -} - -void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const -{ - if (!bufsize || !buf) return; - if (index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); - buf[n] = 0; -} - -/*********************************************/ -/* Search */ -/*********************************************/ - -int String::indexOf(char c) const -{ - return indexOf(c, 0); -} - -int String::indexOf( char ch, unsigned int fromIndex ) const -{ - if (fromIndex >= len) return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::indexOf(const String &s2) const -{ - return indexOf(s2, 0); -} - -int String::indexOf(const String &s2, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if (found == NULL) return -1; - return found - buffer; -} - -int String::lastIndexOf( char theChar ) const -{ - return lastIndexOf(theChar, len - 1); -} - -int String::lastIndexOf(char ch, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( buffer, ch ); - buffer[fromIndex + 1] = tempchar; - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::lastIndexOf(const String &s2) const -{ - return lastIndexOf(s2, len - s2.len); -} - -int String::lastIndexOf(const String &s2, unsigned int fromIndex) const -{ - if (s2.len == 0 || len == 0 || s2.len > len) return -1; - if (fromIndex >= len) fromIndex = len - 1; - int found = -1; - for (char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; - } - return found; -} - -String String::substring(unsigned int left, unsigned int right) const -{ - if (left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if (left >= len) return out; - if (right > len) right = len; - char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; - out = buffer + left; // pointer arithmetic - buffer[right] = temp; //restore character - return out; -} - -/*********************************************/ -/* Modification */ -/*********************************************/ - -void String::replace(char find, char replace) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - if (*p == find) *p = replace; - } -} - -void String::replace(const String& find, const String& replace) -{ - if (len == 0 || find.len == 0) return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if (diff == 0) { - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if (diff < 0) { - char *writeTo = buffer; - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - unsigned int n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); - writeTo += n; - memcpy(writeTo, replace.buffer, replace.len); - writeTo += replace.len; - readFrom = foundAt + find.len; - len += diff; - } - strcpy(writeTo, readFrom); - } else { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if (size == len) return; - if (size > capacity && !changeBuffer(size)) return; - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } -} - -void String::remove(unsigned int index){ - // Pass the biggest integer as the count. The remove method - // below will take care of truncating it at the end of the - // string. - remove(index, (unsigned int)-1); -} - -void String::remove(unsigned int index, unsigned int count){ - if (index >= len) { return; } - if (count <= 0) { return; } - if (count > len - index) { count = len - index; } - char *writeTo = buffer + index; - len = len - count; - strncpy(writeTo, buffer + index + count,len - index); - buffer[len] = 0; -} - -void String::toLowerCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = tolower(*p); - } -} - -void String::toUpperCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = toupper(*p); - } -} - -void String::trim(void) -{ - if (!buffer || len == 0) return; - char *begin = buffer; - while (isspace(*begin)) begin++; - char *end = buffer + len - 1; - while (isspace(*end) && end >= begin) end--; - len = end + 1 - begin; - if (begin > buffer) memcpy(buffer, begin, len); - buffer[len] = 0; -} - -/*********************************************/ -/* Parsing / Conversion */ -/*********************************************/ - -long String::toInt(void) const -{ - if (buffer) return atol(buffer); - return 0; -} - -float String::toFloat(void) const -{ - return float(toDouble()); -} - -double String::toDouble(void) const -{ - if (buffer) return atof(buffer); - return 0; -} \ No newline at end of file diff --git a/lib_standalone/WString.h b/lib_standalone/WString.h index 1a7c9d223..c7b481bf2 100644 --- a/lib_standalone/WString.h +++ b/lib_standalone/WString.h @@ -1,236 +1,69 @@ -/* - WString.h - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. +#ifndef WSTRING_H +#define WSTRING_H - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. +#include - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ +// Reproduces Arduino's String class +class String { + public: + String & operator+=(const char * rhs) { + _str += rhs; + return *this; + } -#ifndef String_class_h -#define String_class_h + size_t length() const { + return _str.size(); + } + + String(const char * str = "") + : _str(str) { + } + + const char * c_str() const { + return _str.c_str(); + } + + bool operator==(const char * s) const { + return _str == s; + } + + friend std::ostream & operator<<(std::ostream & lhs, const ::String & rhs) { + lhs << rhs._str; + return lhs; + } + + /// + bool isEmpty() { + return _str.empty(); + } + + // long toInt() const { + // return std::stol(_str); + // } + + bool equals(const char * s) { + return _str == s; + } + + + private: + std::string _str; +}; + +class StringSumHelper; + +inline bool operator==(const std::string & lhs, const ::String & rhs) { + return lhs == rhs.c_str(); +} + + +size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize); +size_t strlcat(char * dst, const char * src, size_t siz); #define strlen_P strlen #define strncpy_P strncpy #define strcmp_P strcmp #define strcpy_P strcpy -// #include "pgmspace.h" -// #include "noniso.h" - -#include -#include -#include - -// When compiling programs with this class, the following gcc parameters -// dramatically increase performance and memory (RAM) efficiency, typically -// with little or no increase in code size. -// -felide-constructors -// -std=c++0x - -class __FlashStringHelper; -// #define F(string_literal) (reinterpret_cast(PSTR(string_literal))) - -// An inherited class for holding the result of a concatenation. These -// result objects are assumed to be writable by subsequent concatenations. -class StringSumHelper; - -// The string class -class String -{ - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const {} - -public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const String &str); - String(const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String(String &&rval); - String(StringSumHelper &&rval); - #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base=10); - explicit String(int, unsigned char base=10); - explicit String(unsigned int, unsigned char base=10); - explicit String(long, unsigned char base=10); - explicit String(unsigned long, unsigned char base=10); - explicit String(float, unsigned char decimalPlaces=2); - explicit String(double, unsigned char decimalPlaces=2); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const {return len;} - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator = (const String &rhs); - String & operator = (const char *cstr); - String & operator = (const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String & operator = (String &&rval); - String & operator = (StringSumHelper &&rval); - #endif - - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(char c); - unsigned char concat(unsigned char c); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - unsigned char concat(float num); - unsigned char concat(double num); - unsigned char concat(const __FlashStringHelper * str); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator += (const String &rhs) {concat(rhs); return (*this);} - String & operator += (const char *cstr) {concat(cstr); return (*this);} - String & operator += (char c) {concat(c); return (*this);} - String & operator += (unsigned char num) {concat(num); return (*this);} - String & operator += (int num) {concat(num); return (*this);} - String & operator += (unsigned int num) {concat(num); return (*this);} - String & operator += (long num) {concat(num); return (*this);} - String & operator += (unsigned long num) {concat(num); return (*this);} - String & operator += (float num) {concat(num); return (*this);} - String & operator += (double num) {concat(num); return (*this);} - String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} - - friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } - int compareTo(const String &s) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - unsigned char operator == (const String &rhs) const {return equals(rhs);} - unsigned char operator == (const char *cstr) const {return equals(cstr);} - unsigned char operator != (const String &rhs) const {return !equals(rhs);} - unsigned char operator != (const char *cstr) const {return !equals(cstr);} - unsigned char operator < (const String &rhs) const; - unsigned char operator > (const String &rhs) const; - unsigned char operator <= (const String &rhs) const; - unsigned char operator >= (const String &rhs) const; - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char startsWith( const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [] (unsigned int index) const; - char& operator [] (unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const - { getBytes((unsigned char *)buf, bufsize, index); } - const char* c_str() const { return buffer; } - char* begin() { return buffer; } - char* end() { return buffer + length(); } - const char* begin() const { return c_str(); } - const char* end() const { return c_str() + length(); } - - // search - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void remove(unsigned int index); - void remove(unsigned int index, unsigned int count); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - float toFloat(void) const; - double toDouble(void) const; - - unsigned char isEmpty() const; - -protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') -protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - unsigned char concat(const char *cstr, unsigned int length); - - // copy and move - String & copy(const char *cstr, unsigned int length); - String & copy(const __FlashStringHelper *pstr, unsigned int length); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - void move(String &rhs); - #endif -}; - -class StringSumHelper : public String -{ -public: - StringSumHelper(const String &s) : String(s) {} - StringSumHelper(const char *p) : String(p) {} - StringSumHelper(char c) : String(c) {} - StringSumHelper(unsigned char num) : String(num) {} - StringSumHelper(int num) : String(num) {} - StringSumHelper(unsigned int num) : String(num) {} - StringSumHelper(long num) : String(num) {} - StringSumHelper(unsigned long num) : String(num) {} - StringSumHelper(float num) : String(num) {} - StringSumHelper(double num) : String(num) {} -}; - -#endif // String_class_h \ No newline at end of file +#endif diff --git a/src/EMSESPDevicesService.cpp b/src/EMSESPDevicesService.cpp index 8b77d3b94..46d33293f 100644 --- a/src/EMSESPDevicesService.cpp +++ b/src/EMSESPDevicesService.cpp @@ -70,7 +70,9 @@ void EMSESPDevicesService::device_data(AsyncWebServerRequest * request, JsonVari uint8_t id = json["id"]; // get id from selected table row AsyncJsonResponse * response = new AsyncJsonResponse(false, 1024); +#ifndef EMSESP_STANDALONE EMSESP::device_info(id, (JsonObject &)response->getRoot()); +#endif response->setLength(); request->send(response); } else { diff --git a/src/system.cpp b/src/system.cpp index c842f7c22..9c0b1a392 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -197,7 +197,6 @@ void System::syslog_init() { syslog_mark_interval_ = settings.syslog_mark_interval; syslog_host_ = settings.syslog_host; }); - EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & wifiSettings) { syslog_.hostname(wifiSettings.hostname.c_str()); }); #ifndef EMSESP_STANDALONE syslog_.start(); // syslog service re-start @@ -210,6 +209,7 @@ void System::syslog_init() { syslog_.log_level((uuid::log::Level)syslog_level_); syslog_.mark_interval(syslog_mark_interval_); syslog_.destination(addr); + EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & wifiSettings) { syslog_.hostname(wifiSettings.hostname.c_str()); }); #endif } @@ -249,7 +249,11 @@ void System::start() { // returns true if OTA is uploading bool System::upload_status() { +#if defined(EMSESP_STANDALONE) + return false; +#elif return upload_status_ || Update.isRunning(); +#endif } void System::upload_status(bool in_progress) { @@ -380,11 +384,13 @@ int8_t System::wifi_quality() { void System::show_users(uuid::console::Shell & shell) { shell.printfln(F("Users:")); +#ifndef EMSESP_STANDALONE EMSESP::esp8266React.getSecuritySettingsService()->read([&](SecuritySettings & securitySettings) { for (User user : securitySettings.users) { shell.printfln(F(" username: %s, password: %s, is_admin: %s"), user.username.c_str(), user.password.c_str(), user.admin ? F("yes") : F("no")); } }); +#endif shell.println(); } diff --git a/src/test/test.cpp b/src/test/test.cpp index f8f77ac74..440245cad 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#if defined(EMSESP_STANADLONE) +#if defined(EMSESP_STANDALONE) #include "test.h"