void HttpHeaders::setHost(HttpMessage& message, const std::string& value) { message.setHeader(Names::HOST, value); }
void HttpHeaders::addIntHeader(HttpMessage& message, const std::string& name, int value) { message.addHeader(name, Integer::toString(value)); }
void HttpHeaders::setContentLength(HttpMessage& message, int length) { message.setHeader(Names::CONTENT_LENGTH, length); }
void HttpHeaders::setHeader(HttpMessage& message, const std::string& name, const std::vector<std::string>& values) { message.setHeader(name, values); }
void HttpHeaders::addHeader(HttpMessage& message, const std::string& name, const std::string& value) { message.addHeader(name, value); }
void SipRedirectorGateway::processForm(const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response) { UtlString string_get("get"); UtlString string_set("set"); UtlString string_prefix("prefix"); UtlString string_destination("destination"); OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm entered", mLogName.data()); UtlString* user; // Process the request. // Get the body of the request. const HttpBody* request_body = request.getBody(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm A *** request body is '%s'", mLogName.data(), request_body->getBytes()); // Get the values from the form. if (request_body->isMultipart()) { // Extract the values from the form data. UtlHashMap values; int c = request_body->getMultipartCount(); for (int i = 0; i < c; i++) { UtlString* name = new UtlString; if (request_body->getMultipart(i)->getPartHeaderValue("name", *name)) { const char* v; int l; request_body->getMultipartBytes(i, &v, &l); // Strip leading and trailing whitespace from values. UtlString* value = new UtlString(v, l); value->strip(UtlString::both); OsSysLog::add(FAC_SIP, PRI_CRIT, "%s::processForm " "form value '%s' = '%s'", mLogName.data(), name->data(), value->data()); // 'name' and 'value' are now owned by 'values'. values.insertKeyAndValue(name, value); } else { // 'name' is not owned by 'values' and we have to delete it. delete name; } } if (values.findValue(&string_get)) { // This is a "get gateway" request. // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } else if (values.findValue(&string_set)) { // This is a "set gateway" request. // Validate the routing prefix. UtlString* prefix = dynamic_cast <UtlString*> (values.findValue(&string_prefix)); if (prefixIsValid(*prefix)) { // Validate the destination. UtlString* destination = dynamic_cast <UtlString*> (values.findValue(&string_destination)); if (destination_is_valid(destination)) { OsSysLog::add(FAC_SIP, PRI_CRIT, "%s::processForm " "add mapping '%s' -> '%s'", mLogName.data(), prefix->data(), destination->data()); mMapLock.acquire(); // Insert the mapping. mMapUserToContacts.insertKeyAndValue(prefix, destination); mMapContactsToUser.insertKeyAndValue(destination, prefix); mMapLock.release(); writeMappings(); } } // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } else { // Incomprehensible request. // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } } else { // Incomprehensible request. // Insert the default HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } #if 0 #if 0 // This is quite a chore, because getMultipartBytes gets the entire // multipart section, including the trailing delimiter, rather than just // the body, which is what we need. const char* value; int length; request_body->getMultipartBytes(0, &value, &length); #if 0 OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm A *** seeing '%.*s'", mLogName.data(), length, value); #endif // Advance 'value' over the first \r\n\r\n, which ends the headers. const char* s = strstr(value, "\r\n\r\n"); if (s) { s += 4; // Allow for length of \r\n\r\n. length -= s - value; value = s; } OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm B *** seeing '%.*s'", mLogName.data(), length, value); #if 0 // Search backward for the last \r, excepting the one in the second-to-last // position, which marks the end of the contents. if (length >= 3) { for (s = value + length - 3; !(s == value || *s == '\r'); s--) { /* empty */ } length = s - value; } OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm seeing '%.*s'", mLogName.data(), length, value); #endif // Add the mappings. const char* error_msg; int error_location; UtlBoolean success = addMappings(value, length, user, error_msg, error_location); // Construct the response. response = new HttpMessage(); // Send 200 OK reply. response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION, HTTP_OK_CODE, HTTP_OK_TEXT); // Construct the HTML. char buffer1[100]; #if 0 OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm *** domain '%s'", mLogName.data(), Gatewayredirector->mDomainName.data()); #endif if (success) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm success user '%s'", mLogName.data(), user->data()); sprintf(buffer1, "<code>sip:<font size=\"+1\">%s</font>@%s:65070</code> redirects to:<br />", user->data(), Gatewayredirector->mDomainName.data()); } else { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm failure error_msg '%s', error_location %d", mLogName.data(), error_msg, error_location); strcpy(buffer1, "<i>Error:</i>"); } // Transcribe the input value into buffer2. char buffer2[FORM_SIZE]; char* p; int i; if (success) { // An impossible location. error_location = -1; } for (p = buffer2, i = 0; ; i++) { // If this is the error location, insert the error message. if (i == error_location) { *p++ = '!'; *p++ = '-'; *p++ = '-'; strcpy(p, error_msg); p += strlen(error_msg); *p++ = '-'; *p++ = '-'; *p++ = '!'; } // Test for ending the loop after testing to insert the error message, // because the error message may be after the last character. if (i >= length) { break; } switch (value[i]) { case '<': *p++ = '&'; *p++ = 'l'; *p++ = 't'; *p++ = ';'; break; case '>': *p++ = '&'; *p++ = 'g'; *p++ = 't'; *p++ = ';'; break; case '&': *p++ = '&'; *p++ = 'a'; *p++ = 'm'; *p++ = 'p'; *p++ = ';'; break; default: *p++ = value[i]; break; } } *p++ = '\0'; #endif #endif }
void XmlRpcDispatch::processRequest(const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response ) { # ifdef TEST_HTTP ssize_t len; UtlString httpString; request.getBytes(&httpString , &len); OsSysLog::add(FAC_XMLRPC, PRI_DEBUG, "XmlRpcDispatch::processRequest HttpEvent = \n%s", httpString.data()); # endif // Create a response response = new HttpMessage(); response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION_1_1, HTTP_OK_CODE, HTTP_OK_TEXT); UtlString bodyString; ssize_t bodyLength; const HttpBody* requestBody = request.getBody(); requestBody->getBytes(&bodyString, &bodyLength); XmlRpcMethod::ExecutionStatus status; UtlString methodName("<unparsed>"); XmlRpcResponse responseBody; XmlRpcMethodContainer* methodContainer = NULL; UtlSList params; UtlString logString; if (bodyString.length() > XmlRpcBody::MAX_LOG) { logString.append(bodyString, 0, XmlRpcBody::MAX_LOG); logString.append("\n..."); } else { logString = bodyString; } OsSysLog::add(FAC_XMLRPC, PRI_INFO, "XmlRpcDispatch::processRequest requestBody = \n%s", logString.data()); if (parseXmlRpcRequest(bodyString, methodContainer, params, responseBody)) { if (methodContainer) { methodContainer->getName(methodName); responseBody.setMethod(methodName); XmlRpcMethod::Get* methodGet; void* userData; methodContainer->getData(methodGet, userData); XmlRpcMethod* method = methodGet(); OsSysLog::add(FAC_XMLRPC, PRI_DEBUG, "XmlRpcDispatch::processRequest calling method '%s'", methodName.data() ); method->execute(requestContext, params, userData, responseBody, status ); // Delete the instance of the method delete method; // Clean up the memory allocated in params XmlRpcBody::deallocateContainedValues(¶ms); // if the method wants authentication, build the standard response // for anything else, it's already built one. if (XmlRpcMethod::REQUIRE_AUTHENTICATION == status) { // Create an authentication challenge response responseBody.setFault(AUTHENTICATION_REQUIRED_FAULT_CODE, AUTHENTICATION_REQUIRED_FAULT_STRING); } } else { // could not find a registered method - logged and response built in parseXmlRpcRequest status = XmlRpcMethod::FAILED; } } else { // Parsing the request failed - it will have logged a specific error a // and created an appropriate response body status = XmlRpcMethod::FAILED; } // Send the response back responseBody.getBody()->getBytes(&bodyString, &bodyLength); logString.remove(0); if (bodyString.length() > XmlRpcBody::MAX_LOG) { logString.append(bodyString, 0, XmlRpcBody::MAX_LOG); logString.append("\n..."); } else { logString = bodyString; } OsSysLog::add(FAC_XMLRPC, PRI_INFO, "XmlRpcDispatch::processRequest method '%s' response status=%s\n%s", methodName.data(), XmlRpcMethod::ExecutionStatusString(status), logString.data() ); response->setBody(new HttpBody(bodyString.data(), bodyLength)); response->setContentType(CONTENT_TYPE_TEXT_XML); response->setContentLength(bodyLength); }
/** * Test header, message, body, message contructor */ void testMessage() { // TODO break this up into several tests. Too intertwined const char* name = "Content-Type"; const char* value = "text/plain"; const char* httpTopLine = "GET /index.html HTTP/1.0"; const char* valueRef = NULL; const char* n2 = "yyy"; const char* v2 = "yyy-value"; const char* v2a = "yyy-value2"; UtlString messageBytes; UtlString messageBytes2; ssize_t messageLen = 0; ssize_t messageLen2 = 0; const char* body = "<HTML>\n<H3>Hello\n<BR>\n</HTML>\n"; const HttpBody *bodyRef; ssize_t bodyLength = 0; UtlString headerLinePart; HttpMessage *msg; HttpMessage *msg2; msg = new HttpMessage(); // H E A D E R int fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 0, fieldCount); msg->addHeaderField(name, value); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 1, fieldCount); valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value, valueRef); msg->setFirstHeaderLine(httpTopLine); valueRef = msg->getFirstHeaderLine(); ASSERT_STR_EQUAL_MESSAGE("incorrect top header line value", valueRef, httpTopLine); valueRef = msg->getHeaderValue(0, name); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value, valueRef); msg->addHeaderField(n2, v2); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 2", 2, fieldCount); valueRef = msg->getHeaderValue(0, n2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", v2, valueRef); msg->addHeaderField(n2, v2a); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 3", 3, fieldCount); valueRef = msg->getHeaderValue(1, n2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", v2a, valueRef); // B O D Y HttpBody *httpBody = new HttpBody(body, strlen(body)); msg->setBody(httpBody); bodyRef = msg->getBody(); CPPUNIT_ASSERT_MESSAGE("bad body pointer", httpBody == bodyRef); bodyRef->getBytes(&valueRef, &bodyLength); CPPUNIT_ASSERT_MESSAGE("bad body pointer", valueRef != NULL); CPPUNIT_ASSERT_EQUAL_MESSAGE("incorrect body len", (ssize_t)strlen(body), bodyLength); ASSERT_STR_EQUAL_MESSAGE("incorrect body value", body, valueRef); const char* expectedLinePart[] = { "GET", "/index.html", "HTTP/1.0" }; size_t n = sizeof(expectedLinePart) / sizeof(expectedLinePart[0]); for (size_t i = 0; i < n; i++) { msg->getFirstHeaderLinePart(i, &headerLinePart); CPPUNIT_ASSERT_MESSAGE("NULL header line part pointer", !headerLinePart.isNull()); ASSERT_STR_EQUAL_MESSAGE("incorrect hdr line", expectedLinePart[i], headerLinePart.data()); headerLinePart.remove(0); } msg->getBytes(&messageBytes, &messageLen); CPPUNIT_ASSERT_MESSAGE("NULL body pointer", !messageBytes.isNull()); // message constructor msg2 = new HttpMessage(messageBytes.data(), messageLen); msg2->getBytes(&messageBytes2, &messageLen2); valueRef = msg2->getHeaderValue(0, name); ASSERT_STR_EQUAL_MESSAGE("incorrect message bytes", value, valueRef); CPPUNIT_ASSERT_EQUAL_MESSAGE("incorrect message byte length", messageLen, messageLen2); delete msg2; delete msg; // AS DESIGNED: body delete is handled by delete msg // delete httpBody; }
/* ============================ ACCESSORS ================================= */ void WebServer::ProcessEvent( const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response ) { // get the action type (used to be the event) UtlString event; response = new HttpMessage(); ssize_t len; UtlString httpString; SubscribeServerPluginBase* plugin = NULL; request.getBytes(&httpString , &len); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "WebServer::ProcessEvent HttpEvent \n%s", httpString.data()); // get the ACTION CGI variable requestContext.getCgiVariable( EVENTTYPE, event ); if( !event.isNull()) { //according to event type , get the correct plugin from spPluginTable StatusPluginReference* pluginContainer = spPluginTable->getPlugin(event); if(pluginContainer) { plugin = pluginContainer->getPlugin(); if(plugin) { // send 200 ok reply. response->setResponseFirstHeaderLine ( HTTP_PROTOCOL_VERSION, HTTP_OK_CODE, HTTP_OK_TEXT ); //call the event handler for the plugin plugin->handleEvent(requestContext, request, *response); } else { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "WebServer::ProcessEvent no plugin in container for event type '%s'", event.data() ); } } else { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "WebServer::ProcessEvent no plugin found for event type '%s'", event.data() ); } } else { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "WebServer::ProcessEvent no '" EVENTTYPE "' variable found" ); } // We did not find a plugin so nobody handled this request. if(plugin == NULL) { response->setResponseFirstHeaderLine ( HTTP_PROTOCOL_VERSION, HTTP_FILE_NOT_FOUND_CODE, HTTP_FILE_NOT_FOUND_TEXT ); } Os::Logger::instance().flush(); }
HttpMessage RequestHandler :: handleRequest( HttpMessage& request ){ HttpMessage response; std::string body, path, ckey; handler_function func = NULL; size_t pattern_length = 0; uint64_t cache_key; std::unordered_map<uint64_t, CachedEntry>::iterator cache_it; path = request.get_path(); response.set_version( "HTTP/1.1" ); response.set_header_field( "Server", SERVER_VERSION ); response.set_header_field( "Content-Type", "text/html" ); response.set_header_field( "Date", get_gmt_time(0) ); /* ckey = request.get_method() + ":" + path; cache_key = fnv1a_hash( ckey ); */ cache_key = compute_hash( request ); pthread_rwlock_rdlock( &RequestHandler::cache_lock ); cache_it = cache.find( cache_key ); if( cache_it != cache.end() ){ if( (cache_it->second).is_valid() ){ pthread_rwlock_unlock( &RequestHandler::cache_lock ); //std::cerr << "Found @ cache" << std::endl; return (cache_it->second).get_content(); } } pthread_rwlock_unlock( &RequestHandler::cache_lock ); for( std::map< std::string, handler_function >::iterator it = handlers.begin() ; it != handlers.end() ; it++ ){ if( string_startswith( it->first, path ) ){ if( (it->first).size() > pattern_length ){ pattern_length = (it->first).size(); func = it->second; } } } if( func == NULL ){ response.set_code( 404 ); response.set_code_string( "Not found." ); response.set_version( "HTTP/1.1" ); response.set_header_field( "Connection", "close" ); response.set_header_field( "Date", get_gmt_time(0) ); response.set_header_field( "Server", SERVER_VERSION ); response.set_header_field( "Last-Modified", get_gmt_time(0) ); response.set_header_field( "Content-Type", "text/plain" ); response.set_body( "Error 404 - Not found!\n" ); } else{ response_options_t result; try{ result = func( request, response ); } catch( std::string error ){ response.set_code( 500 ); response.set_code_string( "Internal server error." ); } if( !result.ok ){ response.set_code( 404 ); response.set_code_string( "Not found." ); response.set_version( "HTTP/1.1" ); response.set_header_field( "Connection", "close" ); response.set_header_field( "Date", get_gmt_time(0) ); response.set_header_field( "Server", SERVER_VERSION ); response.set_header_field( "Last-Modified", get_gmt_time(0) ); response.set_header_field( "Content-Type", "text/plain" ); response.set_body( "Error 404 - Not found!\n" ); } else{ if( request.has_header_field( "Accept-Encoding" ) ){ if( request.get_header_field( "Accept-Encoding" ).find( "gzip" ) != std::string::npos ){ response.set_body( zlib_gzip_deflate( response.get_body() ) ); response.set_header_field( "Content-Encoding", "gzip" ); } else{ if( request.get_header_field( "Accept-Encoding" ).find( "deflate" ) != std::string::npos ){ response.set_body( zlib_deflate( response.get_body() ) ); response.set_header_field( "Content-Encoding", "deflate" ); } } } if( result.cached ){ add_cache( cache_key, response, result.expires ); } } } return response; }
/** * Test header */ void testHeader() { const char* name1 = "yyy"; const char* value1 = "yyy-value"; const char* valueRef = NULL; const char* name2 = "yyy1"; const char* value2 = "yyy-value1"; const char* value2a = "yyy-value2"; const char* value2b = "yyy-value3"; UtlBoolean rc; HttpMessage *msg; msg = new HttpMessage(); // H E A D E R int fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 0, fieldCount); // add header field name1 msg->addHeaderField(name1, value1); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 1, fieldCount); // get header field count for name1 fieldCount = msg->getCountHeaderFields(name1); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 1, fieldCount); // get header field by index valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value1, valueRef); // get header field by index and name valueRef = msg->getHeaderValue(0, name1); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value1, valueRef); // add header field name2 msg->addHeaderField(name2, value2); // get header field by name and index valueRef = msg->getHeaderValue(0, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // add second header field name2 msg->addHeaderField(name2, value2); // get header field by name and index valueRef = msg->getHeaderValue(0, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // set second header field name2 msg->setHeaderValue(name2, value2b, 1); // get header field by name and index valueRef = msg->getHeaderValue(0, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // insert header field name2 as a second header with name2 msg->insertHeaderField(name2, value2a, 2); // get header field by name and index valueRef = msg->getHeaderValue(0, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 4", 4, fieldCount); // get name1 header field count fieldCount = msg->getCountHeaderFields(name1); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 1", 1, fieldCount); // get name2 header field count fieldCount = msg->getCountHeaderFields(name2); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 3", 3, fieldCount); // get header field by name and index valueRef = msg->getHeaderValue(0, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // get header field by name and index valueRef = msg->getHeaderValue(1, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2a, valueRef); // get header field by index valueRef = msg->getHeaderValue(3); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2b, valueRef); // remove non-existing header field rc = msg->removeHeader("non-exist", 36); CPPUNIT_ASSERT_MESSAGE("incorrect return code", rc == FALSE); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 4", 4, fieldCount); // remove header field name1 rc = msg->removeHeader(name1, 0); CPPUNIT_ASSERT_MESSAGE("incorrect return code", rc == TRUE); // get header field by index valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // get name1 header field count fieldCount = msg->getCountHeaderFields(name1); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 0", 0, fieldCount); // remove second header field name2 rc = msg->removeHeader(name2, 1); CPPUNIT_ASSERT_MESSAGE("incorrect return code", rc == TRUE); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 2", 2, fieldCount); // get name2 header field count fieldCount = msg->getCountHeaderFields(name2); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 2", 2, fieldCount); // get header field by index valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // get header field by name and index valueRef = msg->getHeaderValue(1, name2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2b, valueRef); // get non-exist header field by name and index valueRef = msg->getHeaderValue(2, name2); CPPUNIT_ASSERT_MESSAGE("non-NULL field value", valueRef == NULL); // remove header field name2 rc = msg->removeHeader(name2, 1); CPPUNIT_ASSERT_MESSAGE("incorrect return code", rc == TRUE); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 1", 1, fieldCount); // get header field by index valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value2, valueRef); // remove header field name2 rc = msg->removeHeader(name2, 0); CPPUNIT_ASSERT_MESSAGE("incorrect return code", rc == TRUE); // get overall header field count fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 0", 0, fieldCount); delete msg; }
void SipRedirectorMPT::processForm(const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm entered", mLogName.data()); UtlString* user; // Process the request. // Get the body of the request. const HttpBody* request_body = request.getBody(); // Get the value from the form. // This is quite a chore, because getMultipartBytes gets the entire // multipart section, including the trailing delimiter, rather than just // the body, which is what we need. const char* value; int length; request_body->getMultipartBytes(0, &value, &length); #if 0 Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm A *** seeing '%.*s'", mLogName.data(), length, value); #endif // Advance 'value' over the first \r\n\r\n, which ends the headers. const char* s = strstr(value, "\r\n\r\n"); if (s) { s += 4; // Allow for length of \r\n\r\n. length -= s - value; value = s; } Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm B *** seeing '%.*s'", mLogName.data(), length, value); #if 0 // Search backward for the last \r, excepting the one in the second-to-last // position, which marks the end of the contents. if (length >= 3) { for (s = value + length - 3; !(s == value || *s == '\r'); s--) { /* empty */ } length = s - value; } Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm seeing '%.*s'", mLogName.data(), length, value); #endif // Add the mappings. const char* error_msg; int error_location; UtlBoolean success = MPTredirector->addMappings(value, length, user, error_msg, error_location); // Construct the response. response = new HttpMessage(); // Send 200 OK reply. response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION, HTTP_OK_CODE, HTTP_OK_TEXT); // Construct the HTML. char buffer1[100]; #if 0 Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm *** domain '%s'", mLogName.data(), MPTredirector->mDomainName.data()); #endif if (success) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm success user '%s'", mLogName.data(), user->data()); sprintf(buffer1, "<code>sip:<font size=\"+1\">%s</font>@%s:65070</code> redirects to:<br />", user->data(), MPTredirector->mDomainName.data()); } else { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm failure error_msg '%s', error_location %d", mLogName.data(), error_msg, error_location); strcpy(buffer1, "<i>Error:</i>"); } // Transcribe the input value into buffer2. char buffer2[FORM_SIZE]; char* p; int i; if (success) { // An impossible location. error_location = -1; } for (p = buffer2, i = 0; ; i++) { // If this is the error location, insert the error message. if (i == error_location) { *p++ = '!'; *p++ = '-'; *p++ = '-'; strcpy(p, error_msg); p += strlen(error_msg); *p++ = '-'; *p++ = '-'; *p++ = '!'; } // Test for ending the loop after testing to insert the error message, // because the error message may be after the last character. if (i >= length) { break; } switch (value[i]) { case '<': *p++ = '&'; *p++ = 'l'; *p++ = 't'; *p++ = ';'; break; case '>': *p++ = '&'; *p++ = 'g'; *p++ = 't'; *p++ = ';'; break; case '&': *p++ = '&'; *p++ = 'a'; *p++ = 'm'; *p++ = 'p'; *p++ = ';'; break; default: *p++ = value[i]; break; } } *p++ = '\0'; char buffer[FORM_SIZE]; sprintf(buffer, form, buffer1, buffer2); // Insert the HTML into the response. HttpBody* response_body = new HttpBody(buffer, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); }
int main() { Utils::Title("Testing HttpMessage class", '='); HttpMessage msg; msg.addAttribute(HttpMessage::attribute("Command", "GetFiles")); msg.addAttribute(HttpMessage::attribute("ToAddr", "127.0.0.1:8080")); msg.addAttribute(HttpMessage::attribute("FromAddr", "127.0.0.1:8081")); msg.addAttribute(HttpMessage::attribute("Mode", "OneWay")); msg.addAttribute(HttpMessage::attribute("content_length", "10")); msg.addBody(std::vector<HttpMessage::byte> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); std::cout << "\n" << Utils::addHeaderAndFooterLines(msg.toString()); Utils::title("testing headerString(), bodyString(), and toString()"); std::cout << "\nheader string:"; std::cout << "\n" << msg.headerString(); std::cout << "\nbody string:"; std::cout << "\n" << msg.bodyString(); std::cout << "\n\nmessage string:"; std::cout << "\n" << StringHelper::addHeaderAndFooterLines(msg.toString()); Utils::title("Testing removeAttribute"); putline(); msg.removeAttribute("content_length"); std::cout << msg.toString(); putline(); Utils::title("Testing addBody(const std::string&)"); std::string msgBody = "<msg>this is a message</msg>"; msg.addAttribute(HttpMessage::Attribute("content_length", Converter<size_t>::toString(msgBody.size()))); msg.addBody(msgBody); std::cout << "\n" << StringHelper::addHeaderAndFooterLines(msg.toString()); Utils::title("Testing parseAttribute(const std::string&)"); std::string test2 = "name:value"; std::cout << "\n input = \"" << test2 << "\""; Attribute attrib2 = HttpMessage::parseAttribute(test2); std::cout << "\n result is: " << HttpMessage::attribString(attrib2); test2 = " name : value "; std::cout << "\n input = \"" << test2 << "\""; attrib2 = HttpMessage::parseAttribute(test2); std::cout << "\n result is: " << HttpMessage::attribString(attrib2); Utils::title("Testing Message parsing"); MockSocket sock(msg); HttpMessage msg2; while (true) { std::string line = sock.recvString(); if (line.size() == 0) break; Attribute attrib = HttpMessage::parseAttribute(line); msg2.addAttribute(attrib); } Value val = msg2.findValue("content_length"); if (val.size() > 0) { size_t numBytes = Converter<size_t>::toValue(val); byte* pBuffer = new byte[numBytes]; sock.recv(numBytes, pBuffer); msg2.addBody(numBytes, pBuffer); } std::cout << "\n" << Utils::addHeaderAndFooterLines(msg2.toString()); std::cout << "\n\n"; }
MockSocket(const HttpMessage& msg) : msgString_(msg.toString()) {};
int HttpServer::run(void* runArg) { OsConnectionSocket* requestSocket = NULL; if (!mpServerSocket->isOk()) { OsSysLog::add( FAC_SIP, PRI_ERR, "HttpServer: port not ok" ); httpStatus = OS_PORT_IN_USE; } while(!isShuttingDown() && mpServerSocket->isOk()) { requestSocket = mpServerSocket->accept(); if(requestSocket) { if (mbPersistentConnection) { // Take this opportunity to check for any old HttpConnections that can be deleted int items = mpHttpConnectionList->entries(); if (items != 0) { int deleted = 0; UtlSListIterator iterator(*mpHttpConnectionList); HttpConnection* connection; while ((connection = dynamic_cast<HttpConnection*>(iterator()))) { if (connection->toBeDeleted()) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "HttpServer: destroying connection %p", connection); mpHttpConnectionList->destroy(connection); ++deleted; if (mHttpConnections > 0) { --mHttpConnections; } } } items = mpHttpConnectionList->entries(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "HttpServer: " "destroyed %d inactive HttpConnections, %d remaining", deleted, items); } // Create new persistent connection if (mHttpConnections < MAX_PERSISTENT_HTTP_CONNECTIONS) { ++mHttpConnections; HttpConnection* newConnection = new HttpConnection(requestSocket, this); mpHttpConnectionList->append(newConnection); OsSysLog::add(FAC_SIP, PRI_INFO, "HttpServer::run starting persistent connection %d (%p)", mHttpConnections, newConnection); newConnection->start(); } else { OsSysLog::add(FAC_SIP, PRI_ERR, "HttpServer::run exceeded persistent connection limit (%d):" " sending 503", MAX_PERSISTENT_HTTP_CONNECTIONS); HttpMessage request; HttpMessage response; // Read the http request from the socket request.read(requestSocket); // Send out-of-resources message response.setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION, HTTP_OUT_OF_RESOURCES_CODE, HTTP_OUT_OF_RESOURCES_TEXT); response.write(requestSocket); requestSocket->close(); delete requestSocket; requestSocket = NULL; } } else { HttpMessage request; // Read a http request from the socket request.read(requestSocket); UtlString remoteIp; requestSocket->getRemoteHostIp(&remoteIp); HttpMessage* response = NULL; // If request from Valid IP Address if( processRequestIpAddr(remoteIp, request, response)) { // If the request is authorized processRequest(request, response, requestSocket); } if(response) { response->write(requestSocket); delete response; response = NULL; } requestSocket->close(); delete requestSocket; requestSocket = NULL; } } else { httpStatus = OS_PORT_IN_USE; } } // while (!isShuttingDown && mpServerSocket->isOk()) if ( !isShuttingDown() ) { OsSysLog::add( FAC_SIP, PRI_ERR, "HttpServer: exit due to port failure" ); } httpStatus = OS_TASK_NOT_STARTED; return(TRUE); }
int HttpGetCommand::execute(int argc, char* argv[]) { int commandStatus = CommandProcessor::COMMAND_FAILED; if(argc == 2) { commandStatus = CommandProcessor::COMMAND_SUCCESS; const char* url = argv[1]; const char* serverBegin = strstr(url, "http://"); if(serverBegin != url) { printf("unsupported protocol in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } else { serverBegin += 7; UtlString uri(serverBegin); int serverEndIndex = uri.index("/"); if(serverEndIndex < 0) serverEndIndex = uri.length(); if(serverEndIndex > 0) { UtlString server = uri; server.remove(serverEndIndex); int portIndex = server.index(":"); int port = 0; if(portIndex > 0) { UtlString portString = server; server.remove(portIndex); portString.remove(0, portIndex + 1); printf("port string: %s\n", portString.data()); port = atoi(portString.data()); } uri.remove(0, serverEndIndex); if(uri.isNull()) uri = "/"; printf("HTTP get of %s from server %s port: %d\n", uri.data(), server.data(), port); if(port == 0) { port = 80; printf("defaulting to http port 80\n"); } OsConnectionSocket getSocket(port, server.data()); HttpMessage getRequest; getRequest.setFirstHeaderLine("GET", uri.data(), HTTP_PROTOCOL_VERSION); int wroteBytes = getRequest.write(&getSocket); printf("wrote %d\n", wroteBytes); HttpMessage getResponse; getResponse.read(&getSocket); UtlString responseBytes; int responseLength; getResponse.getBytes(&responseBytes, &responseLength); printf("Got %d bytes\n", responseLength); printf("Response: ++++++++++++++++++++++++++++++++++\n%s\n", responseBytes.data()); } else { printf("invalid server in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } } } else { UtlString usage; getUsage(argv[0], &usage); printf("%s", usage.data()); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; //commandStatus = CommandProcessor::COMMAND_FAILED; } return(commandStatus); }
void HttpServer::processRequest(const HttpMessage& request, HttpMessage*& response, OsConnectionSocket* connection ) { UtlString method; response = NULL; if(true) // used to be authorization check, but I don't want to change all indenting { request.getRequestMethod(&method); method.toUpper(); UtlString uri; request.getRequestUri(&uri); UtlString uriFileName(uri); ssize_t fileNameEnd = -1; if(method.compareTo(HTTP_GET_METHOD) == 0) { fileNameEnd = uriFileName.first('?'); if(fileNameEnd > 0) { uriFileName.remove(fileNameEnd); } } UtlString mappedUriFileName; if (uriFileName.contains("..")) { OsSysLog::add(FAC_SIP, PRI_ERR, "HttpServer::processRequest " "Disallowing URI: '%s' because it contains '..'", uriFileName.data()); // Disallow relative path names going up for security reasons mappedUriFileName.append("/"); } else { OsSysLog::add(FAC_SIP, PRI_INFO, "HttpServer::processRequest " "%s '%s'", method.data(), uriFileName.data()); // Map the file name mapUri(mUriMaps, uriFileName.data(), mappedUriFileName); } // Build the request context HttpRequestContext requestContext(method.data(), uri.data(), mappedUriFileName.data(), NULL, NULL, // was userid connection ); if(requestContext.methodIs(HTTP_POST_METHOD)) { //Need to get the CGI/form variables from the body. const HttpBody* body = request.getBody(); if(body && !body->isMultipart()) { requestContext.extractPostCgiVariables(*body); } } RequestProcessor* requestProcessorPtr = NULL; HttpService* pService = NULL; if( ( requestContext.methodIs(HTTP_GET_METHOD) || requestContext.methodIs(HTTP_POST_METHOD) ) && findRequestProcessor(uriFileName.data(), requestProcessorPtr)) { // There is a request processor for this URI requestProcessorPtr(requestContext, request, response); } else if ( ( requestContext.methodIs(HTTP_GET_METHOD) || requestContext.methodIs(HTTP_POST_METHOD) || requestContext.methodIs(HTTP_PUT_METHOD) || requestContext.methodIs(HTTP_DELETE_METHOD) ) && findHttpService(uriFileName.data(), pService)) { pService->processRequest(requestContext, request, response); } else { processNotSupportedRequest(requestContext, request, response); } } }
void HttpHeaders::setHeader(HttpMessage& message, const std::string& name, int vlaue) { message.setHeader(name, Integer::toString(vlaue)); }
void MsgClient::sendMessage(HttpMessage& msg, Socket& socket) { std::string msgString = msg.toString(); socket.send(msgString.size(), (Socket::byte*)msgString.c_str()); }
HttpMessage Sender::makeMessage(size_t n, const std::string& body, const EndPoint& ep) { HttpMessage msg; HttpMessage::Attribute attrib; EndPoint myEndPoint = "localhost:8081"; // ToDo: make this a member of the sender // given to its constructor. switch (n) { case 1: msg.clear(); msg.addAttribute(HttpMessage::attribute("POST", "Message")); msg.addAttribute(HttpMessage::Attribute("mode", "oneway")); msg.addAttribute(HttpMessage::parseAttribute("toAddr:" + ep)); //msg.addAttribute(HttpMessage::parseAttribute("fromAddr:" + myEndPoint)); msg.addBody(body); if (body.size() > 0) { attrib = HttpMessage::attribute("content-length", Converter<size_t>::toString(body.size())); msg.addAttribute(attrib); } break; case 2: msg.clear(); msg.addAttribute(HttpMessage::attribute("GET", "Message")); msg.addAttribute(HttpMessage::Attribute("mode", "oneway")); msg.addAttribute(HttpMessage::parseAttribute("toAddr:" + ep)); msg.addAttribute(HttpMessage::parseAttribute("fromAddr:" + myEndPoint)); msg.addBody(body); if (body.size() > 0) { attrib = HttpMessage::attribute("content-length", Converter<size_t>::toString(body.size())); msg.addAttribute(attrib); } break; default: msg.clear(); msg.addAttribute(HttpMessage::attribute("Error", "unknown message type")); } return msg; }