#include "UDPTCPNetwork.h" #include #include #include #include #include #include WebRequestBuffer::WebRequestBuffer () { buffer_pos_data = -1; buffer_size = 0; buffer_ptr = NULL; buffer_len = 0; } WebRequestBuffer::~WebRequestBuffer () { if (buffer_ptr) { free (buffer_ptr); buffer_ptr = NULL; buffer_size = 0; buffer_len = 0; buffer_pos_data = -1; } } /// @brief add text to buffer /// @param buffer /// @param len /// @return 0 on error, 1 on success int WebRequestBuffer::AddBuffer (char *buffer, int len) { // // if needed allocate enought buffer, to the next kB if (buffer_ptr == NULL || buffer_size <= buffer_len+len) { buffer_size = 1024 * (1 + ((buffer_len + len) / 1024)); if (buffer_ptr == NULL) buffer_ptr = (char*) malloc (buffer_size); else buffer_ptr = (char*) realloc (buffer_ptr, buffer_size); } if (buffer_ptr == NULL || buffer_size < buffer_len+len) { fprintf (stderr, "%s:%d could not allocate enought memory. buffer_size:%d buffer_len+len:%d \n", __FILE__, __LINE__, buffer_size, buffer_len + len); return 0; } memcpy (buffer_ptr + buffer_len, buffer, len); buffer_len += len; buffer_ptr[buffer_len] = 0; debug("buffer:'%s'\n", buffer_ptr); return 1; }; /// @brief copy the curren buffer to the dstination, resize destination if needed /// @param dstptr pointer to the destination pointer, in case of a reallocation /// @param max pointer to current allocated size of the pointer /// @return > 0 - len in bytes of the buffer, = -1 error occured int WebRequestBuffer::GetBuffer (char **dstptr, int *max) { // check: valid pointers if (dstptr == NULL || max == NULL) { fprintf (stderr, "%s:%d not pointer to buffer or not pointer to a lenght set\n", __FILE__, __LINE__); return -1; } // check: size and reallocate if (*max < buffer_len || *max < 0) { char *tb = (char*) realloc (*dstptr, buffer_len); *dstptr = tb; *max = buffer_size; } // check: could alloc memory if (*dstptr == NULL) { fprintf (stderr, "%s:%d no destination pointer set\n", __FILE__, __LINE__); return -1; } memcpy (*dstptr, buffer_ptr, buffer_len); return buffer_len; }; /// @brief Check if the Request is Complete. In this case the request_type and the request can /// @brief be read with GetRequest and GetType(). For a new request Clear() must be called. /// @return 0 . not complete, 1 . request complete bool WebRequestBuffer::RequestComplete() { int i = 0; int element = 0; // 0. Parameter 1. Value 2. Value n int line = 0; WebHeaderLine hl; request = ""; protocol_version = "HTTP/1.0"; request_type = WEB_REQEST_UNSUPPORTED; buffer_pos_data = -1; if (buffer_ptr == NULL) return false; hl.Clear(); for (i = 0, element = 0; i < buffer_len; i++) { // // check if line is complete if (buffer_ptr[i] == '\n') { if (hl.value.length() == 0 && hl.parameter.length() == 0) { buffer_pos_data = i+1; // save position of first data byte return true; } // the first line holds the request type and the location/path. if (line == 0) { hl.parameter = string_to_upper(hl.parameter); if (hl.parameter.compare("GET") == 0) request_type = WEB_REQEST_GET; if (hl.parameter.compare("POST") == 0) request_type = WEB_REQEST_POST; request = string_to_lower(hl.value); } headerlines.push_back(hl); hl.Clear(); element = 0; line++; continue; } // ignore some elements -> maybe it is not needed else if (strchr ("\t ", buffer_ptr[i]) != NULL) { element++; if (element > 1) hl.value += buffer_ptr[i]; } // ignore last CR else if (buffer_ptr[i] != '\r') { if (element == 0) hl.parameter += buffer_ptr[i]; // first line ignore protocol version else if (line > 0 || element == 1) hl.value += buffer_ptr[i]; } } return false; } /// @brief get some information about the complete request /// @param cmd propably get or set command /// @param obj object related with this command /// @param jp some json data /// @return int WebRequestBuffer::GetRequestCmdObj(std::string *cmd, std::string *obj, JSONParse *jp) { std::string rq = GetRequest(); int secslash = 0; if (cmd == NULL || obj == NULL || jp == NULL) errorexit ("Fatal Error cmd:%p obj:%p jp:%p none of these should be NULL\n", cmd, obj, jp); secslash = rq.find ('/', 1); *cmd = rq.substr(1, secslash-1); *obj = rq.substr(secslash+1, std::string::npos); if (buffer_pos_data > 0) (*jp).Set(buffer_ptr+buffer_pos_data); else (*jp).Clear(); return 1; } std::string WebRequestBuffer::GetRequest() { std::string rq = ""; char lastc = 0; char c = 0; // // filter out /. .. ./ for (int i = 0; i < request.length(); i++) { c = request[i]; if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '/' || c == '.' || c == '-' ) && (!((c == '.' || c == '/' ) && (lastc == '/' || lastc == '.')))) { rq += c; lastc = c; } } return rq; } std::string WebRequestBuffer::GetCookie(std::string name) { std::list::iterator il; std::size_t i; for (il = headerlines.begin(); il != headerlines.end(); il++) { if (string_to_lower(il->parameter).compare("cookie:") == 0) { i = il->value.find('='); if (i == std::string::npos) continue; if (il->value.substr(0, i).compare(name) == 0) return il->value.substr(i+1, std::string::npos); } } return ""; };