Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetInterface MbedJSONValue NTPClient mbed-rtos mbed
Fork of SunriseSunset by
HTTPClient.cpp
00001 /* HTTPClient.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 //Debug is disabled by default 00021 //#define DEBUG "HTCL" 00022 #include <cstdio> 00023 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00024 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00025 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00026 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00027 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00028 #else 00029 #define DBG(x, ...) 00030 #define WARN(x, ...) 00031 #define ERR(x, ...) 00032 #define INFO(x, ...) 00033 #endif 00034 00035 //#define HTTP_PORT 80 00036 00037 #define OK 0 00038 00039 #define MIN(x,y) (((x)<(y))?(x):(y)) 00040 #define MAX(x,y) (((x)>(y))?(x):(y)) 00041 00042 #define CHUNK_SIZE 256 00043 #define MAXLEN_VALUE 120 /* Max URL and Max Value for Name:Value */ 00044 00045 #include <cstring> 00046 00047 #include "HTTPClient.h" 00048 00049 HTTPClient::HTTPClient() : 00050 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), 00051 m_nCustomHeaders(0), m_httpResponseCode(0), 00052 m_maxredirections(1), m_location(NULL) 00053 { 00054 00055 } 00056 00057 HTTPClient::~HTTPClient() 00058 { 00059 00060 } 00061 00062 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification 00063 { 00064 #if 1 00065 if (m_basicAuthUser) 00066 free(m_basicAuthUser); 00067 m_basicAuthUser = (char *)malloc(strlen(user)+1); 00068 strcpy(m_basicAuthUser, user); 00069 if (m_basicAuthPassword) 00070 free(m_basicAuthPassword); 00071 m_basicAuthPassword = (char *)malloc(strlen(password)+1); 00072 strcpy(m_basicAuthPassword, password); 00073 #else 00074 m_basicAuthUser = user; 00075 m_basicAuthPassword = password; 00076 #endif 00077 } 00078 00079 void HTTPClient::customHeaders(const char **headers, size_t pairs) 00080 { 00081 m_customHeaders = headers; 00082 m_nCustomHeaders = pairs; 00083 } 00084 00085 00086 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00087 { 00088 return connect(url, HTTP_GET, NULL, pDataIn, timeout); 00089 } 00090 00091 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00092 { 00093 HTTPText str(result, maxResultLen); 00094 return get(url, &str, timeout); 00095 } 00096 00097 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00098 { 00099 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00100 } 00101 00102 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00103 { 00104 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00105 } 00106 00107 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00108 { 00109 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout); 00110 } 00111 00112 00113 int HTTPClient::getHTTPResponseCode() 00114 { 00115 return m_httpResponseCode; 00116 } 00117 00118 void HTTPClient::setMaxRedirections(int i) 00119 { 00120 if (i < 1) 00121 i = 1; 00122 m_maxredirections = i; 00123 } 00124 00125 #define CHECK_CONN_ERR(ret) \ 00126 do{ \ 00127 if(ret) { \ 00128 m_sock.close(); \ 00129 ERR("Connection error (%d)", ret); \ 00130 return HTTP_CONN; \ 00131 } \ 00132 } while(0) 00133 00134 #define PRTCL_ERR() \ 00135 do{ \ 00136 m_sock.close(); \ 00137 ERR("Protocol error"); \ 00138 return HTTP_PRTCL; \ 00139 } while(0) 00140 00141 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request 00142 { 00143 m_httpResponseCode = 0; //Invalidate code 00144 m_timeout = timeout; 00145 00146 pDataIn->writeReset(); 00147 if( pDataOut ) { 00148 pDataOut->readReset(); 00149 } 00150 00151 char scheme[8]; 00152 uint16_t port; 00153 char host[32]; 00154 char path[MAXLEN_VALUE]; 00155 size_t recvContentLength = 0; 00156 bool recvChunked = false; 00157 int crlfPos = 0; 00158 char buf[CHUNK_SIZE]; 00159 size_t trfLen; 00160 int ret = 0; 00161 00162 int maxRedirect = m_maxredirections; 00163 00164 while (maxRedirect--) { 00165 bool takeRedirect = false; 00166 00167 INFO("parse: [%s]", url); 00168 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?) 00169 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); 00170 if(res != HTTP_OK) { 00171 ERR("parseURL returned %d", res); 00172 return res; 00173 } 00174 00175 if(port == 0) { //TODO do handle HTTPS->443 00176 port = 80; 00177 } 00178 00179 DBG("Scheme: %s", scheme); 00180 DBG("Host: %s", host); 00181 DBG("Port: %d", port); 00182 DBG("Path: %s", path); 00183 00184 //Connect 00185 DBG("Connecting socket to server"); 00186 ret = m_sock.connect(host, port); 00187 if (ret < 0) { 00188 m_sock.close(); 00189 ERR("Could not connect"); 00190 return HTTP_CONN; 00191 } 00192 00193 //Send request 00194 DBG("Sending request"); 00195 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":""; 00196 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 00197 INFO(" buf{%s}", buf); 00198 ret = send(buf); 00199 if (ret) { 00200 m_sock.close(); 00201 ERR("Could not write request"); 00202 return HTTP_CONN; 00203 } 00204 00205 // send authorization 00206 INFO("send auth (if defined)"); 00207 if (m_basicAuthUser && m_basicAuthPassword) { 00208 strcpy(buf, "Authorization: Basic "); 00209 createauth(m_basicAuthUser, m_basicAuthPassword, buf+strlen(buf), sizeof(buf)-strlen(buf)); 00210 strcat(buf, "\r\n"); 00211 INFO(" (%s,%s) => (%s)", m_basicAuthUser, m_basicAuthPassword, buf); 00212 ret = send(buf); 00213 INFO(" ret = %d", ret); 00214 if(ret) { 00215 m_sock.close(); 00216 ERR("Could not write request"); 00217 return HTTP_CONN; 00218 } 00219 } 00220 00221 //Send all headers 00222 INFO("Send custom header(s) %d (if any)", m_nCustomHeaders); 00223 for (size_t nh = 0; nh < m_nCustomHeaders * 2; nh+=2) { 00224 INFO("hdr[%d] %s:", nh, m_customHeaders[nh]); 00225 INFO(" %s", m_customHeaders[nh+1]); 00226 snprintf(buf, sizeof(buf), "%s: %s\r\n", m_customHeaders[nh], m_customHeaders[nh+1]); 00227 ret = send(buf); 00228 if (ret) { 00229 ERR("closing"); 00230 wait_ms(50); 00231 m_sock.close(); 00232 ERR("Could not write request"); 00233 return HTTP_CONN; 00234 } 00235 INFO(" hdr %d", ret); 00236 } 00237 00238 //Send default headers 00239 DBG("Sending headers"); 00240 if( pDataOut != NULL ) { 00241 if( pDataOut->getIsChunked() ) { 00242 ret = send("Transfer-Encoding: chunked\r\n"); 00243 CHECK_CONN_ERR(ret); 00244 } else { 00245 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); 00246 ret = send(buf); 00247 CHECK_CONN_ERR(ret); 00248 } 00249 char type[48]; 00250 if( pDataOut->getDataType(type, 48) == HTTP_OK ) { 00251 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); 00252 ret = send(buf); 00253 CHECK_CONN_ERR(ret); 00254 } 00255 } 00256 00257 //Close headers 00258 DBG("Headers sent"); 00259 ret = send("\r\n"); 00260 CHECK_CONN_ERR(ret); 00261 00262 //Send data (if available) 00263 if( pDataOut != NULL ) { 00264 DBG("Sending data"); 00265 while(true) { 00266 size_t writtenLen = 0; 00267 pDataOut->read(buf, CHUNK_SIZE, &trfLen); 00268 if( pDataOut->getIsChunked() ) { 00269 //Write chunk header 00270 char chunkHeader[16]; 00271 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding 00272 ret = send(chunkHeader); 00273 CHECK_CONN_ERR(ret); 00274 } else if( trfLen == 0 ) { 00275 break; 00276 } 00277 if( trfLen != 0 ) { 00278 ret = send(buf, trfLen); 00279 CHECK_CONN_ERR(ret); 00280 } 00281 00282 if( pDataOut->getIsChunked() ) { 00283 ret = send("\r\n"); //Chunk-terminating CRLF 00284 CHECK_CONN_ERR(ret); 00285 } else { 00286 writtenLen += trfLen; 00287 if( writtenLen >= pDataOut->getDataLen() ) { 00288 break; 00289 } 00290 } 00291 00292 if( trfLen == 0 ) { 00293 break; 00294 } 00295 } 00296 00297 } 00298 00299 //Receive response 00300 DBG("Receiving response"); 00301 //ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes 00302 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); // recommended by Rob Noble to avoid timeout wait 00303 CHECK_CONN_ERR(ret); 00304 buf[trfLen] = '\0'; 00305 INFO("Received \r\n(%s\r\n)", buf); 00306 00307 char* crlfPtr = strstr(buf, "\r\n"); 00308 if( crlfPtr == NULL) { 00309 PRTCL_ERR(); 00310 } 00311 00312 crlfPos = crlfPtr - buf; 00313 buf[crlfPos] = '\0'; 00314 00315 //Parse HTTP response 00316 if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) { 00317 //Cannot match string, error 00318 ERR("Not a correct HTTP answer : {%s}\n", buf); 00319 PRTCL_ERR(); 00320 } 00321 00322 if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 400) ) { 00323 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 00324 WARN("Response code %d", m_httpResponseCode); 00325 PRTCL_ERR(); 00326 } 00327 00328 DBG("Reading headers"); 00329 00330 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00331 trfLen -= (crlfPos + 2); 00332 00333 recvContentLength = 0; 00334 recvChunked = false; 00335 //Now get headers 00336 while( true ) { 00337 crlfPtr = strstr(buf, "\r\n"); 00338 if(crlfPtr == NULL) { 00339 if( trfLen < CHUNK_SIZE - 1 ) { 00340 size_t newTrfLen = 0; 00341 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00342 trfLen += newTrfLen; 00343 buf[trfLen] = '\0'; 00344 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00345 CHECK_CONN_ERR(ret); 00346 continue; 00347 } else { 00348 PRTCL_ERR(); 00349 } 00350 } 00351 00352 crlfPos = crlfPtr - buf; 00353 00354 if(crlfPos == 0) { //End of headers 00355 DBG("Headers read"); 00356 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well 00357 trfLen -= 2; 00358 break; 00359 } 00360 00361 buf[crlfPos] = '\0'; 00362 00363 char key[36]; 00364 char value[MAXLEN_VALUE]; 00365 00366 key[35] = '\0'; 00367 value[MAXLEN_VALUE - 1] = '\0'; 00368 00369 int n = sscanf(buf, "%35[^:]: %119[^\r\n]", key, value); 00370 if ( n == 2 ) { 00371 DBG("Read header : %s: %s", key, value); 00372 if( !strcmp(key, "Content-Length") ) { 00373 sscanf(value, "%d", &recvContentLength); 00374 pDataIn->setDataLen(recvContentLength); 00375 } else if( !strcmp(key, "Transfer-Encoding") ) { 00376 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) { 00377 recvChunked = true; 00378 pDataIn->setIsChunked(true); 00379 } 00380 } else if( !strcmp(key, "Content-Type") ) { 00381 pDataIn->setDataType(value); 00382 } else if ( !strcmp(key, "Location") ) { 00383 if (m_location) 00384 free(m_location); 00385 m_location = (char *)malloc(strlen(value)+1); 00386 if (m_location) { 00387 strcpy(m_location,value); 00388 url = m_location; 00389 INFO("Following redirect[%d] to [%s]", maxRedirect, url); 00390 m_sock.close(); 00391 takeRedirect = true; 00392 break; // exit the while(true) header to follow the redirect 00393 } 00394 } 00395 00396 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00397 trfLen -= (crlfPos + 2); 00398 } else { 00399 ERR("Could not parse header"); 00400 PRTCL_ERR(); 00401 } 00402 00403 } // while(true) // get headers 00404 if (!takeRedirect) 00405 break; 00406 } // while (maxRedirect) 00407 00408 //Receive data 00409 DBG("Receiving data"); 00410 while(true) { 00411 size_t readLen = 0; 00412 00413 if( recvChunked ) { 00414 //Read chunk header 00415 bool foundCrlf; 00416 do { 00417 foundCrlf = false; 00418 crlfPos=0; 00419 buf[trfLen]=0; 00420 if(trfLen >= 2) { 00421 for(; crlfPos < trfLen - 2; crlfPos++) { 00422 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) { 00423 foundCrlf = true; 00424 break; 00425 } 00426 } 00427 } 00428 if(!foundCrlf) { //Try to read more 00429 if( trfLen < CHUNK_SIZE ) { 00430 size_t newTrfLen = 0; 00431 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00432 trfLen += newTrfLen; 00433 CHECK_CONN_ERR(ret); 00434 continue; 00435 } else { 00436 PRTCL_ERR(); 00437 } 00438 } 00439 } while(!foundCrlf); 00440 buf[crlfPos] = '\0'; 00441 int n = sscanf(buf, "%x", &readLen); 00442 if(n!=1) { 00443 ERR("Could not read chunk length"); 00444 PRTCL_ERR(); 00445 } 00446 00447 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more 00448 trfLen -= (crlfPos + 2); 00449 00450 if( readLen == 0 ) { 00451 //Last chunk 00452 break; 00453 } 00454 } else { 00455 readLen = recvContentLength; 00456 } 00457 00458 DBG("Retrieving %d bytes", readLen); 00459 00460 do { 00461 INFO("write %d,%d: %s", trfLen, readLen, buf); 00462 pDataIn->write(buf, MIN(trfLen, readLen)); 00463 if( trfLen > readLen ) { 00464 memmove(buf, &buf[readLen], trfLen - readLen); 00465 trfLen -= readLen; 00466 readLen = 0; 00467 } else { 00468 readLen -= trfLen; 00469 } 00470 00471 if(readLen) { 00472 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); 00473 CHECK_CONN_ERR(ret); 00474 } 00475 } while(readLen); 00476 00477 if( recvChunked ) { 00478 if(trfLen < 2) { 00479 size_t newTrfLen; 00480 //Read missing chars to find end of chunk 00481 INFO("read chunk"); 00482 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00483 CHECK_CONN_ERR(ret); 00484 trfLen += newTrfLen; 00485 } 00486 if( (buf[0] != '\r') || (buf[1] != '\n') ) { 00487 ERR("Format error"); 00488 PRTCL_ERR(); 00489 } 00490 memmove(buf, &buf[2], trfLen - 2); 00491 trfLen -= 2; 00492 } else { 00493 break; 00494 } 00495 00496 } 00497 00498 m_sock.close(); 00499 DBG("Completed HTTP transaction"); 00500 00501 return HTTP_OK; 00502 } 00503 00504 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure 00505 { 00506 DBG("Trying to read between %d and %d bytes", minLen, maxLen); 00507 size_t readLen = 0; 00508 00509 if (!m_sock.is_connected()) { 00510 WARN("Connection was closed by server"); 00511 return HTTP_CLOSED; //Connection was closed by server 00512 } 00513 00514 int ret; 00515 while (readLen < maxLen) { 00516 if (readLen < minLen) { 00517 DBG("Trying to read at most %4d bytes [Blocking] %d,%d", minLen - readLen, minLen, readLen); 00518 m_sock.set_blocking(false, m_timeout); 00519 ret = m_sock.receive_all(buf + readLen, minLen - readLen); 00520 } else { 00521 DBG("Trying to read at most %4d bytes [Not blocking] %d,%d", maxLen - readLen, maxLen, readLen); 00522 m_sock.set_blocking(false, 0); 00523 ret = m_sock.receive(buf + readLen, maxLen - readLen); 00524 } 00525 00526 if (ret > 0) { 00527 readLen += ret; 00528 } else if ( ret == 0 ) { 00529 break; 00530 } else { 00531 if (!m_sock.is_connected()) { 00532 ERR("Connection error (recv returned %d)", ret); 00533 *pReadLen = readLen; 00534 return HTTP_CONN; 00535 } else { 00536 break; 00537 } 00538 } 00539 if (!m_sock.is_connected()) { 00540 break; 00541 } 00542 } 00543 DBG("Read %d bytes", readLen); 00544 buf[readLen] = '\0'; // DS makes it easier to see what's new. 00545 *pReadLen = readLen; 00546 return HTTP_OK; 00547 } 00548 00549 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure 00550 { 00551 if(len == 0) { 00552 len = strlen(buf); 00553 } 00554 DBG("send(%s,%d)", buf, len); 00555 size_t writtenLen = 0; 00556 00557 if(!m_sock.is_connected()) { 00558 WARN("Connection was closed by server"); 00559 return HTTP_CLOSED; //Connection was closed by server 00560 } 00561 00562 m_sock.set_blocking(false, m_timeout); 00563 int ret = m_sock.send_all(buf, len); 00564 if(ret > 0) { 00565 writtenLen += ret; 00566 } else if( ret == 0 ) { 00567 WARN("Connection was closed by server"); 00568 return HTTP_CLOSED; //Connection was closed by server 00569 } else { 00570 ERR("Connection error (send returned %d)", ret); 00571 return HTTP_CONN; 00572 } 00573 00574 DBG("Written %d bytes", writtenLen); 00575 return HTTP_OK; 00576 } 00577 00578 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 00579 { 00580 char* schemePtr = (char*) url; 00581 char* hostPtr = (char*) strstr(url, "://"); 00582 if(hostPtr == NULL) { 00583 WARN("Could not find host"); 00584 return HTTP_PARSE; //URL is invalid 00585 } 00586 00587 if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char 00588 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); 00589 return HTTP_PARSE; 00590 } 00591 memcpy(scheme, schemePtr, hostPtr - schemePtr); 00592 scheme[hostPtr - schemePtr] = '\0'; 00593 00594 hostPtr+=3; 00595 00596 size_t hostLen = 0; 00597 00598 char* portPtr = strchr(hostPtr, ':'); 00599 if( portPtr != NULL ) { 00600 hostLen = portPtr - hostPtr; 00601 portPtr++; 00602 if( sscanf(portPtr, "%hu", port) != 1) { 00603 WARN("Could not find port"); 00604 return HTTP_PARSE; 00605 } 00606 } else { 00607 *port=0; 00608 } 00609 char* pathPtr = strchr(hostPtr, '/'); 00610 if( hostLen == 0 ) { 00611 hostLen = pathPtr - hostPtr; 00612 } 00613 00614 if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char 00615 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); 00616 return HTTP_PARSE; 00617 } 00618 memcpy(host, hostPtr, hostLen); 00619 host[hostLen] = '\0'; 00620 00621 size_t pathLen; 00622 char* fragmentPtr = strchr(hostPtr, '#'); 00623 if(fragmentPtr != NULL) { 00624 pathLen = fragmentPtr - pathPtr; 00625 } else { 00626 pathLen = strlen(pathPtr); 00627 } 00628 00629 if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char 00630 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); 00631 return HTTP_PARSE; 00632 } 00633 memcpy(path, pathPtr, pathLen); 00634 path[pathLen] = '\0'; 00635 00636 return HTTP_OK; 00637 } 00638 00639 void HTTPClient::createauth (const char *user, const char *pwd, char *buf, int len) 00640 { 00641 char tmp[80]; 00642 00643 snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd); 00644 base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf)); 00645 } 00646 00647 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00648 int HTTPClient::base64enc(const char *input, unsigned int length, char *output, int len) 00649 { 00650 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00651 unsigned int c, c1, c2, c3; 00652 00653 if (len < ((((length-1)/3)+1)<<2)) return -1; 00654 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) { 00655 c1 = ((((unsigned char)*((unsigned char *)&input[i])))); 00656 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0; 00657 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0; 00658 00659 c = ((c1 & 0xFC) >> 2); 00660 output[j+0] = base64[c]; 00661 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4); 00662 output[j+1] = base64[c]; 00663 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6); 00664 output[j+2] = (length>i+1)?base64[c]:'='; 00665 c = (c3 & 0x3F); 00666 output[j+3] = (length>i+2)?base64[c]:'='; 00667 } 00668 output[(((length-1)/3)+1)<<2] = '\0'; 00669 return 0; 00670 }
Generated on Sun Jul 17 2022 01:08:53 by
1.7.2
