10.1 Kombiniert die Übung 6.4 Wenn sich jemand nähert, Lauflicht einschalten mit dem Yahoo Weather Dienst, dass bei Unterwarnungen das Lauflicht eingeschaltet wird.

Dependencies:   EthernetInterface mbed-rtos mbed spxml

Fork of YahooWeather by smd.iotkit2.ch

Committer:
stefan1691
Date:
Wed May 27 17:23:55 2015 +0000
Revision:
6:735d5412de0d
Parent:
2:c9e058ee6f87
10.1 Kombiniert die ?bung 6.4 Wenn sich jemand n?hert, Lauflicht einschalten mit dem Yahoo Weather Dienst, dass bei Unterwarnungen das Lauflicht eingeschaltet wird.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcel1691 1:2e29a33cd918 1 /* HTTPClient.cpp */
marcel1691 1:2e29a33cd918 2 /* Copyright (C) 2012 mbed.org, MIT License
marcel1691 1:2e29a33cd918 3 *
marcel1691 1:2e29a33cd918 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
marcel1691 1:2e29a33cd918 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
marcel1691 1:2e29a33cd918 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
marcel1691 1:2e29a33cd918 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
marcel1691 1:2e29a33cd918 8 * furnished to do so, subject to the following conditions:
marcel1691 1:2e29a33cd918 9 *
marcel1691 1:2e29a33cd918 10 * The above copyright notice and this permission notice shall be included in all copies or
marcel1691 1:2e29a33cd918 11 * substantial portions of the Software.
marcel1691 1:2e29a33cd918 12 *
marcel1691 1:2e29a33cd918 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
marcel1691 1:2e29a33cd918 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
marcel1691 1:2e29a33cd918 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
marcel1691 1:2e29a33cd918 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
marcel1691 1:2e29a33cd918 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
marcel1691 1:2e29a33cd918 18 */
marcel1691 1:2e29a33cd918 19
marcel1691 1:2e29a33cd918 20 //Debug is disabled by default
marcel1691 1:2e29a33cd918 21 //#define DEBUG "HTCL"
marcel1691 1:2e29a33cd918 22 #include <cstdio>
marcel1691 1:2e29a33cd918 23 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
marcel1691 1:2e29a33cd918 24 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 25 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 26 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 27 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 28 #else
marcel1691 1:2e29a33cd918 29 #define DBG(x, ...)
marcel1691 1:2e29a33cd918 30 #define WARN(x, ...)
marcel1691 1:2e29a33cd918 31 #define ERR(x, ...)
marcel1691 1:2e29a33cd918 32 #define INFO(x, ...)
marcel1691 1:2e29a33cd918 33 #endif
marcel1691 1:2e29a33cd918 34
marcel1691 1:2e29a33cd918 35 //#define HTTP_PORT 80
marcel1691 1:2e29a33cd918 36
marcel1691 1:2e29a33cd918 37 #define OK 0
marcel1691 1:2e29a33cd918 38
marcel1691 1:2e29a33cd918 39 #define MIN(x,y) (((x)<(y))?(x):(y))
marcel1691 1:2e29a33cd918 40 #define MAX(x,y) (((x)>(y))?(x):(y))
marcel1691 1:2e29a33cd918 41
marcel1691 1:2e29a33cd918 42 #define CHUNK_SIZE 256
marcel1691 1:2e29a33cd918 43 #define MAXLEN_VALUE 120 /* Max URL and Max Value for Name:Value */
marcel1691 1:2e29a33cd918 44
marcel1691 1:2e29a33cd918 45 #include <cstring>
marcel1691 1:2e29a33cd918 46
marcel1691 1:2e29a33cd918 47 #include "HTTPClient.h"
marcel1691 1:2e29a33cd918 48
marcel1691 1:2e29a33cd918 49 HTTPClient::HTTPClient() :
marcel1691 1:2e29a33cd918 50 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL),
marcel1691 1:2e29a33cd918 51 m_nCustomHeaders(0), m_httpResponseCode(0),
marcel1691 1:2e29a33cd918 52 m_maxredirections(1), m_location(NULL)
marcel1691 1:2e29a33cd918 53 {
marcel1691 1:2e29a33cd918 54
marcel1691 1:2e29a33cd918 55 }
marcel1691 1:2e29a33cd918 56
marcel1691 1:2e29a33cd918 57 HTTPClient::~HTTPClient()
marcel1691 1:2e29a33cd918 58 {
marcel1691 1:2e29a33cd918 59
marcel1691 1:2e29a33cd918 60 }
marcel1691 1:2e29a33cd918 61
marcel1691 1:2e29a33cd918 62 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
marcel1691 1:2e29a33cd918 63 {
marcel1691 1:2e29a33cd918 64 #if 1
marcel1691 1:2e29a33cd918 65 if (m_basicAuthUser)
marcel1691 1:2e29a33cd918 66 free(m_basicAuthUser);
marcel1691 1:2e29a33cd918 67 m_basicAuthUser = (char *)malloc(strlen(user)+1);
marcel1691 1:2e29a33cd918 68 strcpy(m_basicAuthUser, user);
marcel1691 1:2e29a33cd918 69 if (m_basicAuthPassword)
marcel1691 1:2e29a33cd918 70 free(m_basicAuthPassword);
marcel1691 1:2e29a33cd918 71 m_basicAuthPassword = (char *)malloc(strlen(password)+1);
marcel1691 1:2e29a33cd918 72 strcpy(m_basicAuthPassword, password);
marcel1691 1:2e29a33cd918 73 #else
marcel1691 1:2e29a33cd918 74 m_basicAuthUser = user;
marcel1691 1:2e29a33cd918 75 m_basicAuthPassword = password;
marcel1691 1:2e29a33cd918 76 #endif
marcel1691 1:2e29a33cd918 77 }
marcel1691 1:2e29a33cd918 78
marcel1691 1:2e29a33cd918 79 void HTTPClient::customHeaders(const char **headers, size_t pairs)
marcel1691 1:2e29a33cd918 80 {
marcel1691 1:2e29a33cd918 81 m_customHeaders = headers;
marcel1691 1:2e29a33cd918 82 m_nCustomHeaders = pairs;
marcel1691 1:2e29a33cd918 83 }
marcel1691 1:2e29a33cd918 84
marcel1691 1:2e29a33cd918 85
marcel1691 1:2e29a33cd918 86 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 87 {
marcel1691 1:2e29a33cd918 88 return connect(url, HTTP_GET, NULL, pDataIn, timeout);
marcel1691 1:2e29a33cd918 89 }
marcel1691 1:2e29a33cd918 90
marcel1691 1:2e29a33cd918 91 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 92 {
marcel1691 1:2e29a33cd918 93 HTTPText str(result, maxResultLen);
marcel1691 1:2e29a33cd918 94 return get(url, &str, timeout);
marcel1691 1:2e29a33cd918 95 }
marcel1691 1:2e29a33cd918 96
marcel1691 1:2e29a33cd918 97 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 98 {
marcel1691 1:2e29a33cd918 99 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
marcel1691 1:2e29a33cd918 100 }
marcel1691 1:2e29a33cd918 101
marcel1691 1:2e29a33cd918 102 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 103 {
marcel1691 1:2e29a33cd918 104 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
marcel1691 1:2e29a33cd918 105 }
marcel1691 1:2e29a33cd918 106
marcel1691 1:2e29a33cd918 107 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 108 {
marcel1691 1:2e29a33cd918 109 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
marcel1691 1:2e29a33cd918 110 }
marcel1691 1:2e29a33cd918 111
marcel1691 1:2e29a33cd918 112
marcel1691 1:2e29a33cd918 113 int HTTPClient::getHTTPResponseCode()
marcel1691 1:2e29a33cd918 114 {
marcel1691 1:2e29a33cd918 115 return m_httpResponseCode;
marcel1691 1:2e29a33cd918 116 }
marcel1691 1:2e29a33cd918 117
marcel1691 1:2e29a33cd918 118 void HTTPClient::setMaxRedirections(int i)
marcel1691 1:2e29a33cd918 119 {
marcel1691 1:2e29a33cd918 120 if (i < 1)
marcel1691 1:2e29a33cd918 121 i = 1;
marcel1691 1:2e29a33cd918 122 m_maxredirections = i;
marcel1691 1:2e29a33cd918 123 }
marcel1691 1:2e29a33cd918 124
marcel1691 1:2e29a33cd918 125 #define CHECK_CONN_ERR(ret) \
marcel1691 1:2e29a33cd918 126 do{ \
marcel1691 1:2e29a33cd918 127 if(ret) { \
marcel1691 1:2e29a33cd918 128 m_sock.close(); \
marcel1691 1:2e29a33cd918 129 ERR("Connection error (%d)", ret); \
marcel1691 1:2e29a33cd918 130 return HTTP_CONN; \
marcel1691 1:2e29a33cd918 131 } \
marcel1691 1:2e29a33cd918 132 } while(0)
marcel1691 1:2e29a33cd918 133
marcel1691 1:2e29a33cd918 134 #define PRTCL_ERR() \
marcel1691 1:2e29a33cd918 135 do{ \
marcel1691 1:2e29a33cd918 136 m_sock.close(); \
marcel1691 1:2e29a33cd918 137 ERR("Protocol error"); \
marcel1691 1:2e29a33cd918 138 return HTTP_PRTCL; \
marcel1691 1:2e29a33cd918 139 } while(0)
marcel1691 1:2e29a33cd918 140
marcel1691 1:2e29a33cd918 141 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
marcel1691 1:2e29a33cd918 142 {
marcel1691 1:2e29a33cd918 143 m_httpResponseCode = 0; //Invalidate code
marcel1691 1:2e29a33cd918 144 m_timeout = timeout;
marcel1691 1:2e29a33cd918 145
marcel1691 1:2e29a33cd918 146 pDataIn->writeReset();
marcel1691 1:2e29a33cd918 147 if( pDataOut ) {
marcel1691 1:2e29a33cd918 148 pDataOut->readReset();
marcel1691 1:2e29a33cd918 149 }
marcel1691 1:2e29a33cd918 150
marcel1691 1:2e29a33cd918 151 char scheme[8];
marcel1691 1:2e29a33cd918 152 uint16_t port;
marcel1691 1:2e29a33cd918 153 char host[32];
marcel1691 1:2e29a33cd918 154 char path[MAXLEN_VALUE];
marcel1691 1:2e29a33cd918 155 size_t recvContentLength = 0;
marcel1691 1:2e29a33cd918 156 bool recvChunked = false;
marcel1691 1:2e29a33cd918 157 int crlfPos = 0;
marcel1691 1:2e29a33cd918 158 char buf[CHUNK_SIZE];
marcel1691 1:2e29a33cd918 159 size_t trfLen;
marcel1691 1:2e29a33cd918 160 int ret = 0;
marcel1691 1:2e29a33cd918 161
marcel1691 1:2e29a33cd918 162 int maxRedirect = m_maxredirections;
marcel1691 1:2e29a33cd918 163
marcel1691 1:2e29a33cd918 164 while (maxRedirect--) {
marcel1691 1:2e29a33cd918 165 bool takeRedirect = false;
marcel1691 1:2e29a33cd918 166
marcel1691 1:2e29a33cd918 167 INFO("parse: [%s]", url);
marcel1691 1:2e29a33cd918 168 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
marcel1691 1:2e29a33cd918 169 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
marcel1691 1:2e29a33cd918 170 if(res != HTTP_OK) {
marcel1691 1:2e29a33cd918 171 ERR("parseURL returned %d", res);
marcel1691 1:2e29a33cd918 172 return res;
marcel1691 1:2e29a33cd918 173 }
marcel1691 1:2e29a33cd918 174
marcel1691 1:2e29a33cd918 175 if(port == 0) { //TODO do handle HTTPS->443
marcel1691 1:2e29a33cd918 176 port = 80;
marcel1691 1:2e29a33cd918 177 }
marcel1691 1:2e29a33cd918 178
marcel1691 1:2e29a33cd918 179 DBG("Scheme: %s", scheme);
marcel1691 1:2e29a33cd918 180 DBG("Host: %s", host);
marcel1691 1:2e29a33cd918 181 DBG("Port: %d", port);
marcel1691 1:2e29a33cd918 182 DBG("Path: %s", path);
marcel1691 1:2e29a33cd918 183
marcel1691 1:2e29a33cd918 184 //Connect
marcel1691 1:2e29a33cd918 185 DBG("Connecting socket to server");
marcel1691 1:2e29a33cd918 186 ret = m_sock.connect(host, port);
marcel1691 1:2e29a33cd918 187 if (ret < 0) {
marcel1691 1:2e29a33cd918 188 m_sock.close();
marcel1691 1:2e29a33cd918 189 ERR("Could not connect");
marcel1691 1:2e29a33cd918 190 return HTTP_CONN;
marcel1691 1:2e29a33cd918 191 }
marcel1691 1:2e29a33cd918 192
marcel1691 1:2e29a33cd918 193 //Send request
marcel1691 1:2e29a33cd918 194 DBG("Sending request");
marcel1691 1:2e29a33cd918 195 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
marcel1691 1:2e29a33cd918 196 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s:%d\r\nConnection: keep-alive\r\n", meth, path, host, port); //Write request
marcel1691 1:2e29a33cd918 197 INFO(" buf{%s}", buf);
marcel1691 1:2e29a33cd918 198 ret = send(buf);
marcel1691 1:2e29a33cd918 199 if (ret) {
marcel1691 1:2e29a33cd918 200 m_sock.close();
marcel1691 1:2e29a33cd918 201 ERR("Could not write request");
marcel1691 1:2e29a33cd918 202 return HTTP_CONN;
marcel1691 1:2e29a33cd918 203 }
marcel1691 1:2e29a33cd918 204
marcel1691 1:2e29a33cd918 205 // send authorization
marcel1691 1:2e29a33cd918 206 INFO("send auth (if defined)");
marcel1691 1:2e29a33cd918 207 if (m_basicAuthUser && m_basicAuthPassword) {
marcel1691 1:2e29a33cd918 208 strcpy(buf, "Authorization: Basic ");
marcel1691 1:2e29a33cd918 209 createauth(m_basicAuthUser, m_basicAuthPassword, buf+strlen(buf), sizeof(buf)-strlen(buf));
marcel1691 1:2e29a33cd918 210 strcat(buf, "\r\n");
marcel1691 1:2e29a33cd918 211 INFO(" (%s,%s) => (%s)", m_basicAuthUser, m_basicAuthPassword, buf);
marcel1691 1:2e29a33cd918 212 ret = send(buf);
marcel1691 1:2e29a33cd918 213 INFO(" ret = %d", ret);
marcel1691 1:2e29a33cd918 214 if(ret) {
marcel1691 1:2e29a33cd918 215 m_sock.close();
marcel1691 1:2e29a33cd918 216 ERR("Could not write request");
marcel1691 1:2e29a33cd918 217 return HTTP_CONN;
marcel1691 1:2e29a33cd918 218 }
marcel1691 1:2e29a33cd918 219 }
marcel1691 1:2e29a33cd918 220
marcel1691 1:2e29a33cd918 221 //Send all headers
marcel1691 1:2e29a33cd918 222 INFO("Send custom header(s) %d (if any)", m_nCustomHeaders);
marcel1691 1:2e29a33cd918 223 for (size_t nh = 0; nh < m_nCustomHeaders * 2; nh+=2) {
marcel1691 1:2e29a33cd918 224 INFO("hdr[%d] %s:", nh, m_customHeaders[nh]);
marcel1691 1:2e29a33cd918 225 INFO(" %s", m_customHeaders[nh+1]);
marcel1691 1:2e29a33cd918 226 snprintf(buf, sizeof(buf), "%s: %s\r\n", m_customHeaders[nh], m_customHeaders[nh+1]);
marcel1691 1:2e29a33cd918 227 ret = send(buf);
marcel1691 1:2e29a33cd918 228 if (ret) {
marcel1691 1:2e29a33cd918 229 ERR("closing");
marcel1691 1:2e29a33cd918 230 wait_ms(50);
marcel1691 1:2e29a33cd918 231 m_sock.close();
marcel1691 1:2e29a33cd918 232 ERR("Could not write request");
marcel1691 1:2e29a33cd918 233 return HTTP_CONN;
marcel1691 1:2e29a33cd918 234 }
marcel1691 1:2e29a33cd918 235 INFO(" hdr %d", ret);
marcel1691 1:2e29a33cd918 236 }
marcel1691 1:2e29a33cd918 237
marcel1691 1:2e29a33cd918 238 //Send default headers
marcel1691 1:2e29a33cd918 239 DBG("Sending headers");
marcel1691 1:2e29a33cd918 240 if( pDataOut != NULL ) {
marcel1691 1:2e29a33cd918 241 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 242 ret = send("Transfer-Encoding: chunked\r\n");
marcel1691 1:2e29a33cd918 243 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 244 } else {
marcel1691 1:2e29a33cd918 245 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
marcel1691 1:2e29a33cd918 246 ret = send(buf);
marcel1691 1:2e29a33cd918 247 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 248 }
marcel1691 1:2e29a33cd918 249 char type[48];
marcel1691 1:2e29a33cd918 250 if( pDataOut->getDataType(type, 48) == HTTP_OK ) {
marcel1691 1:2e29a33cd918 251 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
marcel1691 1:2e29a33cd918 252 ret = send(buf);
marcel1691 1:2e29a33cd918 253 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 254 }
marcel1691 1:2e29a33cd918 255 }
marcel1691 1:2e29a33cd918 256
marcel1691 1:2e29a33cd918 257 //Close headers
marcel1691 1:2e29a33cd918 258 DBG("Headers sent");
marcel1691 1:2e29a33cd918 259 ret = send("\r\n");
marcel1691 1:2e29a33cd918 260 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 261
marcel1691 1:2e29a33cd918 262 //Send data (if available)
marcel1691 1:2e29a33cd918 263 if( pDataOut != NULL ) {
marcel1691 1:2e29a33cd918 264 DBG("Sending data");
marcel1691 1:2e29a33cd918 265 while(true) {
marcel1691 1:2e29a33cd918 266 size_t writtenLen = 0;
marcel1691 1:2e29a33cd918 267 pDataOut->read(buf, CHUNK_SIZE, &trfLen);
marcel1691 1:2e29a33cd918 268 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 269 //Write chunk header
marcel1691 1:2e29a33cd918 270 char chunkHeader[16];
marcel1691 1:2e29a33cd918 271 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
marcel1691 1:2e29a33cd918 272 ret = send(chunkHeader);
marcel1691 1:2e29a33cd918 273 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 274 } else if( trfLen == 0 ) {
marcel1691 1:2e29a33cd918 275 break;
marcel1691 1:2e29a33cd918 276 }
marcel1691 1:2e29a33cd918 277 if( trfLen != 0 ) {
marcel1691 1:2e29a33cd918 278 ret = send(buf, trfLen);
marcel1691 1:2e29a33cd918 279 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 280 }
marcel1691 1:2e29a33cd918 281
marcel1691 1:2e29a33cd918 282 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 283 ret = send("\r\n"); //Chunk-terminating CRLF
marcel1691 1:2e29a33cd918 284 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 285 } else {
marcel1691 1:2e29a33cd918 286 writtenLen += trfLen;
marcel1691 1:2e29a33cd918 287 if( writtenLen >= pDataOut->getDataLen() ) {
marcel1691 1:2e29a33cd918 288 break;
marcel1691 1:2e29a33cd918 289 }
marcel1691 1:2e29a33cd918 290 }
marcel1691 1:2e29a33cd918 291
marcel1691 1:2e29a33cd918 292 if( trfLen == 0 ) {
marcel1691 1:2e29a33cd918 293 break;
marcel1691 1:2e29a33cd918 294 }
marcel1691 1:2e29a33cd918 295 }
marcel1691 1:2e29a33cd918 296
marcel1691 1:2e29a33cd918 297 }
marcel1691 1:2e29a33cd918 298
marcel1691 1:2e29a33cd918 299 //Receive response
marcel1691 1:2e29a33cd918 300 DBG("Receiving response");
marcel1691 1:2e29a33cd918 301 //ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
marcel1691 1:2e29a33cd918 302 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); // recommended by Rob Noble to avoid timeout wait
marcel1691 1:2e29a33cd918 303 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 304 buf[trfLen] = '\0';
marcel1691 1:2e29a33cd918 305 INFO("Received \r\n(%s\r\n)", buf);
marcel1691 1:2e29a33cd918 306
marcel1691 1:2e29a33cd918 307 char* crlfPtr = strstr(buf, "\r\n");
marcel1691 1:2e29a33cd918 308 if( crlfPtr == NULL) {
marcel1691 1:2e29a33cd918 309 PRTCL_ERR();
marcel1691 1:2e29a33cd918 310 }
marcel1691 1:2e29a33cd918 311
marcel1691 1:2e29a33cd918 312 crlfPos = crlfPtr - buf;
marcel1691 1:2e29a33cd918 313 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 314
marcel1691 1:2e29a33cd918 315 //Parse HTTP response
marcel1691 1:2e29a33cd918 316 if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) {
marcel1691 1:2e29a33cd918 317 //Cannot match string, error
marcel1691 1:2e29a33cd918 318 ERR("Not a correct HTTP answer : {%s}\n", buf);
marcel1691 1:2e29a33cd918 319 PRTCL_ERR();
marcel1691 1:2e29a33cd918 320 }
marcel1691 1:2e29a33cd918 321
marcel1691 1:2e29a33cd918 322 if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 400) ) {
marcel1691 1:2e29a33cd918 323 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers
marcel1691 1:2e29a33cd918 324 WARN("Response code %d", m_httpResponseCode);
marcel1691 1:2e29a33cd918 325 PRTCL_ERR();
marcel1691 1:2e29a33cd918 326 }
marcel1691 1:2e29a33cd918 327
marcel1691 1:2e29a33cd918 328 DBG("Reading headers");
marcel1691 1:2e29a33cd918 329
marcel1691 1:2e29a33cd918 330 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 331 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 332
marcel1691 1:2e29a33cd918 333 recvContentLength = 0;
marcel1691 1:2e29a33cd918 334 recvChunked = false;
marcel1691 1:2e29a33cd918 335 //Now get headers
marcel1691 1:2e29a33cd918 336 while( true ) {
marcel1691 1:2e29a33cd918 337 crlfPtr = strstr(buf, "\r\n");
marcel1691 1:2e29a33cd918 338 if(crlfPtr == NULL) {
marcel1691 1:2e29a33cd918 339 if( trfLen < CHUNK_SIZE - 1 ) {
marcel1691 1:2e29a33cd918 340 size_t newTrfLen = 0;
marcel1691 1:2e29a33cd918 341 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 342 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 343 buf[trfLen] = '\0';
marcel1691 1:2e29a33cd918 344 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
marcel1691 1:2e29a33cd918 345 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 346 continue;
marcel1691 1:2e29a33cd918 347 } else {
marcel1691 1:2e29a33cd918 348 PRTCL_ERR();
marcel1691 1:2e29a33cd918 349 }
marcel1691 1:2e29a33cd918 350 }
marcel1691 1:2e29a33cd918 351
marcel1691 1:2e29a33cd918 352 crlfPos = crlfPtr - buf;
marcel1691 1:2e29a33cd918 353
marcel1691 1:2e29a33cd918 354 if(crlfPos == 0) { //End of headers
marcel1691 1:2e29a33cd918 355 DBG("Headers read");
marcel1691 1:2e29a33cd918 356 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 357 trfLen -= 2;
marcel1691 1:2e29a33cd918 358 break;
marcel1691 1:2e29a33cd918 359 }
marcel1691 1:2e29a33cd918 360
marcel1691 1:2e29a33cd918 361 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 362
marcel1691 2:c9e058ee6f87 363 char key[36];
marcel1691 1:2e29a33cd918 364 char value[MAXLEN_VALUE];
marcel1691 1:2e29a33cd918 365
marcel1691 2:c9e058ee6f87 366 key[35] = '\0';
marcel1691 1:2e29a33cd918 367 value[MAXLEN_VALUE - 1] = '\0';
marcel1691 1:2e29a33cd918 368
marcel1691 2:c9e058ee6f87 369 int n = sscanf(buf, "%35[^:]: %119[^\r\n]", key, value);
marcel1691 1:2e29a33cd918 370 if ( n == 2 ) {
marcel1691 1:2e29a33cd918 371 DBG("Read header : %s: %s", key, value);
marcel1691 1:2e29a33cd918 372 if( !strcmp(key, "Content-Length") ) {
marcel1691 1:2e29a33cd918 373 sscanf(value, "%d", &recvContentLength);
marcel1691 1:2e29a33cd918 374 pDataIn->setDataLen(recvContentLength);
marcel1691 1:2e29a33cd918 375 } else if( !strcmp(key, "Transfer-Encoding") ) {
marcel1691 1:2e29a33cd918 376 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) {
marcel1691 1:2e29a33cd918 377 recvChunked = true;
marcel1691 1:2e29a33cd918 378 pDataIn->setIsChunked(true);
marcel1691 1:2e29a33cd918 379 }
marcel1691 1:2e29a33cd918 380 } else if( !strcmp(key, "Content-Type") ) {
marcel1691 1:2e29a33cd918 381 pDataIn->setDataType(value);
marcel1691 1:2e29a33cd918 382 } else if ( !strcmp(key, "Location") ) {
marcel1691 1:2e29a33cd918 383 if (m_location)
marcel1691 1:2e29a33cd918 384 free(m_location);
marcel1691 1:2e29a33cd918 385 m_location = (char *)malloc(strlen(value)+1);
marcel1691 1:2e29a33cd918 386 if (m_location) {
marcel1691 1:2e29a33cd918 387 strcpy(m_location,value);
marcel1691 1:2e29a33cd918 388 url = m_location;
marcel1691 1:2e29a33cd918 389 INFO("Following redirect[%d] to [%s]", maxRedirect, url);
marcel1691 1:2e29a33cd918 390 m_sock.close();
marcel1691 1:2e29a33cd918 391 takeRedirect = true;
marcel1691 1:2e29a33cd918 392 break; // exit the while(true) header to follow the redirect
marcel1691 1:2e29a33cd918 393 }
marcel1691 1:2e29a33cd918 394 }
marcel1691 1:2e29a33cd918 395
marcel1691 1:2e29a33cd918 396 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 397 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 398 } else {
marcel1691 1:2e29a33cd918 399 ERR("Could not parse header");
marcel1691 1:2e29a33cd918 400 PRTCL_ERR();
marcel1691 1:2e29a33cd918 401 }
marcel1691 1:2e29a33cd918 402
marcel1691 1:2e29a33cd918 403 } // while(true) // get headers
marcel1691 1:2e29a33cd918 404 if (!takeRedirect)
marcel1691 1:2e29a33cd918 405 break;
marcel1691 1:2e29a33cd918 406 } // while (maxRedirect)
marcel1691 1:2e29a33cd918 407
marcel1691 1:2e29a33cd918 408 //Receive data
marcel1691 1:2e29a33cd918 409 DBG("Receiving data");
marcel1691 1:2e29a33cd918 410 while(true) {
marcel1691 1:2e29a33cd918 411 size_t readLen = 0;
marcel1691 1:2e29a33cd918 412
marcel1691 1:2e29a33cd918 413 if( recvChunked ) {
marcel1691 1:2e29a33cd918 414 //Read chunk header
marcel1691 1:2e29a33cd918 415 bool foundCrlf;
marcel1691 1:2e29a33cd918 416 do {
marcel1691 1:2e29a33cd918 417 foundCrlf = false;
marcel1691 1:2e29a33cd918 418 crlfPos=0;
marcel1691 1:2e29a33cd918 419 buf[trfLen]=0;
marcel1691 1:2e29a33cd918 420 if(trfLen >= 2) {
marcel1691 1:2e29a33cd918 421 for(; crlfPos < trfLen - 2; crlfPos++) {
marcel1691 1:2e29a33cd918 422 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) {
marcel1691 1:2e29a33cd918 423 foundCrlf = true;
marcel1691 1:2e29a33cd918 424 break;
marcel1691 1:2e29a33cd918 425 }
marcel1691 1:2e29a33cd918 426 }
marcel1691 1:2e29a33cd918 427 }
marcel1691 1:2e29a33cd918 428 if(!foundCrlf) { //Try to read more
marcel1691 1:2e29a33cd918 429 if( trfLen < CHUNK_SIZE ) {
marcel1691 1:2e29a33cd918 430 size_t newTrfLen = 0;
marcel1691 1:2e29a33cd918 431 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 432 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 433 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 434 continue;
marcel1691 1:2e29a33cd918 435 } else {
marcel1691 1:2e29a33cd918 436 PRTCL_ERR();
marcel1691 1:2e29a33cd918 437 }
marcel1691 1:2e29a33cd918 438 }
marcel1691 1:2e29a33cd918 439 } while(!foundCrlf);
marcel1691 1:2e29a33cd918 440 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 441 int n = sscanf(buf, "%x", &readLen);
marcel1691 1:2e29a33cd918 442 if(n!=1) {
marcel1691 1:2e29a33cd918 443 ERR("Could not read chunk length");
marcel1691 1:2e29a33cd918 444 PRTCL_ERR();
marcel1691 1:2e29a33cd918 445 }
marcel1691 1:2e29a33cd918 446
marcel1691 1:2e29a33cd918 447 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
marcel1691 1:2e29a33cd918 448 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 449
marcel1691 1:2e29a33cd918 450 if( readLen == 0 ) {
marcel1691 1:2e29a33cd918 451 //Last chunk
marcel1691 1:2e29a33cd918 452 break;
marcel1691 1:2e29a33cd918 453 }
marcel1691 1:2e29a33cd918 454 } else {
marcel1691 1:2e29a33cd918 455 readLen = recvContentLength;
marcel1691 1:2e29a33cd918 456 }
marcel1691 1:2e29a33cd918 457
marcel1691 1:2e29a33cd918 458 DBG("Retrieving %d bytes", readLen);
marcel1691 1:2e29a33cd918 459
marcel1691 1:2e29a33cd918 460 do {
marcel1691 1:2e29a33cd918 461 INFO("write %d,%d: %s", trfLen, readLen, buf);
marcel1691 1:2e29a33cd918 462 pDataIn->write(buf, MIN(trfLen, readLen));
marcel1691 1:2e29a33cd918 463 if( trfLen > readLen ) {
marcel1691 1:2e29a33cd918 464 memmove(buf, &buf[readLen], trfLen - readLen);
marcel1691 1:2e29a33cd918 465 trfLen -= readLen;
marcel1691 1:2e29a33cd918 466 readLen = 0;
marcel1691 1:2e29a33cd918 467 } else {
marcel1691 1:2e29a33cd918 468 readLen -= trfLen;
marcel1691 1:2e29a33cd918 469 }
marcel1691 1:2e29a33cd918 470
marcel1691 1:2e29a33cd918 471 if(readLen) {
marcel1691 1:2e29a33cd918 472 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
marcel1691 1:2e29a33cd918 473 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 474 }
marcel1691 1:2e29a33cd918 475 } while(readLen);
marcel1691 1:2e29a33cd918 476
marcel1691 1:2e29a33cd918 477 if( recvChunked ) {
marcel1691 1:2e29a33cd918 478 if(trfLen < 2) {
marcel1691 1:2e29a33cd918 479 size_t newTrfLen;
marcel1691 1:2e29a33cd918 480 //Read missing chars to find end of chunk
marcel1691 1:2e29a33cd918 481 INFO("read chunk");
marcel1691 1:2e29a33cd918 482 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 483 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 484 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 485 }
marcel1691 1:2e29a33cd918 486 if( (buf[0] != '\r') || (buf[1] != '\n') ) {
marcel1691 1:2e29a33cd918 487 ERR("Format error");
marcel1691 1:2e29a33cd918 488 PRTCL_ERR();
marcel1691 1:2e29a33cd918 489 }
marcel1691 1:2e29a33cd918 490 memmove(buf, &buf[2], trfLen - 2);
marcel1691 1:2e29a33cd918 491 trfLen -= 2;
marcel1691 1:2e29a33cd918 492 } else {
marcel1691 1:2e29a33cd918 493 break;
marcel1691 1:2e29a33cd918 494 }
marcel1691 1:2e29a33cd918 495
marcel1691 1:2e29a33cd918 496 }
marcel1691 1:2e29a33cd918 497
marcel1691 1:2e29a33cd918 498 m_sock.close();
marcel1691 1:2e29a33cd918 499 DBG("Completed HTTP transaction");
marcel1691 1:2e29a33cd918 500
marcel1691 1:2e29a33cd918 501 return HTTP_OK;
marcel1691 1:2e29a33cd918 502 }
marcel1691 1:2e29a33cd918 503
marcel1691 1:2e29a33cd918 504 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
marcel1691 1:2e29a33cd918 505 {
marcel1691 1:2e29a33cd918 506 DBG("Trying to read between %d and %d bytes", minLen, maxLen);
marcel1691 1:2e29a33cd918 507 size_t readLen = 0;
marcel1691 1:2e29a33cd918 508
marcel1691 1:2e29a33cd918 509 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 510 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 511 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 512 }
marcel1691 1:2e29a33cd918 513
marcel1691 1:2e29a33cd918 514 int ret;
marcel1691 1:2e29a33cd918 515 while (readLen < maxLen) {
marcel1691 1:2e29a33cd918 516 if (readLen < minLen) {
marcel1691 1:2e29a33cd918 517 DBG("Trying to read at most %4d bytes [Blocking] %d,%d", minLen - readLen, minLen, readLen);
marcel1691 1:2e29a33cd918 518 m_sock.set_blocking(false, m_timeout);
marcel1691 1:2e29a33cd918 519 ret = m_sock.receive_all(buf + readLen, minLen - readLen);
marcel1691 1:2e29a33cd918 520 } else {
marcel1691 1:2e29a33cd918 521 DBG("Trying to read at most %4d bytes [Not blocking] %d,%d", maxLen - readLen, maxLen, readLen);
marcel1691 1:2e29a33cd918 522 m_sock.set_blocking(false, 0);
marcel1691 1:2e29a33cd918 523 ret = m_sock.receive(buf + readLen, maxLen - readLen);
marcel1691 1:2e29a33cd918 524 }
marcel1691 1:2e29a33cd918 525
marcel1691 1:2e29a33cd918 526 if (ret > 0) {
marcel1691 1:2e29a33cd918 527 readLen += ret;
marcel1691 1:2e29a33cd918 528 } else if ( ret == 0 ) {
marcel1691 1:2e29a33cd918 529 break;
marcel1691 1:2e29a33cd918 530 } else {
marcel1691 1:2e29a33cd918 531 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 532 ERR("Connection error (recv returned %d)", ret);
marcel1691 1:2e29a33cd918 533 *pReadLen = readLen;
marcel1691 1:2e29a33cd918 534 return HTTP_CONN;
marcel1691 1:2e29a33cd918 535 } else {
marcel1691 1:2e29a33cd918 536 break;
marcel1691 1:2e29a33cd918 537 }
marcel1691 1:2e29a33cd918 538 }
marcel1691 1:2e29a33cd918 539 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 540 break;
marcel1691 1:2e29a33cd918 541 }
marcel1691 1:2e29a33cd918 542 }
marcel1691 1:2e29a33cd918 543 DBG("Read %d bytes", readLen);
marcel1691 1:2e29a33cd918 544 buf[readLen] = '\0'; // DS makes it easier to see what's new.
marcel1691 1:2e29a33cd918 545 *pReadLen = readLen;
marcel1691 1:2e29a33cd918 546 return HTTP_OK;
marcel1691 1:2e29a33cd918 547 }
marcel1691 1:2e29a33cd918 548
marcel1691 1:2e29a33cd918 549 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
marcel1691 1:2e29a33cd918 550 {
marcel1691 1:2e29a33cd918 551 if(len == 0) {
marcel1691 1:2e29a33cd918 552 len = strlen(buf);
marcel1691 1:2e29a33cd918 553 }
marcel1691 1:2e29a33cd918 554 DBG("send(%s,%d)", buf, len);
marcel1691 1:2e29a33cd918 555 size_t writtenLen = 0;
marcel1691 1:2e29a33cd918 556
marcel1691 1:2e29a33cd918 557 if(!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 558 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 559 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 560 }
marcel1691 1:2e29a33cd918 561
marcel1691 1:2e29a33cd918 562 m_sock.set_blocking(false, m_timeout);
marcel1691 1:2e29a33cd918 563 int ret = m_sock.send_all(buf, len);
marcel1691 1:2e29a33cd918 564 if(ret > 0) {
marcel1691 1:2e29a33cd918 565 writtenLen += ret;
marcel1691 1:2e29a33cd918 566 } else if( ret == 0 ) {
marcel1691 1:2e29a33cd918 567 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 568 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 569 } else {
marcel1691 1:2e29a33cd918 570 ERR("Connection error (send returned %d)", ret);
marcel1691 1:2e29a33cd918 571 return HTTP_CONN;
marcel1691 1:2e29a33cd918 572 }
marcel1691 1:2e29a33cd918 573
marcel1691 1:2e29a33cd918 574 DBG("Written %d bytes", writtenLen);
marcel1691 1:2e29a33cd918 575 return HTTP_OK;
marcel1691 1:2e29a33cd918 576 }
marcel1691 1:2e29a33cd918 577
marcel1691 1:2e29a33cd918 578 HTTPResult HTTPClient::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
marcel1691 1:2e29a33cd918 579 {
marcel1691 1:2e29a33cd918 580 char* schemePtr = (char*) url;
marcel1691 1:2e29a33cd918 581 char* hostPtr = (char*) strstr(url, "://");
marcel1691 1:2e29a33cd918 582 if(hostPtr == NULL) {
marcel1691 1:2e29a33cd918 583 WARN("Could not find host");
marcel1691 1:2e29a33cd918 584 return HTTP_PARSE; //URL is invalid
marcel1691 1:2e29a33cd918 585 }
marcel1691 1:2e29a33cd918 586
marcel1691 1:2e29a33cd918 587 if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 588 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
marcel1691 1:2e29a33cd918 589 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 590 }
marcel1691 1:2e29a33cd918 591 memcpy(scheme, schemePtr, hostPtr - schemePtr);
marcel1691 1:2e29a33cd918 592 scheme[hostPtr - schemePtr] = '\0';
marcel1691 1:2e29a33cd918 593
marcel1691 1:2e29a33cd918 594 hostPtr+=3;
marcel1691 1:2e29a33cd918 595
marcel1691 1:2e29a33cd918 596 size_t hostLen = 0;
marcel1691 1:2e29a33cd918 597
marcel1691 1:2e29a33cd918 598 char* portPtr = strchr(hostPtr, ':');
marcel1691 1:2e29a33cd918 599 if( portPtr != NULL ) {
marcel1691 1:2e29a33cd918 600 hostLen = portPtr - hostPtr;
marcel1691 1:2e29a33cd918 601 portPtr++;
marcel1691 1:2e29a33cd918 602 if( sscanf(portPtr, "%hu", port) != 1) {
marcel1691 1:2e29a33cd918 603 WARN("Could not find port");
marcel1691 1:2e29a33cd918 604 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 605 }
marcel1691 1:2e29a33cd918 606 } else {
marcel1691 1:2e29a33cd918 607 *port=0;
marcel1691 1:2e29a33cd918 608 }
marcel1691 1:2e29a33cd918 609 char* pathPtr = strchr(hostPtr, '/');
marcel1691 1:2e29a33cd918 610 if( hostLen == 0 ) {
marcel1691 1:2e29a33cd918 611 hostLen = pathPtr - hostPtr;
marcel1691 1:2e29a33cd918 612 }
marcel1691 1:2e29a33cd918 613
marcel1691 1:2e29a33cd918 614 if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 615 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
marcel1691 1:2e29a33cd918 616 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 617 }
marcel1691 1:2e29a33cd918 618 memcpy(host, hostPtr, hostLen);
marcel1691 1:2e29a33cd918 619 host[hostLen] = '\0';
marcel1691 1:2e29a33cd918 620
marcel1691 1:2e29a33cd918 621 size_t pathLen;
marcel1691 1:2e29a33cd918 622 char* fragmentPtr = strchr(hostPtr, '#');
marcel1691 1:2e29a33cd918 623 if(fragmentPtr != NULL) {
marcel1691 1:2e29a33cd918 624 pathLen = fragmentPtr - pathPtr;
marcel1691 1:2e29a33cd918 625 } else {
marcel1691 1:2e29a33cd918 626 pathLen = strlen(pathPtr);
marcel1691 1:2e29a33cd918 627 }
marcel1691 1:2e29a33cd918 628
marcel1691 1:2e29a33cd918 629 if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 630 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
marcel1691 1:2e29a33cd918 631 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 632 }
marcel1691 1:2e29a33cd918 633 memcpy(path, pathPtr, pathLen);
marcel1691 1:2e29a33cd918 634 path[pathLen] = '\0';
marcel1691 1:2e29a33cd918 635
marcel1691 1:2e29a33cd918 636 return HTTP_OK;
marcel1691 1:2e29a33cd918 637 }
marcel1691 1:2e29a33cd918 638
marcel1691 1:2e29a33cd918 639 void HTTPClient::createauth (const char *user, const char *pwd, char *buf, int len)
marcel1691 1:2e29a33cd918 640 {
marcel1691 1:2e29a33cd918 641 char tmp[80];
marcel1691 1:2e29a33cd918 642
marcel1691 1:2e29a33cd918 643 snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
marcel1691 1:2e29a33cd918 644 base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
marcel1691 1:2e29a33cd918 645 }
marcel1691 1:2e29a33cd918 646
marcel1691 1:2e29a33cd918 647 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
marcel1691 1:2e29a33cd918 648 int HTTPClient::base64enc(const char *input, unsigned int length, char *output, int len)
marcel1691 1:2e29a33cd918 649 {
marcel1691 1:2e29a33cd918 650 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
marcel1691 1:2e29a33cd918 651 unsigned int c, c1, c2, c3;
marcel1691 1:2e29a33cd918 652
marcel1691 1:2e29a33cd918 653 if (len < ((((length-1)/3)+1)<<2)) return -1;
marcel1691 1:2e29a33cd918 654 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
marcel1691 1:2e29a33cd918 655 c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
marcel1691 1:2e29a33cd918 656 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
marcel1691 1:2e29a33cd918 657 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
marcel1691 1:2e29a33cd918 658
marcel1691 1:2e29a33cd918 659 c = ((c1 & 0xFC) >> 2);
marcel1691 1:2e29a33cd918 660 output[j+0] = base64[c];
marcel1691 1:2e29a33cd918 661 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
marcel1691 1:2e29a33cd918 662 output[j+1] = base64[c];
marcel1691 1:2e29a33cd918 663 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
marcel1691 1:2e29a33cd918 664 output[j+2] = (length>i+1)?base64[c]:'=';
marcel1691 1:2e29a33cd918 665 c = (c3 & 0x3F);
marcel1691 1:2e29a33cd918 666 output[j+3] = (length>i+2)?base64[c]:'=';
marcel1691 1:2e29a33cd918 667 }
marcel1691 1:2e29a33cd918 668 output[(((length-1)/3)+1)<<2] = '\0';
marcel1691 1:2e29a33cd918 669 return 0;
marcel1691 1:2e29a33cd918 670 }