Change the CHUNK_SIZE, KEY_SIZE and VALUE_SIZE
Dependents: CurrentWeatherData_W5500 EmailButton EmailButton HTTPClient_Weather ... more
Fork of HTTPClient 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 #if 0 00022 //Enable debug 00023 #include <cstdio> 00024 #define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 00025 #define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 00026 #define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 00027 00028 #else 00029 //Disable debug 00030 #define DBG(x, ...) 00031 #define WARN(x, ...) 00032 #define ERR(x, ...) 00033 00034 #endif 00035 00036 #define HTTP_PORT 80 00037 00038 #define OK 0 00039 00040 #define MIN(x,y) (((x)<(y))?(x):(y)) 00041 #define MAX(x,y) (((x)>(y))?(x):(y)) 00042 00043 //#define CHUNK_SIZE 256 00044 #define CHUNK_SIZE 1024 00045 00046 #define KEY_SIZE 64 00047 #define VALUE_SIZE 64 00048 00049 #include <cstring> 00050 00051 #include "HTTPClient.h" 00052 00053 HTTPClient::HTTPClient() : 00054 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0) 00055 { 00056 00057 } 00058 00059 HTTPClient::~HTTPClient() 00060 { 00061 00062 } 00063 00064 #if 0 00065 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification 00066 { 00067 m_basicAuthUser = user; 00068 m_basicAuthPassword = password; 00069 } 00070 #endif 00071 00072 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00073 { 00074 return connect(url, HTTP_GET, NULL, pDataIn, timeout); 00075 } 00076 00077 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00078 { 00079 HTTPText str(result, maxResultLen); 00080 return get(url, &str, timeout); 00081 } 00082 00083 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00084 { 00085 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00086 } 00087 00088 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00089 { 00090 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00091 } 00092 00093 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00094 { 00095 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout); 00096 } 00097 00098 00099 int HTTPClient::getHTTPResponseCode() 00100 { 00101 return m_httpResponseCode; 00102 } 00103 00104 #define CHECK_CONN_ERR(ret) \ 00105 do{ \ 00106 if(ret) { \ 00107 m_sock.close(); \ 00108 ERR("Connection error (%d)", ret); \ 00109 return HTTP_CONN; \ 00110 } \ 00111 } while(0) 00112 00113 #define PRTCL_ERR() \ 00114 do{ \ 00115 m_sock.close(); \ 00116 ERR("Protocol error"); \ 00117 return HTTP_PRTCL; \ 00118 } while(0) 00119 00120 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request 00121 { 00122 m_httpResponseCode = 0; //Invalidate code 00123 m_timeout = timeout; 00124 00125 pDataIn->writeReset(); 00126 if( pDataOut ) 00127 { 00128 pDataOut->readReset(); 00129 } 00130 00131 char scheme[8]; 00132 uint16_t port; 00133 char host[32]; 00134 char path[64]; 00135 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?) 00136 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); 00137 if(res != HTTP_OK) 00138 { 00139 ERR("parseURL returned %d", res); 00140 return res; 00141 } 00142 00143 if(port == 0) //TODO do handle HTTPS->443 00144 { 00145 port = 80; 00146 } 00147 00148 DBG("Scheme: %s", scheme); 00149 DBG("Host: %s", host); 00150 DBG("Port: %d", port); 00151 DBG("Path: %s", path); 00152 00153 //Connect 00154 DBG("Connecting socket to server"); 00155 int ret = m_sock.connect(host, port); 00156 if (ret < 0) 00157 { 00158 m_sock.close(); 00159 ERR("Could not connect"); 00160 return HTTP_CONN; 00161 } 00162 00163 //Send request 00164 DBG("Sending request"); 00165 char buf[CHUNK_SIZE]; 00166 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":""; 00167 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request 00168 ret = send(buf); 00169 if(ret) 00170 { 00171 m_sock.close(); 00172 ERR("Could not write request"); 00173 return HTTP_CONN; 00174 } 00175 00176 //Send all headers 00177 00178 //Send default headers 00179 DBG("Sending headers"); 00180 if( pDataOut != NULL ) 00181 { 00182 if( pDataOut->getIsChunked() ) 00183 { 00184 ret = send("Transfer-Encoding: chunked\r\n"); 00185 CHECK_CONN_ERR(ret); 00186 } 00187 else 00188 { 00189 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); 00190 ret = send(buf); 00191 CHECK_CONN_ERR(ret); 00192 } 00193 char type[48]; 00194 if( pDataOut->getDataType(type, 48) == HTTP_OK ) 00195 { 00196 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); 00197 ret = send(buf); 00198 CHECK_CONN_ERR(ret); 00199 } 00200 00201 //Send specific headers 00202 while( pDataOut->getHeader(buf, sizeof(buf) - 3) ) //must have space left for CRLF + 0 terminating char 00203 { 00204 size_t headerlen = strlen(buf); 00205 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n"); 00206 ret = send(buf); 00207 CHECK_CONN_ERR(ret); 00208 } 00209 } 00210 00211 //Send specific headers 00212 while( pDataIn->getHeader(buf, sizeof(buf) - 3) ) 00213 { 00214 size_t headerlen = strlen(buf); 00215 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n"); 00216 ret = send(buf); 00217 CHECK_CONN_ERR(ret); 00218 } 00219 00220 //Close headers 00221 DBG("Headers sent"); 00222 ret = send("\r\n"); 00223 CHECK_CONN_ERR(ret); 00224 00225 size_t trfLen; 00226 00227 //Send data (if available) 00228 if( pDataOut != NULL ) 00229 { 00230 DBG("Sending data"); 00231 while(true) 00232 { 00233 size_t writtenLen = 0; 00234 pDataOut->read(buf, CHUNK_SIZE, &trfLen); 00235 if( pDataOut->getIsChunked() ) 00236 { 00237 //Write chunk header 00238 char chunkHeader[16]; 00239 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding 00240 ret = send(chunkHeader); 00241 CHECK_CONN_ERR(ret); 00242 } 00243 else if( trfLen == 0 ) 00244 { 00245 break; 00246 } 00247 if( trfLen != 0 ) 00248 { 00249 ret = send(buf, trfLen); 00250 CHECK_CONN_ERR(ret); 00251 } 00252 00253 if( pDataOut->getIsChunked() ) 00254 { 00255 ret = send("\r\n"); //Chunk-terminating CRLF 00256 CHECK_CONN_ERR(ret); 00257 } 00258 else 00259 { 00260 writtenLen += trfLen; 00261 if( writtenLen >= pDataOut->getDataLen() ) 00262 { 00263 break; 00264 } 00265 } 00266 00267 if( trfLen == 0 ) 00268 { 00269 break; 00270 } 00271 } 00272 } 00273 00274 //Receive response 00275 DBG("Receiving response"); 00276 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes 00277 CHECK_CONN_ERR(ret); 00278 00279 buf[trfLen] = '\0'; 00280 00281 //Make sure we got the first response line 00282 char* crlfPtr = NULL; 00283 while( true ) 00284 { 00285 crlfPtr = strstr(buf, "\r\n"); 00286 if(crlfPtr == NULL) 00287 { 00288 if( trfLen < CHUNK_SIZE - 1 ) 00289 { 00290 size_t newTrfLen; 00291 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00292 trfLen += newTrfLen; 00293 buf[trfLen] = '\0'; 00294 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00295 CHECK_CONN_ERR(ret); 00296 continue; 00297 } 00298 else 00299 { 00300 PRTCL_ERR(); 00301 } 00302 } 00303 break; 00304 } 00305 00306 int crlfPos = crlfPtr - buf; 00307 buf[crlfPos] = '\0'; 00308 00309 //Parse HTTP response 00310 //if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) 00311 if(crlfPos > 13) 00312 { 00313 buf[13] = '\0'; 00314 } 00315 if( sscanf(buf, "HTTP/%*d.%*d %d", &m_httpResponseCode) != 1 ) //Kludge for newlib nano 00316 { 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 >= 300) ) 00323 { 00324 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 00325 WARN("Response code %d", m_httpResponseCode); 00326 PRTCL_ERR(); 00327 } 00328 00329 DBG("Reading headers"); 00330 00331 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00332 trfLen -= (crlfPos + 2); 00333 00334 00335 size_t recvContentLength = 0; 00336 bool recvChunked = false; 00337 bool recvLengthUnknown = true; 00338 //Now get headers 00339 while( true ) 00340 { 00341 crlfPtr = strstr(buf, "\r\n"); 00342 if(crlfPtr == NULL) 00343 { 00344 if( trfLen < CHUNK_SIZE - 1 ) 00345 { 00346 size_t newTrfLen; 00347 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00348 trfLen += newTrfLen; 00349 buf[trfLen] = '\0'; 00350 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00351 CHECK_CONN_ERR(ret); 00352 continue; 00353 } 00354 else 00355 { 00356 PRTCL_ERR(); 00357 } 00358 } 00359 00360 crlfPos = crlfPtr - buf; 00361 00362 if(crlfPos == 0) //End of headers 00363 { 00364 DBG("Headers read"); 00365 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well 00366 trfLen -= 2; 00367 break; 00368 } 00369 00370 buf[crlfPos] = '\0'; 00371 00372 char key[KEY_SIZE]; 00373 char value[VALUE_SIZE]; 00374 00375 memset(key, 0, KEY_SIZE); 00376 memset(value, 0, VALUE_SIZE); 00377 00378 //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); 00379 00380 int n = 0; 00381 00382 char* keyEnd = strchr(buf, ':'); 00383 if(keyEnd != NULL) 00384 { 00385 *keyEnd = '\0'; 00386 if(strlen(buf) < VALUE_SIZE) 00387 { 00388 strcpy(key, buf); 00389 n++; 00390 char* valueStart = keyEnd + 2; 00391 if( (valueStart - buf) < crlfPos ) 00392 { 00393 if(strlen(valueStart) < VALUE_SIZE) 00394 { 00395 strcpy(value, valueStart); 00396 n++; 00397 } 00398 } 00399 } 00400 } 00401 if ( n == 2 ) 00402 { 00403 DBG("Read header : %s: %s\n", key, value); 00404 if( !strcmp(key, "Content-Length") ) 00405 { 00406 sscanf(value, "%d", &recvContentLength); 00407 recvLengthUnknown = false; 00408 pDataIn->setDataLen(recvContentLength); 00409 } 00410 else if( !strcmp(key, "Transfer-Encoding") ) 00411 { 00412 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) 00413 { 00414 recvChunked = true; 00415 recvLengthUnknown = false; 00416 pDataIn->setIsChunked(true); 00417 } 00418 } 00419 else if( !strcmp(key, "Content-Type") ) 00420 { 00421 pDataIn->setDataType(value); 00422 } 00423 00424 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00425 trfLen -= (crlfPos + 2); 00426 00427 } 00428 else 00429 { 00430 ERR("Could not parse header"); 00431 PRTCL_ERR(); 00432 } 00433 00434 } 00435 00436 //Receive data 00437 DBG("Receiving data"); 00438 while(true) 00439 { 00440 size_t readLen = 0; 00441 00442 if( recvChunked ) 00443 { 00444 //Read chunk header 00445 bool foundCrlf; 00446 do 00447 { 00448 foundCrlf = false; 00449 crlfPos=0; 00450 buf[trfLen]=0; 00451 if(trfLen >= 2) 00452 { 00453 for(; crlfPos < trfLen - 2; crlfPos++) 00454 { 00455 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) 00456 { 00457 foundCrlf = true; 00458 break; 00459 } 00460 } 00461 } 00462 if(!foundCrlf) //Try to read more 00463 { 00464 if( trfLen < CHUNK_SIZE ) 00465 { 00466 size_t newTrfLen; 00467 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00468 trfLen += newTrfLen; 00469 CHECK_CONN_ERR(ret); 00470 continue; 00471 } 00472 else 00473 { 00474 PRTCL_ERR(); 00475 } 00476 } 00477 } while(!foundCrlf); 00478 buf[crlfPos] = '\0'; 00479 int n = sscanf(buf, "%x", &readLen); 00480 if(n!=1) 00481 { 00482 ERR("Could not read chunk length"); 00483 PRTCL_ERR(); 00484 } 00485 00486 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more 00487 trfLen -= (crlfPos + 2); 00488 00489 if( readLen == 0 ) 00490 { 00491 //Last chunk 00492 break; 00493 } 00494 } 00495 else 00496 { 00497 readLen = recvContentLength; 00498 } 00499 00500 DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen); 00501 00502 do 00503 { 00504 if(recvLengthUnknown ) 00505 { 00506 readLen = trfLen; 00507 } 00508 pDataIn->write(buf, MIN(trfLen, readLen)); 00509 if(!recvLengthUnknown) 00510 { 00511 if( trfLen > readLen ) 00512 { 00513 memmove(buf, &buf[readLen], trfLen - readLen); 00514 trfLen -= readLen; 00515 readLen = 0; 00516 } 00517 else 00518 { 00519 readLen -= trfLen; 00520 } 00521 } 00522 else 00523 { 00524 trfLen = 0; 00525 } 00526 00527 if(readLen || recvLengthUnknown) 00528 { 00529 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); 00530 if(recvLengthUnknown && (ret == HTTP_CLOSED)) 00531 { 00532 //Write and exit 00533 pDataIn->write(buf, trfLen); 00534 break; 00535 } 00536 CHECK_CONN_ERR(ret); 00537 if(recvLengthUnknown && (trfLen == 0)) 00538 { 00539 break; 00540 } 00541 } 00542 } while(readLen || recvLengthUnknown); 00543 00544 if( recvChunked ) 00545 { 00546 if(trfLen < 2) 00547 { 00548 size_t newTrfLen; 00549 //Read missing chars to find end of chunk 00550 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00551 CHECK_CONN_ERR(ret); 00552 trfLen += newTrfLen; 00553 } 00554 if( (buf[0] != '\r') || (buf[1] != '\n') ) 00555 { 00556 ERR("Format error"); 00557 PRTCL_ERR(); 00558 } 00559 memmove(buf, &buf[2], trfLen - 2); 00560 trfLen -= 2; 00561 } 00562 else 00563 { 00564 break; 00565 } 00566 00567 } 00568 00569 m_sock.close(); 00570 DBG("Completed HTTP transaction"); 00571 00572 return HTTP_OK; 00573 } 00574 00575 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure 00576 { 00577 DBG("Trying to read between %d and %d bytes", minLen, maxLen); 00578 size_t readLen = 0; 00579 00580 if(!m_sock.is_connected()) 00581 { 00582 WARN("Connection was closed by server"); 00583 return HTTP_CLOSED; //Connection was closed by server 00584 } 00585 00586 int ret; 00587 while(readLen < maxLen) 00588 { 00589 if(readLen < minLen) 00590 { 00591 DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen); 00592 m_sock.set_blocking(false, m_timeout); 00593 ret = m_sock.receive_all(buf + readLen, minLen - readLen); 00594 } 00595 else 00596 { 00597 DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen); 00598 m_sock.set_blocking(false, 0); 00599 ret = m_sock.receive(buf + readLen, maxLen - readLen); 00600 } 00601 00602 if( ret > 0) 00603 { 00604 readLen += ret; 00605 } 00606 else if( ret == 0 ) 00607 { 00608 break; 00609 } 00610 else 00611 { 00612 if(!m_sock.is_connected()) 00613 { 00614 ERR("Connection error (recv returned %d)", ret); 00615 *pReadLen = readLen; 00616 return HTTP_CONN; 00617 } 00618 else 00619 { 00620 break; 00621 } 00622 } 00623 00624 if(!m_sock.is_connected()) 00625 { 00626 break; 00627 } 00628 } 00629 DBG("Read %d bytes", readLen); 00630 *pReadLen = readLen; 00631 return HTTP_OK; 00632 } 00633 00634 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure 00635 { 00636 if(len == 0) 00637 { 00638 len = strlen(buf); 00639 } 00640 DBG("Trying to write %d bytes", len); 00641 size_t writtenLen = 0; 00642 00643 if(!m_sock.is_connected()) 00644 { 00645 WARN("Connection was closed by server"); 00646 return HTTP_CLOSED; //Connection was closed by server 00647 } 00648 00649 m_sock.set_blocking(false, m_timeout); 00650 int ret = m_sock.send_all(buf, len); 00651 if(ret > 0) 00652 { 00653 writtenLen += ret; 00654 } 00655 else if( ret == 0 ) 00656 { 00657 WARN("Connection was closed by server"); 00658 return HTTP_CLOSED; //Connection was closed by server 00659 } 00660 else 00661 { 00662 ERR("Connection error (send returned %d)", ret); 00663 return HTTP_CONN; 00664 } 00665 00666 DBG("Written %d bytes", writtenLen); 00667 return HTTP_OK; 00668 } 00669 00670 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 00671 { 00672 char* schemePtr = (char*) url; 00673 char* hostPtr = (char*) strstr(url, "://"); 00674 if(hostPtr == NULL) 00675 { 00676 WARN("Could not find host"); 00677 return HTTP_PARSE; //URL is invalid 00678 } 00679 00680 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char 00681 { 00682 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); 00683 return HTTP_PARSE; 00684 } 00685 memcpy(scheme, schemePtr, hostPtr - schemePtr); 00686 scheme[hostPtr - schemePtr] = '\0'; 00687 00688 hostPtr+=3; 00689 00690 size_t hostLen = 0; 00691 00692 char* portPtr = strchr(hostPtr, ':'); 00693 if( portPtr != NULL ) 00694 { 00695 hostLen = portPtr - hostPtr; 00696 portPtr++; 00697 if( sscanf(portPtr, "%hu", port) != 1) 00698 { 00699 WARN("Could not find port"); 00700 return HTTP_PARSE; 00701 } 00702 } 00703 else 00704 { 00705 *port=0; 00706 } 00707 char* pathPtr = strchr(hostPtr, '/'); 00708 if( hostLen == 0 ) 00709 { 00710 hostLen = pathPtr - hostPtr; 00711 } 00712 00713 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char 00714 { 00715 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); 00716 return HTTP_PARSE; 00717 } 00718 memcpy(host, hostPtr, hostLen); 00719 host[hostLen] = '\0'; 00720 00721 size_t pathLen; 00722 char* fragmentPtr = strchr(hostPtr, '#'); 00723 if(fragmentPtr != NULL) 00724 { 00725 pathLen = fragmentPtr - pathPtr; 00726 } 00727 else 00728 { 00729 pathLen = strlen(pathPtr); 00730 } 00731 00732 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char 00733 { 00734 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); 00735 return HTTP_PARSE; 00736 } 00737 memcpy(path, pathPtr, pathLen); 00738 path[pathLen] = '\0'; 00739 00740 return HTTP_OK; 00741 }
Generated on Tue Jul 12 2022 21:42:25 by 1.7.2