From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- pki/base/tps/src/httpClient/request.cpp | 431 ++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 pki/base/tps/src/httpClient/request.cpp (limited to 'pki/base/tps/src/httpClient/request.cpp') diff --git a/pki/base/tps/src/httpClient/request.cpp b/pki/base/tps/src/httpClient/request.cpp new file mode 100644 index 000000000..629f74821 --- /dev/null +++ b/pki/base/tps/src/httpClient/request.cpp @@ -0,0 +1,431 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ +/** BEGIN COPYRIGHT BLOCK + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Copyright (C) 2007 Red Hat, Inc. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +#include +#include "httpClient/httpc/request.h" +#include "httpClient/httpc/engine.h" +#include "httpClient/httpc/PSPRUtil.h" +#include "engine/RA.h" +#include "main/Memory.h" + +//-- static const char *DEBUG_MODULE = "httpclient"; +//-- static const char *DEBUG_CLASS_NAME = "PSHttpRequest"; + +/** + * Constructor + * @param server The server to send request to + * @param uri The uri representing the request e.g /presence/start + * @param prot HTTP10 or HTTP11 . + * @param to Timeout ... ignore for now + */ + +PSHttpRequest::PSHttpRequest(const PSHttpServer* server, + const char *uri, + HttpProtocol prot, + PRIntervalTime to) : NetRequest(server) { + //timeout = to; + timeout = PR_INTERVAL_NO_TIMEOUT; + _method = PL_strdup("GET"); + _uri = PL_strdup(uri); + _proto = prot; + _body = NULL; + _bodyLength = -1; + _expectedResponseLength = -1; + _expectStandardBody = PR_FALSE; + _expectDynamicBody = PR_FALSE; + _hangupOk = PR_FALSE; + _fileFd = NULL; + nickName = NULL; + _headers = new StringKeyCache("request",10*60); +} + +/** + * Destructor + * + */ + +PSHttpRequest::~PSHttpRequest() { + if( _method != NULL ) { + PL_strfree( _method ); + _method = NULL; + } + if( _uri != NULL ) { + PL_strfree( _uri ); + _uri = NULL; + } + if( nickName != NULL ) { + PL_strfree( nickName ); + nickName = NULL; + } + if( _fileFd != NULL ) { + PR_Close( _fileFd ); + _fileFd = NULL; + } + if( _headers != NULL ) { + delete _headers; + _headers = NULL; + } +} + +/** + * sets the request method for Http protocol + * @param method GET /POST etc + * + */ + +PRBool PSHttpRequest::setMethod(const char *method) { + if( _method != NULL ) { + free( _method ); + _method = NULL; + } + _method = PL_strdup(method); + return PR_TRUE; +} + +void PSHttpRequest::setExpectedResponseLength(int size) { + _expectedResponseLength = size; +} + +void PSHttpRequest::setExpectStandardBody() { + _expectStandardBody = PR_TRUE; +} + +void PSHttpRequest::setExpectDynamicBody() { + _expectDynamicBody = PR_TRUE; +} + +PRBool PSHttpRequest::getExpectStandardBody() { + return _expectStandardBody; +} + +PRBool PSHttpRequest::getExpectDynamicBody() { + return _expectDynamicBody; +} + +int PSHttpRequest::getExpectedResponseLength() { + return _expectedResponseLength; +} + +/** + * Returns the method to use + * + * @return GET /POST etc + */ + +char * PSHttpRequest::getMethod() { + return _method; +} + +/** + * Returns HTTP0 or HTTP11 + */ +HttpProtocol HttpMessage::getProtocol() const { + return proto; +} + +/** + * Adds an HTTP header to the request + * + * @param name header name + * @param value header value + */ +PRBool PSHttpRequest::addHeader(const char *name, const char *value) { + char *dvalue = PL_strdup(value); + CacheEntry *entry = _headers->Put(name,dvalue); + if (entry == NULL ) { + if( dvalue != NULL ) { + PL_strfree( dvalue ); + dvalue = NULL; + } + return PR_FALSE; + } else { + return PR_TRUE; + } +} + +/** + * Gets the value for a header for this HTTP request object + * + * @param name Name of the header + * @return The value of the header in the request object + */ + +const char * PSHttpRequest::getHeader(const char *name) { + CacheEntry *entry = _headers->Get(name); + return entry ? (char *)entry->GetData() : NULL; +} + +/** + * Sets the body of a POST message + * + * @param size Content length + * @param body Content of the message; it is not copied + * @return PR_TRUE if the Content-length header can be set + */ +PRBool PSHttpRequest::setBody(int size, const char* body) { + char byteStr[12]; + + sprintf(byteStr, "%d", size); + if (!addHeader("Content-length", byteStr)) { + return PR_FALSE; + } + + _bodyLength = size; + _body = (char *)body; + + return PR_TRUE; +} + +PRBool PSHttpRequest::addRandomBody(int size) { + char byteStr[12]; + + sprintf(byteStr, "%d", size); + if (!addHeader("Content-length", byteStr)) { + return PR_FALSE; + } + + _bodyLength = size; + + return PR_TRUE; +} + +PRBool PSHttpRequest::useLocalFileAsBody(const char* fileName) { + PRBool res = PR_FALSE; + PRFileInfo finfo; + if (PR_GetFileInfo(fileName, &finfo) == PR_SUCCESS) { + res = PR_TRUE; + char byteStr[25]; + sprintf(byteStr, "%d", finfo.size); + if (!addHeader("Content-length", byteStr)) { + return PR_FALSE; + } + _bodyLength = finfo.size; + _fileFd = PR_Open(fileName, PR_RDONLY, 0); + if (!_fileFd) { + return PR_FALSE; + } + } + + return PR_TRUE; +} + +/** + * This function sends the HTTP request to the server. + * @param sock - the connection onto which the request is to be sent + */ + +PRBool PSHttpRequest::send( PRFileDesc *sock ) { + const char *hostname; +//-- static const char *DEBUG_METHOD_NAME = "send"; +//-- DebugLogger *logger = DebugLogger::GetDebugLogger( DEBUG_MODULE ); + + PRBool rv = PR_FALSE; + if (!sock) { + return rv; + } + + char *data = NULL; + + if (_proto == HTTP11) { + hostname = getHeader("Host"); + + if (hostname == NULL) { + // long port = _server->getPort(); + + char address[100]; + PR_snprintf(address, 100, "%s:%d", _server->getAddr(), + _server->getPort()); + addHeader("Host", address); + } + } + + // create the HTTP string "GET /presence/stop HTTP/1.0" + char *path = strstr( _uri, "//" ); + if ( path ) { + path = strchr( path + 2, '/' ); + } + if ( !path ) { + path = _uri; + } + data = PR_smprintf( "%s %s %s\r\n", _method, path, + HttpProtocolToString(_proto) ); + + // Send HTTP headers + char **keys; + char *headerValue = NULL; + int nKeys = _headers->GetKeys( &keys ); + for ( int i = 0 ; i < nKeys; i++ ) { + CacheEntry *entry = _headers->Get( keys[i] ); + if (entry) { + headerValue = (char *)entry->GetData(); + //adds the headers name: value + data = PR_sprintf_append(data,"%s: %s\r\n",keys[i],headerValue); + if( headerValue != NULL ) { + PL_strfree( headerValue ); + headerValue = NULL; + } + } + entry = _headers->Remove(keys[i]); + if( entry != NULL ) { + delete entry; + entry = NULL; + } + if( keys[i] != NULL ) { + delete [] ( keys[i] ); + keys[i] = NULL; + } + } + if( keys != NULL ) { + delete [] keys; + keys = NULL; + } + + // Send terminator + data = PR_sprintf_append(data,"\r\n"); + + int len = PL_strlen(data); + //send the data .. + int bytes = PR_Send(sock, data, len, 0, timeout); + if( data != NULL ) { + PR_smprintf_free( data ); + data = NULL; + } + if ( bytes != len ) { +//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME, +//-- DEBUG_METHOD_NAME, + RA::Debug( LL_PER_PDU, + "PSHttpRequest::send: ", + "Error sending request -- PR_Send returned(%d) Msg=%s\n", + PR_GetError(), + "XXX" ); + return PR_FALSE; + } + + if ( _fileFd ) { + // Send body from file + PRInt32 bytesSent = PR_TransmitFile(sock, _fileFd, 0, 0, + PR_TRANSMITFILE_KEEP_OPEN, + timeout); + if ( bytesSent < 0 ) { +//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME, +//-- DEBUG_METHOD_NAME, + RA::Debug( LL_PER_PDU, + "PSHttpRequest::send: ", + "Error sending request\n" ); + return PR_FALSE; + } + } else if (_bodyLength > 0) { + // Send internally stored body + char *allocated = NULL; + if ( !_body ) { + // Send a generated pattern + _body = allocated = new char[_bodyLength]; + for ( int index = 0; index < _bodyLength; index++ ) { + _body[index] = (unsigned char)(index %256); + } + } + int sentBytes = 0; + char *toSend = _body; + for ( int i = _bodyLength; i > 0; i -= sentBytes ) { + sentBytes = PR_Send( sock, toSend, i, 0, timeout ); + if ( sentBytes < 0 ) { +//-- logger->Log( LOGLEVEL_SEVERE, DEBUG_CLASS_NAME, +//-- DEBUG_METHOD_NAME, + RA::Debug( LL_PER_PDU, + "PSHttpRequest::send: ", + "Error sending request in PR_Send\n" ); + return PR_FALSE; + } + toSend += sentBytes; + } + if ( allocated ) { + if( _body != NULL ) { + delete [] _body; + _body = NULL; + } + } + } + + return PR_TRUE; +} + +/** + * Sets the nickname for the client cert to be send to the server + * @param certName Nickname of the cert in the cert db + */ +void PSHttpRequest::setCertNickName(const char *certName) { + nickName = PL_strdup(certName); +} + +/** + * Gets the nickname for the client cert + * @return certName Nickname of the cert in the cert db + */ +char * PSHttpRequest::getCertNickName() { + return nickName; +} + +void PSHttpRequest::setHangupOk() { + _hangupOk = PR_TRUE; +} + +PRBool PSHttpRequest::isHangupOk() { + return(_hangupOk); +} + + +/** + * returns PR_TRUE if ssl is enabled for this request + */ +PRBool NetRequest::isSSL() const { + return SSLOn; +} + +/** + * enable/disable SSL for the request + */ +void NetRequest::setSSL(PRBool SSLstate) { + SSLOn=SSLstate; +} + +/** +* Constructor for NetRequest class. This is a superclass of httprequest class +* @param server The server to which the request is to be send +*/ +NetRequest :: NetRequest(const PSHttpServer* server) { + _server = server; + timeout = Engine::globaltimeout; + SSLOn=PR_FALSE; + if (server) + SSLOn=server->isSSL(); + handshake = PR_FALSE; + cipherCount = 0; + cipherSet = NULL; + +} + +/** +* Returns the current configured timeout +*/ +PRIntervalTime NetRequest :: getTimeout() const { + return timeout; +} -- cgit