Skip to content

Commit 2207ee6

Browse files
author
QuickSander
committed
feature: fix build error of basic authorization.
1 parent e7eb739 commit 2207ee6

File tree

6 files changed

+85
-56
lines changed

6 files changed

+85
-56
lines changed

platformio.ini

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,28 @@
1-
# Created by Sander van Woensel on 29-01-16.
2-
# Copyright (c) 2016 Sander van Woensel. All rights reserved.
3-
#
4-
# Project Configuration File
5-
#
6-
# A detailed documentation with the EXAMPLES is located here:
7-
# http://docs.platformio.org/en/latest/projectconf.html
8-
#
1+
; PlatformIO Project Configuration File
2+
;
3+
; Build options: build flags, source filter
4+
; Upload options: custom upload port, speed and extra flags
5+
; Library options: dependencies, extra library storages
6+
; Advanced options: extra scripting
7+
;
8+
; Please visit documentation for the other options and examples
9+
; https://docs.platformio.org/page/projectconf.html
910

1011
[platformio]
11-
# Since we desire to integrate with Arduino (and the way it likes its directory
12-
# structure), point source directory to the directory containing an example with
13-
# loop() and setup() and the lib directory to the directory Arduino stores its
14-
# libraries in. This way, PlatformIO will find this very library via the Arduino
15-
# library directory.
1612
src_dir = examples/HelloHttp
1713
lib_dir = ../
1814

1915
[env:esp01]
2016
platform = espressif8266
2117
framework = arduino
2218
board = esp01
23-
# Custom upload tool to force use of esptool.py instead of default esptool.
24-
# See: http://arduino.stackexchange.com/questions/20219/upload-with-esptool-fails-with-espcomm-send-command-cant-receive-slip-payload
2519
extra_scripts = ../../Tools/platformio_esptool.py
20+
lib_deps = agdl/Base64@^1.0.0
2621

2722
[env:uno]
2823
platform = atmelavr
2924
framework = arduino
3025
board = uno
31-
lib_deps = WiFi
32-
33-
# TODO Work in progress
34-
#[env:native]
35-
#platform = native
36-
# Relative to src_dir ("examples/")
37-
#src_filter = +<../../test/*>
26+
lib_deps =
27+
WiFi
28+
agdl/Base64@^1.0.0

src/internals/FixString.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class FixString
4141
// Assignment
4242
FixString<MAX_SIZE>& operator=(const char* pCStr);
4343
FixString<MAX_SIZE>& operator=(const __FlashStringHelper * str);
44+
FixString<MAX_SIZE>& operator=(const String& arduinostr);
4445
template<size_t RHS_SIZE> FixString<MAX_SIZE>& operator=(const FixString<RHS_SIZE>& fixStr);
4546
// We need this since move constructor implicitely declares assignment operators private.
4647
FixString<MAX_SIZE>& operator=(const FixString<MAX_SIZE>& fixStr) = default;
@@ -161,6 +162,15 @@ ArduinoHttpServer::FixString<MAX_SIZE>& ArduinoHttpServer::FixString<MAX_SIZE>::
161162
return (*this = FixString<MAX_SIZE>(pFlashStr));
162163
}
163164

165+
//------------------------------------------------------------------------------
166+
//! \brief Assignment operator for Arduino Strings.
167+
template <size_t MAX_SIZE>
168+
ArduinoHttpServer::FixString<MAX_SIZE>& ArduinoHttpServer::FixString<MAX_SIZE>::operator=(const String& arduinostr)
169+
{
170+
return (*this = FixString<MAX_SIZE>(arduinostr));
171+
}
172+
173+
164174
//------------------------------------------------------------------------------
165175
//! \brief Assignment operator
166176
template <size_t MAX_SIZE>

src/internals/HttpField.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "ArduinoHttpServerDebug.h"
1212

1313
const char* ArduinoHttpServer::HttpField::SEPERATOR = ": ";
14+
const char* ArduinoHttpServer::HttpField::SUB_VALUE_SEPERATOR = " ";
1415
const char* ArduinoHttpServer::HttpField::CONTENT_TYPE_STR = "Content-Type";
1516
const char* ArduinoHttpServer::HttpField::CONTENT_LENGTH_TYPE_STR = "Content-Length";
1617
const char* ArduinoHttpServer::HttpField::USER_AGENT_TYPE_STR = "User-Agent";
@@ -78,3 +79,32 @@ const ArduinoHttpServer::HttpField::Type ArduinoHttpServer::HttpField::getType()
7879
{
7980
return m_type;
8081
}
82+
83+
//! \brief Retrieve part of a value indicated by a zero based index.
84+
//! \details Retrieve "username:password" from "Basic username:password": call with subValueIndex 1.
85+
const ArduinoHttpServer::HttpField::SubValueString ArduinoHttpServer::HttpField::getSubValueString(size_t subValueIndex) const
86+
{
87+
SubValueString subValue;
88+
auto startIndex(0);
89+
auto endIndex(0);
90+
91+
for(auto currentSubValueIndex=0U; currentSubValueIndex < subValueIndex; currentSubValueIndex++)
92+
{
93+
endIndex = m_value.indexOf(SUB_VALUE_SEPERATOR, startIndex);
94+
95+
// If separator has been found.
96+
if(endIndex >=0)
97+
{
98+
subValue = m_value.substring(startIndex + strlen(SUB_VALUE_SEPERATOR), endIndex);
99+
startIndex = endIndex;
100+
}
101+
else
102+
{
103+
subValue = m_value.substring(startIndex);
104+
}
105+
}
106+
107+
108+
return subValue;
109+
}
110+

src/internals/HttpField.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#ifndef __ArduinoHttpServer__HttpField__
1111
#define __ArduinoHttpServer__HttpField__
1212

13+
#include "FixString.hpp"
14+
1315
#include "Arduino.h"
1416

1517
namespace ArduinoHttpServer
@@ -21,6 +23,8 @@ class HttpField
2123

2224
public:
2325

26+
using SubValueString = FixString<128>;
27+
2428
enum class Type: char
2529
{
2630
NOT_SUPPORTED,
@@ -41,12 +45,14 @@ class HttpField
4145
const Type getType() const;
4246

4347
inline const String& getValueAsString() const {return m_value; };
48+
const SubValueString getSubValueString(size_t subValueIndex) const;
4449
inline const int getValueAsInt() const {return m_value.toInt(); };
4550

4651
private:
4752
void determineType(const String& typeStr);
4853

4954
static const char *SEPERATOR;
55+
static const char* SUB_VALUE_SEPERATOR;
5056
static const char* CONTENT_TYPE_STR;
5157
static const char* CONTENT_LENGTH_TYPE_STR;
5258
static const char* USER_AGENT_TYPE_STR;

src/internals/StreamHttpReply.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,17 @@ void ArduinoHttpServer::AbstractStreamHttpReply::send(const String& data, const
2626
// Read away remaining bytes.
2727
while(getStream().read()>=0);
2828

29-
String httpErrorReply;
30-
httpErrorReply += AHS_F("HTTP/1.1 ");
31-
httpErrorReply += getCode() + " ";
32-
httpErrorReply += title + "\r\n";
33-
httpErrorReply += AHS_F("Connection: close\r\n");
34-
httpErrorReply += AHS_F("Content-Length: ");
35-
httpErrorReply += data.length();
36-
httpErrorReply += AHS_F("\r\n");
37-
httpErrorReply += AHS_F("Content-Type: ");
38-
httpErrorReply += m_contentType;
39-
httpErrorReply += AHS_F("\r\n");
40-
httpErrorReply += AHS_F("\r\n");
41-
httpErrorReply += data;
42-
httpErrorReply += AHS_F("\r\n");
43-
4429
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Printing Reply ... ");
45-
getStream().print(httpErrorReply);
30+
31+
getStream().print( AHS_F("HTTP/1.1 ") );
32+
getStream().print( getCode() + " ");
33+
getStream().print( title + "\r\n" );
34+
getStream().print( AHS_F("Connection: close\r\n") );
35+
getStream().print( AHS_F("Content-Length: ") ); getStream().print( data.length()); getStream().print( AHS_F("\r\n") );
36+
getStream().print( AHS_F("Content-Type: ") ); getStream().print( m_contentType ); getStream().print( AHS_F("\r\n") );
37+
getStream().print( AHS_F("\r\n") );
38+
getStream().print( data ); getStream().print( AHS_F("\r\n") );
39+
4640
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("done.");
4741
}
4842

@@ -151,12 +145,12 @@ void ArduinoHttpServer::StreamHttpAuthenticateReply::send()
151145
// Read away remaining bytes.
152146
while(getStream().read()>=0);
153147

154-
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Printing Reply ... ");
148+
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Printing authenticate reply ... ");
155149
getStream().println(AHS_F("HTTP/1.1 401 Unauthorized"));
156150
getStream().println(AHS_F("WWW-Authenticate: Basic realm=\"Login Required\""));
157151
getStream().println(AHS_F("Connection: close"));
158152
getStream().println(AHS_F(""));
159-
getStream().println(AHS_F("<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD><BODY BGCOLOR=\"#cc9999\"><H4>401 Unauthorized</H4>Authorization required.</BODY></HTML>"));
153+
getStream().println(AHS_F("<html><head><title>401 Unauthorized</title></head><body><h4>401 Unauthorized</h4>Authorization required.</body></html>"));
160154
getStream().println(AHS_F(""));
161155
getStream().println(AHS_F(""));
162156
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("done.");

src/internals/StreamHttpRequest.hpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class StreamHttpRequest
8585
static const long LINE_READ_TIMEOUT_MS = 10000L; //!< [ms] Wait 10s for reception of a complete line.
8686
static const int MAX_RETRIES_WAIT_DATA_AVAILABLE = 255;
8787

88+
constexpr static const char* BASIC_AUTH_TYPE_STR = "Basic";
89+
8890
void parseRequest(char lineBuffer[MAX_LINE_SIZE]);
8991
void parseMethod(char lineBuffer[MAX_LINE_SIZE]);
9092
void parseResource();
@@ -380,34 +382,30 @@ const ArduinoHttpServer::ErrorString ArduinoHttpServer::StreamHttpRequest<MAX_BO
380382
}
381383

382384
template <size_t MAX_BODY_SIZE>
383-
bool ArduinoHttpServer::StreamHttpRequest<MAX_BODY_SIZE>::authenticate(const char * username, const char * password) const
385+
bool ArduinoHttpServer::StreamHttpRequest<MAX_BODY_SIZE>::authenticate(const char *username, const char *password) const
384386
{
385387
if (m_authorizationField.getType() == HttpField::Type::NOT_SUPPORTED)
386388
{
387389
return false;
388390
}
389391

390-
if (!m_authorizationField.getValueAsString().startsWith("Basic"))
392+
// HTTP value: "<Type> <Base 64 encoded credentials>"
393+
// Retrieve type and verify wether it is basic authorization.
394+
if(!(m_authorizationField.getSubValueString(0) == BASIC_AUTH_TYPE_STR))
391395
{
392-
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("Unsupported auth header");
396+
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Unsupported authentication header: ");
397+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN(m_authorizationField);
393398
return false;
394399
}
395400

396-
String combinedInput;
397-
if (!combinedInput.reserve(strlen(username) + strlen(password) + 2))
398-
{
399-
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("Not enough memory");
400-
return false;
401-
}
402-
combinedInput += username;
403-
combinedInput += AHS_F(":");
404-
combinedInput += password;
401+
FixString<128U> combinedInput;
402+
combinedInput += username; combinedInput += AHS_F(":"); combinedInput += password;
405403

406-
int encodedLength = Base64.encodedLength(combinedInput.length());
407-
char encodedString[encodedLength];
408-
Base64.encode(encodedString, combinedInput.c_str(), combinedInput.length());
404+
const int encodedLength = Base64.encodedLength(combinedInput.length());
405+
char encodedString[encodedLength] = {0};
406+
Base64.encode(encodedString, combinedInput.cStr(), combinedInput.length());
409407

410-
if (strcmp(m_authorizationField.getValueAsString().c_str()+6,encodedString) == 0)
408+
if ( m_authorizationField.getSubValueString(1) == encodedString )
411409
{
412410
return true;
413411
}

0 commit comments

Comments
 (0)