void cg_http_packet_read_headers(CgHttpPacket *httpPkt, CgSocket *sock, char *lineBuf, size_t lineBufSize) { CgStringTokenizer *strTok; CgHttpHeader *header; ssize_t readLen; char *name, *value; cg_log_debug_l4("Entering...\n"); while (1) { readLen = cg_socket_readline(sock, lineBuf, lineBufSize); if (readLen <= 2) break; name = NULL; value = NULL; strTok = cg_string_tokenizer_new(lineBuf, CG_HTTP_HEADERLINE_DELIM); if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) name = cg_string_tokenizer_nexttoken(strTok); if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { value = cg_string_tokenizer_nextalltoken(strTok); cg_strrtrim(value, CG_HTTP_HEADERLINE_DELIM, cg_strlen(CG_HTTP_HEADERLINE_DELIM)); } if (0 < cg_strlen(name)) { if (cg_strlen(value) == 0) value = ""; header = cg_http_header_new(); cg_http_header_setname(header, name); cg_http_header_setvalue(header, value); cg_http_packet_addheader(httpPkt, header); } cg_string_tokenizer_delete(strTok); } cg_log_debug_l4("Leaving...\n"); }
CgXmlNode *cg_soap_request_getbodynode(CgSoapRequest *soapReq) { CgXmlNode *envNode; CgXmlNode *bodyNode = NULL; CgXmlAttribute *attr; char *name; CgStringTokenizer *tok; char *nsPrefix; size_t bodyLen; char *body; cg_log_debug_l4("Entering...\n"); envNode = cg_soap_request_getenvelopenode(soapReq); if (envNode == NULL) return NULL; if (cg_xml_node_haschildnodes(envNode) == FALSE) return NULL; /* We cannot assume the namespace prefix for Body is 's'. According to spec, it could be anything... */ for (attr = cg_xml_node_getattributes(envNode); attr != NULL; attr = cg_xml_attribute_next(attr)) { /* First, find the namespace declaration attribute. */ /* Note: We must take a copy of the attr name. Tokenizer doesn't do it (by default) */ name = cg_strdup( cg_xml_attribute_getname(attr) ); tok = cg_string_tokenizer_new(name, ":"); nsPrefix = cg_string_tokenizer_nexttoken(tok); if ( -1 != cg_strstr(nsPrefix, "xmlns")) { /* This attribute is a namespace declaration. Check is it the one defined for SOAP. */ if (cg_strcmp(cg_xml_attribute_getvalue(attr), CG_SOAP_XMLNS_URL) == 0) { /* This namespace declaration is correct. Use it to find the body node... */ if (cg_string_tokenizer_hasmoretoken(tok)) { /* There is a prefix */ nsPrefix = cg_string_tokenizer_nexttoken(tok); bodyLen = cg_strlen(nsPrefix) + cg_strlen(CG_SOAP_DELIM) + cg_strlen(CG_SOAP_BODY) + 1; /* +1 for trailing '\0'*/ body = (char*)malloc(bodyLen); if ( NULL == body ) { cg_log_debug_s("Memory allocation failure!\n"); return NULL; } #if defined(HAVE_SNPRINTF) snprintf(body, bodyLen, "%s%s%s", nsPrefix, CG_SOAP_DELIM, CG_SOAP_BODY); #else sprintf(body, "%s%s%s", nsPrefix, CG_SOAP_DELIM, CG_SOAP_BODY); #endif bodyNode = cg_xml_node_getchildnode(envNode, body); free(body); } else { /* No prefix */ bodyNode = cg_xml_node_getchildnode(envNode, CG_SOAP_BODY); } /* Free memory before leaving the loop */ cg_string_tokenizer_delete(tok); free(name); break; } } cg_string_tokenizer_delete(tok); free(name); } cg_log_debug_l4("Leaving...\n"); return bodyNode; }
BOOL cg_http_request_read(CgHttpRequest *httpReq, CgSocket *sock) { char lineBuf[CG_HTTP_READLINE_BUFSIZE]; CgStringTokenizer *strTok; int readLen; CgNetURI *uri = NULL; BOOL failed = FALSE; cg_log_debug_l4("Entering...\n"); cg_http_request_clear(httpReq); /* If first character(s) is \n or \r\n we ignore it(them) and read second line. */ do { readLen = cg_socket_readline(sock, lineBuf, sizeof(lineBuf)); } while (readLen >= 1 && readLen <=2); if (readLen <= 0) return FALSE; strTok = cg_string_tokenizer_new(lineBuf, CG_HTTP_STATUSLINE_DELIM); if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) cg_http_request_setmethod(httpReq, cg_string_tokenizer_nexttoken(strTok)); else failed = TRUE; if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) cg_http_request_seturi(httpReq, cg_string_tokenizer_nexttoken(strTok)); else failed = TRUE; if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) cg_http_request_setversion(httpReq, cg_string_tokenizer_nexttoken(strTok)); else failed = TRUE; cg_string_tokenizer_delete(strTok); if (failed == TRUE) return FALSE; /* We could do some further validation for the HTTP-request? */ /* Change URI to be relative (absolute not needed anymore) */ uri = cg_net_uri_new(); if (uri != NULL) { cg_net_uri_set(uri, cg_http_request_geturi(httpReq)); if (cg_net_uri_isabsolute(uri) == TRUE && cg_net_uri_getrequest(uri) != NULL) { cg_http_request_seturi(httpReq, cg_net_uri_getrequest(uri)); } cg_net_uri_delete(uri); uri = NULL; } /* Read headers */ cg_http_packet_clear((CgHttpPacket *)httpReq); cg_http_packet_read_headers((CgHttpPacket *)httpReq, sock, lineBuf, sizeof(lineBuf)); /* HTTP-request must have Content-Length or Transfer-Encoding header in order to have body */ if (cg_http_packet_hasheader((CgHttpPacket *)httpReq, CG_HTTP_CONTENT_LENGTH) || cg_http_packet_hasheader((CgHttpPacket *)httpReq, CG_HTTP_TRANSFER_ENCODING)) cg_http_packet_read_body((CgHttpPacket *)httpReq, sock, lineBuf, sizeof(lineBuf)); cg_log_debug_l4("Leaving...\n"); return TRUE; }
/** * Callback function for CURL to read each HTTP header line * CgStringTokenizer might have been a viable choice to do the parsing * of various fields. Then again, it would not have read correctly a * header line with, for example, the time (because of multiple use of colons): * Foo: 12:34:56 EEST DST */ static size_t cg_http_request_header_callback(void *ptr, size_t size, size_t nmemb, void *stream) { char* headerLine = NULL; char* name = NULL; char* value = NULL; CgStringTokenizer* strTok = NULL; CgHttpResponse* httpRes = NULL; int head = 0; int tail = 0; cg_log_debug_l4("Entering...\n"); if (stream == NULL || ptr == NULL) { return 0; } httpRes = (CgHttpResponse*) stream; headerLine = (char*) ptr; /* Read header items */ if (cg_strncmp(headerLine, CG_HTTP_VER11, cg_strlen(CG_HTTP_VER11)) == 0 || cg_strncmp(headerLine, CG_HTTP_VER10, cg_strlen(CG_HTTP_VER10)) == 0) { /* <HTTP/version> <status code> <reason phrase> */ strTok = cg_string_tokenizer_new(headerLine, CG_HTTP_STATUSLINE_DELIM); if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { cg_http_response_setversion(httpRes, cg_string_tokenizer_nexttoken(strTok)); } if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { cg_http_response_setstatuscode(httpRes, atoi(cg_string_tokenizer_nexttoken(strTok))); } if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { value = cg_string_tokenizer_nextalltoken(strTok); cg_strrtrim(value, CG_HTTP_STATUSLINE_DELIM, cg_strlen(CG_HTTP_STATUSLINE_DELIM)); cg_http_response_setreasonphrase(httpRes, value); } cg_string_tokenizer_delete(strTok); } else { /* Find the header delimiter */ for (head = 0; head < size * nmemb; head++) { if (headerLine[head] == ':') { break; } } /* Unable to find a colon, this is not a valid header line */ if (head <= 0 || head >= (size * nmemb) - 1) { return size * nmemb; } /* Take the header name */ name = (char*) malloc(head + 1); if ( NULL == name ) { cg_log_debug_s("Memory allocation failure!\n"); return 0; } memcpy(name, headerLine, head); name[head] = '\0'; /* Skip colon and space(s) */ for (head++; head < size * nmemb; head++) { if (headerLine[head] != 0x20) { break; } } /* Unable to find anything sensible anymore */ if (head >= (size * nmemb) - 1) { return size * nmemb; } /* Find the end of the actual value, without CRLF */ for (tail = size * nmemb; tail > 0; tail --) { if (headerLine[tail] == '\r') { break; } else if (headerLine[tail] == '\n') { if (tail > 0 && headerLine[tail - 1] == '\r') { tail--; break; } } } /* Unable to find CRLF */ if (tail <= head) { free(name); return size * nmemb; } /* Take the header value */ value = (char*) malloc(tail - head + 1); if ( NULL == value ) { cg_log_debug_s("Memory allocation failure!\n"); return 0; } memcpy(value, headerLine + head, tail - head); value[tail - head] = '\0'; /* Set the header value to the response */ cg_http_response_setheadervalue(httpRes, name, value); free(name); free(value); } return size * nmemb; cg_log_debug_l4("Leaving...\n"); }