You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-dev@axis.apache.org by "Arcangelo Di Balsamo (JIRA)" <ax...@ws.apache.org> on 2005/03/08 15:06:52 UTC

[jira] Created: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS

Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
-------------------------------------------------------------------------------------------------------------

         Key: AXISCPP-518
         URL: http://issues.apache.org/jira/browse/AXISCPP-518
     Project: Axis-C++
        Type: Bug
  Components: Transport (axis3)  
    Versions: unspecified    
 Environment: The bug affects all platforms
    Reporter: Arcangelo Di Balsamo


I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation. 
The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
I've already made a fix: the affected module is HTTPTransport.cpp.
The modified code is :


/*
*   Copyright 2003-2004 The Apache Software Foundation.
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

/*
 * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
 *
 */

#ifdef WIN32
#pragma warning (disable : 4786)
#pragma warning (disable : 4101)
#endif

#include "HTTPTransport.hpp"

#include <stdio.h>
#include <iostream>

/*
 * HTTPTransport constuctor
 */
HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
m_strHTTPProtocol ("HTTP/1.1"),
m_strHTTPMethod ("POST"),
m_bChunked (false),
m_bReadPastHTTPHeaders (false),
m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
m_bMaintainSession (false)
{
    m_pcEndpointUri = NULL;
    m_pReleaseBufferCallback = 0;
    m_eProtocolType = APTHTTP1_1;
    m_strBytesToSend = "";
    m_strHeaderBytesToSend = "";
    m_iBytesLeft = 0;
    m_iContentLength = 0;
    m_pcReceived = 0;
	m_bChannelSecure = false;
    m_pNormalChannel = 0;
    m_pSecureChannel = 0;
	m_pActiveChannel = 0;
    m_pChannelFactory = new ChannelFactory();
    m_bMimeTrue = false;
    m_viCurrentHeader = m_vHTTPHeaders.begin();
	m_pszRxBuffer = new char [BUF_SIZE];
#ifdef WIN32
	m_lChannelTimeout = 10;
#else
	m_lChannelTimeout = 0;
#endif
}

/*
 * HTTPTransport destuctor
 */
HTTPTransport::~HTTPTransport()
{
    if( m_pcEndpointUri)
    {
	delete[] m_pcEndpointUri;
    }

    if( m_pChannelFactory)
	{
		delete m_pChannelFactory;

		m_pChannelFactory = 0;
	}

	delete [] m_pszRxBuffer;
}

/*
 * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
 * Everytime the endpoint changes then currently connected channel is closed
 * and a new channel connection is opened.
 *
 * @param	EndpointURI - char * to a null terminated string that holds the
 *			new URI. 
 */
void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
{
    bool bUpdateURL = false;

    // Get the current channel URI
    if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
    {
	// Does the new URI equal the existing channel URI?
		if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
		{
	    // There is a new URI.
			bUpdateURL = true;
		}
    }
    else
    {
		bUpdateURL = true;
    }


    // If there is a new URI, then this flag will be set.  Depending on whether
    // there is an SSL implementation available, if the new URI is a secure
	// connection, a secure channel will be opened.  If an SSL implementation
	// is not available and the URL requires a secure connection then an
	// exception will be thrown.
    if( bUpdateURL)
    {
		if( m_pActiveChannel == NULL)
		{
			m_pActiveChannel = m_pNormalChannel;
		}

		m_pActiveChannel->setURL( pcEndpointUri);

		m_bReopenConnection = true;

	// Check if the new URI requires SSL (denoted by the https prefix).
		if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
		{
			if( m_pSecureChannel != NULL)
			{
				m_pNormalChannel->close();

				m_pActiveChannel = m_pSecureChannel;

				m_pActiveChannel->setURL( pcEndpointUri);

				m_bChannelSecure = true;
			}

			if( !m_bChannelSecure)
			{
				throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
			}
		}
		else
		{
	    // URI does not require a secure channel.  Delete the existing
	    // channel if it is secure and create a new unsecure
	    // channel.
			if (m_bChannelSecure)
			{
				if( m_pNormalChannel != NULL)
				{
					m_pSecureChannel->close();

					m_pActiveChannel = m_pNormalChannel;
					m_pActiveChannel->setURL( pcEndpointUri);
					m_bChannelSecure = false;
				}

				if( m_bChannelSecure)
				{
					throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
				}
			}
		}
    }

// Need this code to set the channel timeout.  If the timeout was changed
// before the channel was created, then it may not have the correct timeout.
// By setting it here, the channel is sure to have the correct timeout value
// next time the channel is read.
	if( m_pActiveChannel != NULL)
	{
		m_pActiveChannel->setTimeout( m_lChannelTimeout);
	}
}

/*
 * HTTPTransport::openConnection().
 */

int HTTPTransport::openConnection()
{
	return m_pActiveChannel->open();
}

/*
 * HTTPTransport::closeConnection().
 */
void HTTPTransport::closeConnection()
{
    // get ready for a new message.
    m_bReadPastHTTPHeaders = false;

    //clear the message buffer in preperation of the next read.
    m_strReceived = "";

    m_iContentLength = 0;

	if( m_pActiveChannel != NULL)
	{
		m_pActiveChannel->close();
	}
}

/*
 * HTTPTransport::flushOutput() Is called when the message construction is
 * complete.  The message is ready to be 'flushed out' onto the network.  
 * Check if the URI has changed.  If it has, then need to open a new Channel
 * instance before transmitting the message.
 *
 * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
 * this will be set to TRANSPORT_FINISHED.  Otherwise, an exception will have
 * been thrown.
 */
AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
{
    if( m_bReopenConnection)
    {
		m_bReopenConnection = false;

		if( m_pActiveChannel->open() != AXIS_SUCCESS)
		{
		    int				iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
			const char *	pszLastError = new char[iStringLength];

		    memcpy( (void *) pszLastError,
					m_pActiveChannel->GetLastErrorMsg().c_str(),
					iStringLength);

		    throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
										  (char *) pszLastError);
			}
		}

    // In preperation for sending the message, calculate the size of the message
    // by using the string length method.
    // NB: This calculation may not necessarily be correct when dealing with SSL
    //     messages as the length of the encoded message is not necessarily the
    //         same as the length of the uncoded message.
    char buff[8];

	sprintf( buff, "%d", m_strBytesToSend.length ());

    this->setTransportProperty ("Content-Length", buff);

    // The header is now complete.  The message header and message can now be
    // transmitted.
	try
	{
		*m_pActiveChannel << this->getHTTPHeaders ();
		*m_pActiveChannel << this->m_strBytesToSend.c_str ();
	}
	catch( HTTPTransportException & e)
	{
		throw;
	}
	catch( AxisException & e)
	{
		throw;
	}
	catch(...)
	{
		throw;
	}

    // Empty the bytes to send string.
	m_strBytesToSend = "";
	m_strHeaderBytesToSend = "";

	return TRANSPORT_FINISHED;
}

/* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
 * information block that will preceed the SOAP message.
 *
 * @return const char* Pointer to a NULL terminated character string containing
 * the HTTP header block of information.
 */
const char * HTTPTransport::getHTTPHeaders()
{
    URL &			url = m_pActiveChannel->getURLObject();
    unsigned short	uiPort = url.getPort();
    char			buff[8];

    m_strHeaderBytesToSend = m_strHTTPMethod + " ";
    m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
    m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
    m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();

    sprintf (buff, "%u", uiPort);

    m_strHeaderBytesToSend += ":";
    m_strHeaderBytesToSend += buff;
    m_strHeaderBytesToSend += "\r\n";
    m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";

    // Set other HTTP headers
    for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
    {
		m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
		m_strHeaderBytesToSend += ": ";
		m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
		m_strHeaderBytesToSend += "\r\n";
    }

    // Set session cookie
    if (m_bMaintainSession && (m_strSessionKey.size () > 0))
    {
		m_strHeaderBytesToSend += "Cookie";
		m_strHeaderBytesToSend += ": ";
		m_strHeaderBytesToSend += m_strSessionKey;
		m_strHeaderBytesToSend += "\r\n";
    }

    m_strHeaderBytesToSend += "\r\n";

    return m_strHeaderBytesToSend.c_str ();
}

/* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
 * (i.e. GET or POST) that will be part of the HTTP header block.
 *
 * @return const char* Pointer to a NULL terminated character string containing
 * the HTTP method.
 */
const char * HTTPTransport::getHTTPMethod()
{
    return m_strHTTPMethod.c_str ();
}

/* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
 * method (i.e. POST or GET) that will be part of the HTTP header block.
 *
 * @param const char* Pointer to a NULL terminated character string containing
 * the new HTTP method.
 */
void HTTPTransport::setHTTPMethod( const char *cpMethod)
{
    m_strHTTPMethod = std::string( cpMethod);
}

/* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
 * concatinates the new send buffer to the bytes to send string.  This message
 * will only be sent when a flush buffer is received.
 *
 * @param const char* SendBufer - Pointer to a NULL terminated character string
 * containing all or some of the transmission message.
 * @param const void* BufferId - Pointer.  This parameter is ignored.
 *
 * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
 * always be TRANSPORT_IN_PROGRESS).
 */
AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
{
    m_strBytesToSend += std::string (pcSendBuffer);

    return TRANSPORT_IN_PROGRESS;
}

/* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
 * receive the synchronous reply to the sent message.
 *
 * @param const char* ReceiveBuffer - Pointer to a character string that on
 * return will containing all or part of the received message.
 * @param int* Size - Pointer to an integer value that on return will contain
 * the length of the received message.
 *
 * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
 * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
 */
AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
{
    if (0 >= m_iBytesLeft)
    {
		try
		{
			m_pszRxBuffer [0] = '\0';
			*m_pActiveChannel >> m_pszRxBuffer;
			m_strReceived = m_pszRxBuffer;

		    if( !m_bReadPastHTTPHeaders)
		    {
				unsigned int start = std::string::npos;

				do
				{
					do
					{
						if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
						{
							m_pszRxBuffer [0] = '\0';
							*m_pActiveChannel >> m_pszRxBuffer;
						    m_strReceived += m_pszRxBuffer;
						}
					} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);

					if( m_strReceived.find ("HTTP") == std::string::npos)
					{
			// Most probably what we read was left overs from earlier reads
			// Skip this \r\n\r\n
						m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);

						do
						{
							if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
							{
								m_pszRxBuffer [0] = '\0';
								*m_pActiveChannel >> m_pszRxBuffer;
								m_strReceived += m_pszRxBuffer;
							}
						} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
			// now this must contain HTTP. Else there is a conent error.
					}

		    //now we have found the end of headers
					m_bReadPastHTTPHeaders = true;

				    unsigned int pos = 0;

		    // Look for content lenght
				    if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
					{
						m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
																	   m_strReceived.find( "\n", pos)).c_str());
				    }

		    // Check if the message is chunked
				    if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
					{
						m_bChunked = true;
					}
					else
					{
						m_bChunked = false;
					}

		    // check if there is HTTP header. If not, there must be an error and 
		    // will be detected by processResponseHTTPHeaders()
		    // However, must make sure that the left overs from eatlier reads
		    // do not appear before HTTP/1.x
					start = m_strReceived.find( "HTTP");

					if( start == std::string::npos)
					{
						start = 0;
					}

		    // Extract HTTP headers and process them
				    m_strResponseHTTPHeaders = m_strReceived.substr( start,
																     m_strReceived.find( "\r\n\r\n") + 2 - start);
				    processResponseHTTPHeaders();

				    if( m_iResponseHTTPStatusCode == 100)
				    {
			// Samisa: We found Continue. Keep on reading and processing headers
			// till we get a HTTP code other than 100
			// Here it is assumed that the whole of the request is already sent
						m_pszRxBuffer [0] = '\0';
						*m_pActiveChannel >> m_pszRxBuffer;
						m_strReceived = m_pszRxBuffer;
					}
				} while( m_iResponseHTTPStatusCode == 100);

                if ( m_iResponseHTTPStatusCode != 500 &&
                    ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
				{
				    throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
												  const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
				}

		// Done with HTTP headers, get payload
				m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
		    }

	    // Read past headers. Deal with payload

	    // make sure we have a message with some content
		    if( m_strReceived.length () == 0)
			{
				m_pszRxBuffer [0] = '\0';
				*m_pActiveChannel >> m_pszRxBuffer;
				m_strReceived = m_pszRxBuffer;
			}

			if( m_strReceived.length () > 0) 
			{
			    if( m_bChunked && m_iContentLength < 1)	// Read first chunk
				{
			/*
			 *Chunked data looks like ->
			 *      Chunked-Body   = *chunk
			 *                       "0" CRLF
			 *                       footer
			 *                       CRLF
			 *
			 *      chunk          = chunk-size [ chunk-ext ] CRLF
			 *                         chunk-data CRLF
			 *
			 *      hex-no-zero    = <HEX excluding "0">
			 *
			 *      chunk-size     = hex-no-zero *HEX
			 *      chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
			 *      chunk-ext-name = token
			 *      chunk-ext-val  = token | quoted-string
			 *      chunk-data     = chunk-size(OCTET)
			 *
			 *      footer         = *entity-header
			 */
			// firstly read in the chunk size line.
			//There might be chunk extensions in there too but we may not need them
					unsigned int endOfChunkData = m_strReceived.find( "\r\n");

			// make sure we have read at least some part of the message
					if( endOfChunkData == std::string::npos)
					{
						do
						{
							m_pszRxBuffer [0] = '\0';
							*m_pActiveChannel >> m_pszRxBuffer;
							m_strReceived = m_pszRxBuffer;
							endOfChunkData = m_strReceived.find( "\r\n");
						} while( endOfChunkData == std::string::npos);
					}

					int endOfChunkSize = endOfChunkData;

			// now get the size of the chunk from the data
			// look to see if there are any extensions - these are put in brackets so look for those
					if( m_strReceived.substr( 0, endOfChunkData).find( "(") != string::npos)
					{
						endOfChunkSize = m_strReceived.find( "(");
					}

			// convert the hex String into the length of the chunk
					m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());

			// if the chunk size is zero then we have reached the footer
			// If we have reached the footer then we can throw it away because we don't need it
					if( m_iContentLength > 0)
					{
				// now get the chunk without the CRLF
				// check if we have read past chunk length
						if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
						{
							m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
						}
						else	// we have read lesser than chunk length
						{
							m_strReceived = m_strReceived.substr( endOfChunkData + 2);
						}
				/* We have received part of chunk data. If received payload
				 *  is a mime struct, process it
				 */
						if( m_bMimeTrue)
						{
							processRootMimeBody();
						}
					}
					else
					{
						m_strReceived = "";
					}
				}
				else if( m_bChunked)	// read continued portions of a chunk
				{
			// Samisa - NOTE: It looks as if there is some logic duplication
			// in this block, where we read continued chunks and the block
			// above, where we read the first chunk. However, there are slight
			// logical differences here, and that is necessary to enable the
			// pull model used by the parser - this logic makes pulling more
			// efficient (30th Sept 2004)
					if( m_strReceived.length () >= m_iContentLength)	// We have reached end of current chunk
					{
				// Get remainder of current chunk
						std::string strTemp = m_strReceived.substr( 0, m_iContentLength);

				// Start looking for the next chunk
				// The format we are expecting here is:
				// <previous chunk>\r\n<chunk size>\r\n<next chunk>

						unsigned int endOfChunkData = m_strReceived.find( "\r\n");

				// Make sure that we have the found the end of previous chunk
						while( endOfChunkData == std::string::npos)
						{
							m_pszRxBuffer [0] = '\0';
							*m_pActiveChannel >> m_pszRxBuffer;
							m_strReceived += m_pszRxBuffer;
							endOfChunkData = m_strReceived.find( "\r\n");
						}

						m_strReceived = m_strReceived.substr( endOfChunkData + 2);	// Skip end of previous chunk

						endOfChunkData = m_strReceived.find( "\r\n");	// Locate the start of next chunk

				// Make sure that we have the starting line of next chunk
						while( endOfChunkData == std::string::npos)
						{
							m_pszRxBuffer [0] = '\0';
							*m_pActiveChannel >> m_pszRxBuffer;
							m_strReceived += m_pszRxBuffer;
							endOfChunkData = m_strReceived.find( "\r\n");
						}

						int endOfChunkSize = endOfChunkData;

				// look to see if there are any extensions - these are put in brackets so look for those
						if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
						{
							endOfChunkSize = m_strReceived.find ("(");
						}

				// convert the hex String into the length of the chunk
						int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());

				// if the chunk size is zero then we have reached the footer
				// If we have reached the footer then we can throw it away because we don't need it
						if( iTempContentLength > 0)
						{
				// Update the content lenght to be remainde of previous chunk and lenght of new chunk
							m_iContentLength += iTempContentLength;

				// now get the chunk without the CRLF
				// check if we have read past chunk length
							if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
							{
								m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
							}
							else
							{
								m_strReceived = m_strReceived.substr( endOfChunkData + 2);
							}

				/* We have received part of chunk data. If received payload
				 *  is a mime struct, process it
				 */
							if( m_bMimeTrue)
							{
								processRootMimeBody();
							}
						}
						else
						{
							m_strReceived = "";
						}

				// Append the data of new chunk to data from previous chunk
						m_strReceived = strTemp + m_strReceived;

						}		// End of if (m_strReceived.length() >= m_iContentLength)
			// If we have not reached end of current chunk, nothing to be done
					}
					else		// Not chunked
					{
				//nothing to do here
				/* We have received part of chunk data. If received payload
				 *  is a mime struct, process it
				 */
						if( m_bMimeTrue)
						{
							processRootMimeBody();
						}
					}
				}

				m_pcReceived = m_strReceived.c_str();

				if( m_pcReceived)
				{
					m_iBytesLeft = strlen( m_pcReceived);
				}
				else
				{
					throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
				}

				m_iContentLength -= m_iBytesLeft;
		}
		catch( HTTPTransportException & e)
		{
			throw;
		}
		catch( AxisException & e)
		{
		    throw;
		}
		catch(...)
		{
		    throw;
		}
    }

    if (( m_pcReceived) && (*m_pcReceived))
    {
		int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;

		strncpy( pcBuffer, m_pcReceived, iToCopy);

		m_iBytesLeft -= iToCopy;
		m_pcReceived += iToCopy;
		*pSize = iToCopy;

		return TRANSPORT_IN_PROGRESS;
	}
	else
	{
		m_bReadPastHTTPHeaders = false;	// get ready for a new message
		m_strReceived = "";	//clear the message buffer in preperation of the next read

		return TRANSPORT_FINISHED;
    }
}

/* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
 * method used to set a HTTP transport or SSL implementation property.
 *
 * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
 * the type of information to be stored in either the HTTP Header or SSL
 * implementation settings.
 * @param const char* Value is a NULL terminated character string containing
 * the value associated with the type.
 */
void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
{
    const char *key = NULL;

    switch (type)
    {
	    case SOAPACTION_HEADER:
		{
			key = "SOAPAction";
		    break;
		}

		case SERVICE_URI:		// need to set ?
		{
			break;
		}

		case OPERATION_NAME:	// need to set ?
		{
			break;
		}

		case SOAP_MESSAGE_LENGTH:
		{
			key = "Content-Length";	// this Axis transport handles only HTTP
			break;
		}

		case TRANSPORT_PROPERTIES:
		{
			m_pActiveChannel->setTransportProperty( type, value);

			break;
		}

		case SECURE_PROPERTIES:
		{
			m_pActiveChannel->setSecureProperties( value);

			break;
		}

		case CHANNEL_HTTP_DLL_NAME:
		{
			m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
			break;
		}

		case CHANNEL_HTTP_SSL_DLL_NAME:
		{
			m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
			break;
		}

		default:
		{
			break;
		}
    }

    if( key)
    {
		setTransportProperty( key, value);
    }
}

/* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
 * method used to set a HTTP transport or SSL implementation property.
 *
 * @param const char* Key is a NULL terminated character string containing
 * the type of information to be stored in either the HTTP Header or SSL
 * implementation settings.
 * @param const char* Value is a NULL terminated character string containing
 * the value associated with the type.
 */
void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
{
    if( !pcKey || !pcValue)	// Samisa - fix for AXISCPP-295. We must check for valid values here.
	{
		return;
	}

    bool b_KeyFound = false;

    if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
    {
		std::string strKeyToFind = std::string( pcKey);

		for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
		{
		    if (m_vHTTPHeaders[i].first == strKeyToFind)
			{
				m_vHTTPHeaders[i].second = (string) pcValue;

				b_KeyFound = true;

				break;
		    }
		}
    }

    if( !b_KeyFound)
    {
		m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
    }
}

/* HTTPTransport::getTransportProperty( Type) Is a public method that will
 * return the HTTP Header/SSL implementation value associated with type.
 *
 * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
 * the type of information to be retrieved in either the HTTP Header or SSL
 * implementation settings.
 *
 * @return const char* Value is a NULL terminated character string containing
 * the value associated with the type.
 */
const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
{
    const char *pszPropValue = NULL;

    switch( eType)
    {
	    case SOAPACTION_HEADER:
		{
			int iIndex = FindTransportPropertyIndex( "SOAPAction");

		    if (iIndex > -1)
		    {
				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
		    }

		    break;
		}

	    case SERVICE_URI:
		{
			break;
		}

	    case OPERATION_NAME:
		{
			break;
		}

	    case SOAP_MESSAGE_LENGTH:
		{
			int iIndex = FindTransportPropertyIndex( "Content-Length");

		    if (iIndex > -1)
		    {
				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
		    }

		    break;
		}

	case TRANSPORT_PROPERTIES:
    case SECURE_PROPERTIES:
		{
			pszPropValue = m_pActiveChannel->getTransportProperty( eType);
			break;
		}

	case CHANNEL_HTTP_SSL_DLL_NAME:
	case CHANNEL_HTTP_DLL_NAME:
		{
			break;
		}
    }

    return pszPropValue;
}

/* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
 * return the HTTP Header index associated with Key.
 *
 * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
 * the type of information to be retrieved in either the HTTP Header settings.
 *
 * @return int Index is an index to the key within the HTTP Header list.  If
 * the return value is -1, then the key was not found.
 */
int HTTPTransport::FindTransportPropertyIndex( string sKey)
{
    bool	bKeyFound = false;
    int		iIndex = 0;

    do
    {
		if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
		{
			bKeyFound = true;
		}
		else
		{
			iIndex++;
		}
    } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);

    if( !bKeyFound)
    {
		iIndex = -1;
    }

    return iIndex;
}

/* HTTPTransport::getServiceName() Is a public method to return the HTTP
 * Header service name.
 *
 * @return const char* Value is a NULL terminated character string containing
 * the value associated with the service name.
 */
const char * HTTPTransport::getServiceName()
{
    //Assume SOAPAction header to contain service name
    int		iIndex = FindTransportPropertyIndex( "SOAPAction");

    if (iIndex > -1)
    {
		return m_vHTTPHeaders[iIndex].second.c_str();
    }

    return NULL;
}


AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
{
    return m_eProtocolType;
}

int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
{
    if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
    {
		m_eProtocolType = eProtocol;

		m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";

		return AXIS_SUCCESS;
    }
    else
	{
		return AXIS_FAIL;
	}
}

/**
 * HTTPTransport::getSubProtocol() is a public method that is supposed to
 * return the sub protocol (currently this method always return 0).
 * This method is supposed to return whether it is http GET or POST
 */
int HTTPTransport::getSubProtocol()
{
    //TODO
    // for SimpleAxisServer assume POST
    return AXIS_HTTP_POST;
    //return 0;
}

/* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
 * updating the proxy for the connection.
 *
 * @param const char* Host is a NULL terminated character string containing the new
 * proxy host.
 * @param unsigned int Port is the new proxy port number.
 */
void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
{
    m_strProxyHost = pcProxyHost;
    m_uiProxyPort = uiProxyPort;
    m_bUseProxy = true;
}

/* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
 * current maximum timeout period between that can elapse between receiving
 * message parts.
 *
 * @param const long Timeout is a long value in seconds.
 */
void HTTPTransport::setTimeout( const long lSeconds)
{
	if( m_pActiveChannel != NULL)
	{
		m_pActiveChannel->setTimeout( lSeconds);
	}

	m_lChannelTimeout = lSeconds;
}

/* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
 * current HTTP protocol settings.
 *
 * @return const char* HTTPProtocol is a NULL terminated character string
 * containing the HTTP protocol.
 */
const char * HTTPTransport::getHTTPProtocol()
{
    return m_strHTTPProtocol.c_str ();
}

/* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
 */
int axtoi( char *pcHexStg)
{
    int		iN = 0;			// position in string
    int		iM = 0;			// position in digit[] to shift
    int		iCount;			// loop index
    int		intValue = 0;	// integer value of hex string
    int		iDigit[32];		// hold values to convert

    while( iN < 32)
    {
		if( pcHexStg[iN] == '\0')
		{
			break;
		}
	
		if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40)	//if 0 to 9
		{
			iDigit[iN] = pcHexStg[iN] & 0x0f;	//convert to int
		}
		else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f')	//if a to f
		{
			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
		}
		else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F')	//if A to F
		{
			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
		}
		else
		{
			break;
		}

	iN++;
    }

    iCount = iN;
    iM = iN - 1;
    iN = 0;

    while( iN < iCount)
    {
	// digit[n] is value of hex digit at position n
	// (m << 2) is the number of positions to shift
	// OR the bits into return value
		intValue = intValue | (iDigit[iN] << (iM << 2));
		iM--;			// adjust the position to set
		iN++;			// next digit to process
    }

    return intValue;
}

/* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
 * parse the HTTP header of the response message.
 */
void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
{
    unsigned int iPosition = std::string::npos;
    unsigned int iStartPosition = iPosition;

    if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
    {
		m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
		iPosition += strlen( "HTTP/1.x");

		while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
		{
			iPosition++;
		}

		iStartPosition = iPosition;

		while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
		{
			iPosition++;
		}

		std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
																				 iPosition - iStartPosition);
		m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());

		iStartPosition = ++iPosition;
		iPosition = m_strResponseHTTPHeaders.find( "\n");
		m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
																		  iPosition - iStartPosition - 1);

	// reached the end of the first line
		iStartPosition = m_strResponseHTTPHeaders.find( "\n");

		iStartPosition++;

	// read header fields and add to vector
		do
		{
		    m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
			iPosition = m_strResponseHTTPHeaders.find( "\n");

		    if( iPosition == std::string::npos)
		    {
				break;
			}

			std::string		strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
			unsigned int	iSeperator = strHeaderLine.find(":");

		    if( iSeperator == std::string::npos)
			{
				break;
			}

			iStartPosition = iPosition + 1;

			string	key = strHeaderLine.substr( 0, iSeperator);
			string	value = strHeaderLine.substr( iSeperator + 1,
												  strHeaderLine.length () - iSeperator - 1 - 1);

			m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));

	    // if HTTP/1.0 we have to always close the connection by default
		    if( m_eProtocolType == APTHTTP1_0)
			{
				m_bReopenConnection = true;
			}

	    // if HTTP/1.1 we have to assume persistant connection by default

	    // We need to close the connection and open a new one if we have 'Connection: close'
			if( key == "Connection" && value == " close")
			{
				m_bReopenConnection = true;
			}

	    // For both HTTP/1.0 and HTTP/1.1,
	    // We need to keep the connection if we have 'Connection: Keep-Alive'
			if( key == "Connection" && value == " Keep-Alive")
			{
				m_bReopenConnection = false;
			}

	    // Look for cookies
			if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
		    {
				if( key == "Set-Cookie")
				{
					m_strSessionKey = value;

		    // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
		    // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
		    // And discards stuff after first ';'
		    // This is the same assumption used in Axis Java
					unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
		    
					if( ulKeyEndsAt != std::string::npos)
				    {
						m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
				    }
				}
		    }

	    /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
	       start="<content id>" */
			if( key == "Content-Type")
			{
				m_strContentType = value;
		
				unsigned long	ulMimePos = m_strContentType.find( ";");
				std::string		strTypePart;

				if( ulMimePos != std::string::npos)
				{
					strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
				}
		
				if( "Multipart/Related" == strTypePart)
				{
					m_bMimeTrue = true;
					m_strContentType = m_strContentType.substr( ulMimePos + 1,
																m_strContentType.length());

				    ulMimePos = m_strContentType.find( "boundary=");
					m_strMimeBoundary = m_strContentType.substr( ulMimePos);
					ulMimePos = m_strMimeBoundary.find( ";");
					m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);

					ulMimePos = m_strContentType.find( "type=");
					m_strMimeType = m_strContentType.substr( ulMimePos);
					ulMimePos = m_strMimeType.find( ";");
					m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);

				    ulMimePos = m_strContentType.find( "start=");
					m_strMimeStart = m_strContentType.substr( ulMimePos);
					ulMimePos = m_strMimeStart.find( ";");
					m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
				}
			}
		} while( iPosition != std::string::npos);
    }
    else
    {
		throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
									  "Protocol is not HTTP.");
    }
}

/* HTTPTransport::processRootMimeBody() Is a public method used to
 * parse the mime attachments.
 */
void HTTPTransport::processRootMimeBody()
{
    if( false == m_bReadPastRootMimeHeader)
    {
		do
		{
			if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
			{
				m_pszRxBuffer [0] = '\0';
				*m_pActiveChannel >> m_pszRxBuffer;
				m_strReceived += m_pszRxBuffer;
			}
		} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);

	//now we have found the end of root mime header
		m_bReadPastRootMimeHeader = true;

	//processMimeHeader(); For the time being we don't process this
	// Done with root mime body headers, get rest of the payload 
	// which contain the soap message
		m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
	
		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);

		if (intMimeTemp != std::string::npos)
		{
			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
			m_strMimeReceived = m_strReceived.substr( intMimeTemp);

	    /* Using m_strMimeReceived will be 
	     * continued when getAttachment is called.
	     */
			m_bMimeTrue = false;
		}
    }
    else
    {
		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
		
		if( intMimeTemp != std::string::npos)
		{
			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
			m_strMimeReceived = m_strReceived.substr( intMimeTemp);

	    /* Using m_strMimeReceived will be 
	     * continued when getAttachment is called.
	     */
			m_bMimeTrue = false;
		}

	return;
    }
}

/* HTTPTransport::processMimeHeaders() Is a public method used to
 * parse the Mime headers of the response message.
 */
void HTTPTransport::processMimeHeader()
{
    unsigned int pos = 0;
    unsigned int temppos = 0;

    // Look for content lenght
    if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
	{
		m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
														 m_strMimeReceived.find( "\n", pos));
		pos = m_strMimeContentType.find( ";");
		temppos = m_strMimeContentType.find( "\r\n");

		if( pos < temppos)
		{
			m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
		}
		else
		{
			m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
		}
    }

    // Look for mime root body's content transfer encoding
    if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
	{
		m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
																     m_strMimeReceived.find( "\n", pos));
		temppos = m_strMimeContentTransferEncoding.find( "\r\n");
		m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
    }

    // Look for mime root body's content id
    if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
	{
		m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
													   m_strMimeReceived.find( "\n", pos));
		temppos = m_strMimeContentID.find( "\r\n");
		m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
    }

    // Look for mime root body's content location
    if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
    {
		m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
																   m_strMimeReceived.find( "\n", pos)).c_str());
		temppos = m_strMimeContentLocation.find( "\r\n");
		m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
    }
}

void HTTPTransport::processMimeBody ()
{
}

void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
{
	m_pszRxBuffer [0] = '\0';
	*m_pActiveChannel >> m_pszRxBuffer;
    m_strMimeReceived += m_pszRxBuffer;

    do
    {
		if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
		{
			m_pszRxBuffer [0] = '\0';
			*m_pActiveChannel >> m_pszRxBuffer;
		    m_strMimeReceived += m_pszRxBuffer;
		}
    } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);

    //now we have found the end of next mime header
    processMimeHeader();

    m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
    processMimeBody();
}

void HTTPTransport::setSocket( unsigned int uiNewSocket)
{
    m_pActiveChannel->setSocket( uiNewSocket);
}

const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
{
    std::string strKeyToFind = std::string( pcKey);

    for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
	{
		if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
		{
			return ((string) m_vResponseHTTPHeaders[i].second).c_str();
		}
    }

    return NULL;
}

const char * HTTPTransport::getFirstTransportPropertyKey()
{
    m_viCurrentHeader = m_vHTTPHeaders.begin ();

    if( m_viCurrentHeader == m_vHTTPHeaders.end())
	{
		return NULL;
	}
    else
	{
		return (*m_viCurrentHeader).first.c_str();
	}
}

const char * HTTPTransport::getNextTransportPropertyKey()
{
    //already at the end?
    if( m_viCurrentHeader == m_vHTTPHeaders.end())
	{
		return NULL;
	}

    m_viCurrentHeader++;

    if( m_viCurrentHeader == m_vHTTPHeaders.end())
	{
		return NULL;
	}
    else
	{
		return (*m_viCurrentHeader).first.c_str();
	}
}

const char * HTTPTransport::getCurrentTransportPropertyKey()
{
    if( m_viCurrentHeader == m_vHTTPHeaders.end())
	{
		return NULL;
	}
    else
	{
		return (*m_viCurrentHeader).first.c_str();
	}
}

const char * HTTPTransport::getCurrentTransportPropertyValue()
{
    if( m_viCurrentHeader == m_vHTTPHeaders.end())
	{
		return NULL;
	}
    else
	{
		return (*m_viCurrentHeader).second.c_str();
	}
}

void HTTPTransport::deleteCurrentTransportProperty()
{
    if( m_viCurrentHeader != m_vHTTPHeaders.end())
    {
		m_vHTTPHeaders.erase( m_viCurrentHeader);
    }
}

void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
{
    vector < std::pair < std::string,
	std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
    unsigned int uiCount = 1;

    while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
    {
		if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
		{
			if( uiCount == uiOccurance)
			{
				m_vHTTPHeaders.erase( currentHeader);
				break;
			}
	    
			uiCount++;
		}
	
		currentHeader++;
    }
}

void HTTPTransport::setMaintainSession( bool bSession)
{
    m_bMaintainSession = bSession;
}

void HTTPTransport::setSessionId( const char * pcSessionId)
{
    m_strSessionKey = std::string (pcSessionId);
}

const char * HTTPTransport::getSessionId()
{
    return m_strSessionKey.c_str();
}



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


[jira] Closed: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS

Posted by "Samisa Abeysinghe (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXISCPP-518?page=history ]
     
Samisa Abeysinghe closed AXISCPP-518:
-------------------------------------

     Resolution: Fixed
    Fix Version: 1.5 Final

Applied rest of the changes. Now all requasted changes are in CVS

> Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
> -------------------------------------------------------------------------------------------------------------
>
>          Key: AXISCPP-518
>          URL: http://issues.apache.org/jira/browse/AXISCPP-518
>      Project: Axis-C++
>         Type: Bug
>   Components: Transport (axis3)
>     Versions: unspecified
>  Environment: The bug affects all platforms
>     Reporter: Arcangelo Di Balsamo
>     Assignee: Samisa Abeysinghe
>      Fix For: 1.5 Final
>  Attachments: HTTPTransport.cpp, HTTPTransportcpp diff.txt, HTTPTrasportTestClient.zip
>
> I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
> The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
> I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation. 
> The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
> I've already made a fix: the affected module is HTTPTransport.cpp.
> The modified code is :
> /*
> *   Copyright 2003-2004 The Apache Software Foundation.
> *
> *   Licensed under the Apache License, Version 2.0 (the "License");
> *   you may not use this file except in compliance with the License.
> *   You may obtain a copy of the License at
> *
> *       http://www.apache.org/licenses/LICENSE-2.0
> *
> *   Unless required by applicable law or agreed to in writing, software
> *   distributed under the License is distributed on an "AS IS" BASIS,
> *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> *   See the License for the specific language governing permissions and
> *   limitations under the License.
> */
> /*
>  * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
>  *
>  */
> #ifdef WIN32
> #pragma warning (disable : 4786)
> #pragma warning (disable : 4101)
> #endif
> #include "HTTPTransport.hpp"
> #include <stdio.h>
> #include <iostream>
> /*
>  * HTTPTransport constuctor
>  */
> HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
> m_strHTTPProtocol ("HTTP/1.1"),
> m_strHTTPMethod ("POST"),
> m_bChunked (false),
> m_bReadPastHTTPHeaders (false),
> m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
> m_bMaintainSession (false)
> {
>     m_pcEndpointUri = NULL;
>     m_pReleaseBufferCallback = 0;
>     m_eProtocolType = APTHTTP1_1;
>     m_strBytesToSend = "";
>     m_strHeaderBytesToSend = "";
>     m_iBytesLeft = 0;
>     m_iContentLength = 0;
>     m_pcReceived = 0;
> 	m_bChannelSecure = false;
>     m_pNormalChannel = 0;
>     m_pSecureChannel = 0;
> 	m_pActiveChannel = 0;
>     m_pChannelFactory = new ChannelFactory();
>     m_bMimeTrue = false;
>     m_viCurrentHeader = m_vHTTPHeaders.begin();
> 	m_pszRxBuffer = new char [BUF_SIZE];
> #ifdef WIN32
> 	m_lChannelTimeout = 10;
> #else
> 	m_lChannelTimeout = 0;
> #endif
> }
> /*
>  * HTTPTransport destuctor
>  */
> HTTPTransport::~HTTPTransport()
> {
>     if( m_pcEndpointUri)
>     {
> 	delete[] m_pcEndpointUri;
>     }
>     if( m_pChannelFactory)
> 	{
> 		delete m_pChannelFactory;
> 		m_pChannelFactory = 0;
> 	}
> 	delete [] m_pszRxBuffer;
> }
> /*
>  * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
>  * Everytime the endpoint changes then currently connected channel is closed
>  * and a new channel connection is opened.
>  *
>  * @param	EndpointURI - char * to a null terminated string that holds the
>  *			new URI. 
>  */
> void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
> {
>     bool bUpdateURL = false;
>     // Get the current channel URI
>     if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
>     {
> 	// Does the new URI equal the existing channel URI?
> 		if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
> 		{
> 	    // There is a new URI.
> 			bUpdateURL = true;
> 		}
>     }
>     else
>     {
> 		bUpdateURL = true;
>     }
>     // If there is a new URI, then this flag will be set.  Depending on whether
>     // there is an SSL implementation available, if the new URI is a secure
> 	// connection, a secure channel will be opened.  If an SSL implementation
> 	// is not available and the URL requires a secure connection then an
> 	// exception will be thrown.
>     if( bUpdateURL)
>     {
> 		if( m_pActiveChannel == NULL)
> 		{
> 			m_pActiveChannel = m_pNormalChannel;
> 		}
> 		m_pActiveChannel->setURL( pcEndpointUri);
> 		m_bReopenConnection = true;
> 	// Check if the new URI requires SSL (denoted by the https prefix).
> 		if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
> 		{
> 			if( m_pSecureChannel != NULL)
> 			{
> 				m_pNormalChannel->close();
> 				m_pActiveChannel = m_pSecureChannel;
> 				m_pActiveChannel->setURL( pcEndpointUri);
> 				m_bChannelSecure = true;
> 			}
> 			if( !m_bChannelSecure)
> 			{
> 				throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
> 			}
> 		}
> 		else
> 		{
> 	    // URI does not require a secure channel.  Delete the existing
> 	    // channel if it is secure and create a new unsecure
> 	    // channel.
> 			if (m_bChannelSecure)
> 			{
> 				if( m_pNormalChannel != NULL)
> 				{
> 					m_pSecureChannel->close();
> 					m_pActiveChannel = m_pNormalChannel;
> 					m_pActiveChannel->setURL( pcEndpointUri);
> 					m_bChannelSecure = false;
> 				}
> 				if( m_bChannelSecure)
> 				{
> 					throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
> 				}
> 			}
> 		}
>     }
> // Need this code to set the channel timeout.  If the timeout was changed
> // before the channel was created, then it may not have the correct timeout.
> // By setting it here, the channel is sure to have the correct timeout value
> // next time the channel is read.
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( m_lChannelTimeout);
> 	}
> }
> /*
>  * HTTPTransport::openConnection().
>  */
> int HTTPTransport::openConnection()
> {
> 	return m_pActiveChannel->open();
> }
> /*
>  * HTTPTransport::closeConnection().
>  */
> void HTTPTransport::closeConnection()
> {
>     // get ready for a new message.
>     m_bReadPastHTTPHeaders = false;
>     //clear the message buffer in preperation of the next read.
>     m_strReceived = "";
>     m_iContentLength = 0;
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->close();
> 	}
> }
> /*
>  * HTTPTransport::flushOutput() Is called when the message construction is
>  * complete.  The message is ready to be 'flushed out' onto the network.  
>  * Check if the URI has changed.  If it has, then need to open a new Channel
>  * instance before transmitting the message.
>  *
>  * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
>  * this will be set to TRANSPORT_FINISHED.  Otherwise, an exception will have
>  * been thrown.
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
> {
>     if( m_bReopenConnection)
>     {
> 		m_bReopenConnection = false;
> 		if( m_pActiveChannel->open() != AXIS_SUCCESS)
> 		{
> 		    int				iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
> 			const char *	pszLastError = new char[iStringLength];
> 		    memcpy( (void *) pszLastError,
> 					m_pActiveChannel->GetLastErrorMsg().c_str(),
> 					iStringLength);
> 		    throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
> 										  (char *) pszLastError);
> 			}
> 		}
>     // In preperation for sending the message, calculate the size of the message
>     // by using the string length method.
>     // NB: This calculation may not necessarily be correct when dealing with SSL
>     //     messages as the length of the encoded message is not necessarily the
>     //         same as the length of the uncoded message.
>     char buff[8];
> 	sprintf( buff, "%d", m_strBytesToSend.length ());
>     this->setTransportProperty ("Content-Length", buff);
>     // The header is now complete.  The message header and message can now be
>     // transmitted.
> 	try
> 	{
> 		*m_pActiveChannel << this->getHTTPHeaders ();
> 		*m_pActiveChannel << this->m_strBytesToSend.c_str ();
> 	}
> 	catch( HTTPTransportException & e)
> 	{
> 		throw;
> 	}
> 	catch( AxisException & e)
> 	{
> 		throw;
> 	}
> 	catch(...)
> 	{
> 		throw;
> 	}
>     // Empty the bytes to send string.
> 	m_strBytesToSend = "";
> 	m_strHeaderBytesToSend = "";
> 	return TRANSPORT_FINISHED;
> }
> /* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
>  * information block that will preceed the SOAP message.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP header block of information.
>  */
> const char * HTTPTransport::getHTTPHeaders()
> {
>     URL &			url = m_pActiveChannel->getURLObject();
>     unsigned short	uiPort = url.getPort();
>     char			buff[8];
>     m_strHeaderBytesToSend = m_strHTTPMethod + " ";
>     m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
>     m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
>     m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();
>     sprintf (buff, "%u", uiPort);
>     m_strHeaderBytesToSend += ":";
>     m_strHeaderBytesToSend += buff;
>     m_strHeaderBytesToSend += "\r\n";
>     m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";
>     // Set other HTTP headers
>     for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
>     {
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     // Set session cookie
>     if (m_bMaintainSession && (m_strSessionKey.size () > 0))
>     {
> 		m_strHeaderBytesToSend += "Cookie";
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_strSessionKey;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     m_strHeaderBytesToSend += "\r\n";
>     return m_strHeaderBytesToSend.c_str ();
> }
> /* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
>  * (i.e. GET or POST) that will be part of the HTTP header block.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP method.
>  */
> const char * HTTPTransport::getHTTPMethod()
> {
>     return m_strHTTPMethod.c_str ();
> }
> /* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
>  * method (i.e. POST or GET) that will be part of the HTTP header block.
>  *
>  * @param const char* Pointer to a NULL terminated character string containing
>  * the new HTTP method.
>  */
> void HTTPTransport::setHTTPMethod( const char *cpMethod)
> {
>     m_strHTTPMethod = std::string( cpMethod);
> }
> /* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
>  * concatinates the new send buffer to the bytes to send string.  This message
>  * will only be sent when a flush buffer is received.
>  *
>  * @param const char* SendBufer - Pointer to a NULL terminated character string
>  * containing all or some of the transmission message.
>  * @param const void* BufferId - Pointer.  This parameter is ignored.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
>  * always be TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
> {
>     m_strBytesToSend += std::string (pcSendBuffer);
>     return TRANSPORT_IN_PROGRESS;
> }
> /* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
>  * receive the synchronous reply to the sent message.
>  *
>  * @param const char* ReceiveBuffer - Pointer to a character string that on
>  * return will containing all or part of the received message.
>  * @param int* Size - Pointer to an integer value that on return will contain
>  * the length of the received message.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
>  * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
> {
>     if (0 >= m_iBytesLeft)
>     {
> 		try
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 			m_strReceived = m_pszRxBuffer;
> 		    if( !m_bReadPastHTTPHeaders)
> 		    {
> 				unsigned int start = std::string::npos;
> 				do
> 				{
> 					do
> 					{
> 						if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 						    m_strReceived += m_pszRxBuffer;
> 						}
> 					} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 					if( m_strReceived.find ("HTTP") == std::string::npos)
> 					{
> 			// Most probably what we read was left overs from earlier reads
> 			// Skip this \r\n\r\n
> 						m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 						do
> 						{
> 							if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 							{
> 								m_pszRxBuffer [0] = '\0';
> 								*m_pActiveChannel >> m_pszRxBuffer;
> 								m_strReceived += m_pszRxBuffer;
> 							}
> 						} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 			// now this must contain HTTP. Else there is a conent error.
> 					}
> 		    //now we have found the end of headers
> 					m_bReadPastHTTPHeaders = true;
> 				    unsigned int pos = 0;
> 		    // Look for content lenght
> 				    if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
> 					{
> 						m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
> 																	   m_strReceived.find( "\n", pos)).c_str());
> 				    }
> 		    // Check if the message is chunked
> 				    if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
> 					{
> 						m_bChunked = true;
> 					}
> 					else
> 					{
> 						m_bChunked = false;
> 					}
> 		    // check if there is HTTP header. If not, there must be an error and 
> 		    // will be detected by processResponseHTTPHeaders()
> 		    // However, must make sure that the left overs from eatlier reads
> 		    // do not appear before HTTP/1.x
> 					start = m_strReceived.find( "HTTP");
> 					if( start == std::string::npos)
> 					{
> 						start = 0;
> 					}
> 		    // Extract HTTP headers and process them
> 				    m_strResponseHTTPHeaders = m_strReceived.substr( start,
> 																     m_strReceived.find( "\r\n\r\n") + 2 - start);
> 				    processResponseHTTPHeaders();
> 				    if( m_iResponseHTTPStatusCode == 100)
> 				    {
> 			// Samisa: We found Continue. Keep on reading and processing headers
> 			// till we get a HTTP code other than 100
> 			// Here it is assumed that the whole of the request is already sent
> 						m_pszRxBuffer [0] = '\0';
> 						*m_pActiveChannel >> m_pszRxBuffer;
> 						m_strReceived = m_pszRxBuffer;
> 					}
> 				} while( m_iResponseHTTPStatusCode == 100);
>                 if ( m_iResponseHTTPStatusCode != 500 &&
>                     ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
> 				{
> 				    throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
> 												  const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
> 				}
> 		// Done with HTTP headers, get payload
> 				m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
> 		    }
> 	    // Read past headers. Deal with payload
> 	    // make sure we have a message with some content
> 		    if( m_strReceived.length () == 0)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived = m_pszRxBuffer;
> 			}
> 			if( m_strReceived.length () > 0) 
> 			{
> 			    if( m_bChunked && m_iContentLength < 1)	// Read first chunk
> 				{
> 			/*
> 			 *Chunked data looks like ->
> 			 *      Chunked-Body   = *chunk
> 			 *                       "0" CRLF
> 			 *                       footer
> 			 *                       CRLF
> 			 *
> 			 *      chunk          = chunk-size [ chunk-ext ] CRLF
> 			 *                         chunk-data CRLF
> 			 *
> 			 *      hex-no-zero    = <HEX excluding "0">
> 			 *
> 			 *      chunk-size     = hex-no-zero *HEX
> 			 *      chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
> 			 *      chunk-ext-name = token
> 			 *      chunk-ext-val  = token | quoted-string
> 			 *      chunk-data     = chunk-size(OCTET)
> 			 *
> 			 *      footer         = *entity-header
> 			 */
> 			// firstly read in the chunk size line.
> 			//There might be chunk extensions in there too but we may not need them
> 					unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 			// make sure we have read at least some part of the message
> 					if( endOfChunkData == std::string::npos)
> 					{
> 						do
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived = m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						} while( endOfChunkData == std::string::npos);
> 					}
> 					int endOfChunkSize = endOfChunkData;
> 			// now get the size of the chunk from the data
> 			// look to see if there are any extensions - these are put in brackets so look for those
> 					if( m_strReceived.substr( 0, endOfChunkData).find( "(") != string::npos)
> 					{
> 						endOfChunkSize = m_strReceived.find( "(");
> 					}
> 			// convert the hex String into the length of the chunk
> 					m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 			// if the chunk size is zero then we have reached the footer
> 			// If we have reached the footer then we can throw it away because we don't need it
> 					if( m_iContentLength > 0)
> 					{
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 						if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
> 						}
> 						else	// we have read lesser than chunk length
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 						}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 					else
> 					{
> 						m_strReceived = "";
> 					}
> 				}
> 				else if( m_bChunked)	// read continued portions of a chunk
> 				{
> 			// Samisa - NOTE: It looks as if there is some logic duplication
> 			// in this block, where we read continued chunks and the block
> 			// above, where we read the first chunk. However, there are slight
> 			// logical differences here, and that is necessary to enable the
> 			// pull model used by the parser - this logic makes pulling more
> 			// efficient (30th Sept 2004)
> 					if( m_strReceived.length () >= m_iContentLength)	// We have reached end of current chunk
> 					{
> 				// Get remainder of current chunk
> 						std::string strTemp = m_strReceived.substr( 0, m_iContentLength);
> 				// Start looking for the next chunk
> 				// The format we are expecting here is:
> 				// <previous chunk>\r\n<chunk size>\r\n<next chunk>
> 						unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 				// Make sure that we have the found the end of previous chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						m_strReceived = m_strReceived.substr( endOfChunkData + 2);	// Skip end of previous chunk
> 						endOfChunkData = m_strReceived.find( "\r\n");	// Locate the start of next chunk
> 				// Make sure that we have the starting line of next chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						int endOfChunkSize = endOfChunkData;
> 				// look to see if there are any extensions - these are put in brackets so look for those
> 						if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
> 						{
> 							endOfChunkSize = m_strReceived.find ("(");
> 						}
> 				// convert the hex String into the length of the chunk
> 						int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 				// if the chunk size is zero then we have reached the footer
> 				// If we have reached the footer then we can throw it away because we don't need it
> 						if( iTempContentLength > 0)
> 						{
> 				// Update the content lenght to be remainde of previous chunk and lenght of new chunk
> 							m_iContentLength += iTempContentLength;
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 							if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
> 							}
> 							else
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 							}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 							if( m_bMimeTrue)
> 							{
> 								processRootMimeBody();
> 							}
> 						}
> 						else
> 						{
> 							m_strReceived = "";
> 						}
> 				// Append the data of new chunk to data from previous chunk
> 						m_strReceived = strTemp + m_strReceived;
> 						}		// End of if (m_strReceived.length() >= m_iContentLength)
> 			// If we have not reached end of current chunk, nothing to be done
> 					}
> 					else		// Not chunked
> 					{
> 				//nothing to do here
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 				}
> 				m_pcReceived = m_strReceived.c_str();
> 				if( m_pcReceived)
> 				{
> 					m_iBytesLeft = strlen( m_pcReceived);
> 				}
> 				else
> 				{
> 					throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
> 				}
> 				m_iContentLength -= m_iBytesLeft;
> 		}
> 		catch( HTTPTransportException & e)
> 		{
> 			throw;
> 		}
> 		catch( AxisException & e)
> 		{
> 		    throw;
> 		}
> 		catch(...)
> 		{
> 		    throw;
> 		}
>     }
>     if (( m_pcReceived) && (*m_pcReceived))
>     {
> 		int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;
> 		strncpy( pcBuffer, m_pcReceived, iToCopy);
> 		m_iBytesLeft -= iToCopy;
> 		m_pcReceived += iToCopy;
> 		*pSize = iToCopy;
> 		return TRANSPORT_IN_PROGRESS;
> 	}
> 	else
> 	{
> 		m_bReadPastHTTPHeaders = false;	// get ready for a new message
> 		m_strReceived = "";	//clear the message buffer in preperation of the next read
> 		return TRANSPORT_FINISHED;
>     }
> }
> /* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
> {
>     const char *key = NULL;
>     switch (type)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			key = "SOAPAction";
> 		    break;
> 		}
> 		case SERVICE_URI:		// need to set ?
> 		{
> 			break;
> 		}
> 		case OPERATION_NAME:	// need to set ?
> 		{
> 			break;
> 		}
> 		case SOAP_MESSAGE_LENGTH:
> 		{
> 			key = "Content-Length";	// this Axis transport handles only HTTP
> 			break;
> 		}
> 		case TRANSPORT_PROPERTIES:
> 		{
> 			m_pActiveChannel->setTransportProperty( type, value);
> 			break;
> 		}
> 		case SECURE_PROPERTIES:
> 		{
> 			m_pActiveChannel->setSecureProperties( value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_SSL_DLL_NAME:
> 		{
> 			m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
> 			break;
> 		}
> 		default:
> 		{
> 			break;
> 		}
>     }
>     if( key)
>     {
> 		setTransportProperty( key, value);
>     }
> }
> /* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param const char* Key is a NULL terminated character string containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
> {
>     if( !pcKey || !pcValue)	// Samisa - fix for AXISCPP-295. We must check for valid values here.
> 	{
> 		return;
> 	}
>     bool b_KeyFound = false;
>     if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
>     {
> 		std::string strKeyToFind = std::string( pcKey);
> 		for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
> 		{
> 		    if (m_vHTTPHeaders[i].first == strKeyToFind)
> 			{
> 				m_vHTTPHeaders[i].second = (string) pcValue;
> 				b_KeyFound = true;
> 				break;
> 		    }
> 		}
>     }
>     if( !b_KeyFound)
>     {
> 		m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
>     }
> }
> /* HTTPTransport::getTransportProperty( Type) Is a public method that will
>  * return the HTTP Header/SSL implementation value associated with type.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header or SSL
>  * implementation settings.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
> {
>     const char *pszPropValue = NULL;
>     switch( eType)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "SOAPAction");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	    case SERVICE_URI:
> 		{
> 			break;
> 		}
> 	    case OPERATION_NAME:
> 		{
> 			break;
> 		}
> 	    case SOAP_MESSAGE_LENGTH:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "Content-Length");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	case TRANSPORT_PROPERTIES:
>     case SECURE_PROPERTIES:
> 		{
> 			pszPropValue = m_pActiveChannel->getTransportProperty( eType);
> 			break;
> 		}
> 	case CHANNEL_HTTP_SSL_DLL_NAME:
> 	case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			break;
> 		}
>     }
>     return pszPropValue;
> }
> /* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
>  * return the HTTP Header index associated with Key.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header settings.
>  *
>  * @return int Index is an index to the key within the HTTP Header list.  If
>  * the return value is -1, then the key was not found.
>  */
> int HTTPTransport::FindTransportPropertyIndex( string sKey)
> {
>     bool	bKeyFound = false;
>     int		iIndex = 0;
>     do
>     {
> 		if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
> 		{
> 			bKeyFound = true;
> 		}
> 		else
> 		{
> 			iIndex++;
> 		}
>     } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);
>     if( !bKeyFound)
>     {
> 		iIndex = -1;
>     }
>     return iIndex;
> }
> /* HTTPTransport::getServiceName() Is a public method to return the HTTP
>  * Header service name.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the service name.
>  */
> const char * HTTPTransport::getServiceName()
> {
>     //Assume SOAPAction header to contain service name
>     int		iIndex = FindTransportPropertyIndex( "SOAPAction");
>     if (iIndex > -1)
>     {
> 		return m_vHTTPHeaders[iIndex].second.c_str();
>     }
>     return NULL;
> }
> AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
> {
>     return m_eProtocolType;
> }
> int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
> {
>     if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
>     {
> 		m_eProtocolType = eProtocol;
> 		m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";
> 		return AXIS_SUCCESS;
>     }
>     else
> 	{
> 		return AXIS_FAIL;
> 	}
> }
> /**
>  * HTTPTransport::getSubProtocol() is a public method that is supposed to
>  * return the sub protocol (currently this method always return 0).
>  * This method is supposed to return whether it is http GET or POST
>  */
> int HTTPTransport::getSubProtocol()
> {
>     //TODO
>     // for SimpleAxisServer assume POST
>     return AXIS_HTTP_POST;
>     //return 0;
> }
> /* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
>  * updating the proxy for the connection.
>  *
>  * @param const char* Host is a NULL terminated character string containing the new
>  * proxy host.
>  * @param unsigned int Port is the new proxy port number.
>  */
> void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
> {
>     m_strProxyHost = pcProxyHost;
>     m_uiProxyPort = uiProxyPort;
>     m_bUseProxy = true;
> }
> /* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
>  * current maximum timeout period between that can elapse between receiving
>  * message parts.
>  *
>  * @param const long Timeout is a long value in seconds.
>  */
> void HTTPTransport::setTimeout( const long lSeconds)
> {
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( lSeconds);
> 	}
> 	m_lChannelTimeout = lSeconds;
> }
> /* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
>  * current HTTP protocol settings.
>  *
>  * @return const char* HTTPProtocol is a NULL terminated character string
>  * containing the HTTP protocol.
>  */
> const char * HTTPTransport::getHTTPProtocol()
> {
>     return m_strHTTPProtocol.c_str ();
> }
> /* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
>  */
> int axtoi( char *pcHexStg)
> {
>     int		iN = 0;			// position in string
>     int		iM = 0;			// position in digit[] to shift
>     int		iCount;			// loop index
>     int		intValue = 0;	// integer value of hex string
>     int		iDigit[32];		// hold values to convert
>     while( iN < 32)
>     {
> 		if( pcHexStg[iN] == '\0')
> 		{
> 			break;
> 		}
> 	
> 		if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40)	//if 0 to 9
> 		{
> 			iDigit[iN] = pcHexStg[iN] & 0x0f;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f')	//if a to f
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F')	//if A to F
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else
> 		{
> 			break;
> 		}
> 	iN++;
>     }
>     iCount = iN;
>     iM = iN - 1;
>     iN = 0;
>     while( iN < iCount)
>     {
> 	// digit[n] is value of hex digit at position n
> 	// (m << 2) is the number of positions to shift
> 	// OR the bits into return value
> 		intValue = intValue | (iDigit[iN] << (iM << 2));
> 		iM--;			// adjust the position to set
> 		iN++;			// next digit to process
>     }
>     return intValue;
> }
> /* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
>  * parse the HTTP header of the response message.
>  */
> void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
> {
>     unsigned int iPosition = std::string::npos;
>     unsigned int iStartPosition = iPosition;
>     if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
>     {
> 		m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
> 		iPosition += strlen( "HTTP/1.x");
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
> 		{
> 			iPosition++;
> 		}
> 		iStartPosition = iPosition;
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
> 		{
> 			iPosition++;
> 		}
> 		std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																				 iPosition - iStartPosition);
> 		m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());
> 		iStartPosition = ++iPosition;
> 		iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																		  iPosition - iStartPosition - 1);
> 	// reached the end of the first line
> 		iStartPosition = m_strResponseHTTPHeaders.find( "\n");
> 		iStartPosition++;
> 	// read header fields and add to vector
> 		do
> 		{
> 		    m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
> 			iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		    if( iPosition == std::string::npos)
> 		    {
> 				break;
> 			}
> 			std::string		strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
> 			unsigned int	iSeperator = strHeaderLine.find(":");
> 		    if( iSeperator == std::string::npos)
> 			{
> 				break;
> 			}
> 			iStartPosition = iPosition + 1;
> 			string	key = strHeaderLine.substr( 0, iSeperator);
> 			string	value = strHeaderLine.substr( iSeperator + 1,
> 												  strHeaderLine.length () - iSeperator - 1 - 1);
> 			m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
> 	    // if HTTP/1.0 we have to always close the connection by default
> 		    if( m_eProtocolType == APTHTTP1_0)
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // if HTTP/1.1 we have to assume persistant connection by default
> 	    // We need to close the connection and open a new one if we have 'Connection: close'
> 			if( key == "Connection" && value == " close")
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // For both HTTP/1.0 and HTTP/1.1,
> 	    // We need to keep the connection if we have 'Connection: Keep-Alive'
> 			if( key == "Connection" && value == " Keep-Alive")
> 			{
> 				m_bReopenConnection = false;
> 			}
> 	    // Look for cookies
> 			if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
> 		    {
> 				if( key == "Set-Cookie")
> 				{
> 					m_strSessionKey = value;
> 		    // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
> 		    // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
> 		    // And discards stuff after first ';'
> 		    // This is the same assumption used in Axis Java
> 					unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
> 		    
> 					if( ulKeyEndsAt != std::string::npos)
> 				    {
> 						m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
> 				    }
> 				}
> 		    }
> 	    /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
> 	       start="<content id>" */
> 			if( key == "Content-Type")
> 			{
> 				m_strContentType = value;
> 		
> 				unsigned long	ulMimePos = m_strContentType.find( ";");
> 				std::string		strTypePart;
> 				if( ulMimePos != std::string::npos)
> 				{
> 					strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
> 				}
> 		
> 				if( "Multipart/Related" == strTypePart)
> 				{
> 					m_bMimeTrue = true;
> 					m_strContentType = m_strContentType.substr( ulMimePos + 1,
> 																m_strContentType.length());
> 				    ulMimePos = m_strContentType.find( "boundary=");
> 					m_strMimeBoundary = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeBoundary.find( ";");
> 					m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
> 					ulMimePos = m_strContentType.find( "type=");
> 					m_strMimeType = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeType.find( ";");
> 					m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);
> 				    ulMimePos = m_strContentType.find( "start=");
> 					m_strMimeStart = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeStart.find( ";");
> 					m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
> 				}
> 			}
> 		} while( iPosition != std::string::npos);
>     }
>     else
>     {
> 		throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
> 									  "Protocol is not HTTP.");
>     }
> }
> /* HTTPTransport::processRootMimeBody() Is a public method used to
>  * parse the mime attachments.
>  */
> void HTTPTransport::processRootMimeBody()
> {
>     if( false == m_bReadPastRootMimeHeader)
>     {
> 		do
> 		{
> 			if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived += m_pszRxBuffer;
> 			}
> 		} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 	//now we have found the end of root mime header
> 		m_bReadPastRootMimeHeader = true;
> 	//processMimeHeader(); For the time being we don't process this
> 	// Done with root mime body headers, get rest of the payload 
> 	// which contain the soap message
> 		m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 	
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		if (intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
>     }
>     else
>     {
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		
> 		if( intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
> 	return;
>     }
> }
> /* HTTPTransport::processMimeHeaders() Is a public method used to
>  * parse the Mime headers of the response message.
>  */
> void HTTPTransport::processMimeHeader()
> {
>     unsigned int pos = 0;
>     unsigned int temppos = 0;
>     // Look for content lenght
>     if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
> 	{
> 		m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
> 														 m_strMimeReceived.find( "\n", pos));
> 		pos = m_strMimeContentType.find( ";");
> 		temppos = m_strMimeContentType.find( "\r\n");
> 		if( pos < temppos)
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
> 		}
> 		else
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
> 		}
>     }
>     // Look for mime root body's content transfer encoding
>     if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
> 	{
> 		m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
> 																     m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentTransferEncoding.find( "\r\n");
> 		m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
>     }
>     // Look for mime root body's content id
>     if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
> 	{
> 		m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
> 													   m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentID.find( "\r\n");
> 		m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
>     }
>     // Look for mime root body's content location
>     if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
>     {
> 		m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
> 																   m_strMimeReceived.find( "\n", pos)).c_str());
> 		temppos = m_strMimeContentLocation.find( "\r\n");
> 		m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
>     }
> }
> void HTTPTransport::processMimeBody ()
> {
> }
> void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
> {
> 	m_pszRxBuffer [0] = '\0';
> 	*m_pActiveChannel >> m_pszRxBuffer;
>     m_strMimeReceived += m_pszRxBuffer;
>     do
>     {
> 		if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 		    m_strMimeReceived += m_pszRxBuffer;
> 		}
>     } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);
>     //now we have found the end of next mime header
>     processMimeHeader();
>     m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
>     processMimeBody();
> }
> void HTTPTransport::setSocket( unsigned int uiNewSocket)
> {
>     m_pActiveChannel->setSocket( uiNewSocket);
> }
> const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
> {
>     std::string strKeyToFind = std::string( pcKey);
>     for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
> 	{
> 		if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
> 		{
> 			return ((string) m_vResponseHTTPHeaders[i].second).c_str();
> 		}
>     }
>     return NULL;
> }
> const char * HTTPTransport::getFirstTransportPropertyKey()
> {
>     m_viCurrentHeader = m_vHTTPHeaders.begin ();
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getNextTransportPropertyKey()
> {
>     //already at the end?
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     m_viCurrentHeader++;
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyKey()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyValue()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).second.c_str();
> 	}
> }
> void HTTPTransport::deleteCurrentTransportProperty()
> {
>     if( m_viCurrentHeader != m_vHTTPHeaders.end())
>     {
> 		m_vHTTPHeaders.erase( m_viCurrentHeader);
>     }
> }
> void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
> {
>     vector < std::pair < std::string,
> 	std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
>     unsigned int uiCount = 1;
>     while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
>     {
> 		if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
> 		{
> 			if( uiCount == uiOccurance)
> 			{
> 				m_vHTTPHeaders.erase( currentHeader);
> 				break;
> 			}
> 	    
> 			uiCount++;
> 		}
> 	
> 		currentHeader++;
>     }
> }
> void HTTPTransport::setMaintainSession( bool bSession)
> {
>     m_bMaintainSession = bSession;
> }
> void HTTPTransport::setSessionId( const char * pcSessionId)
> {
>     m_strSessionKey = std::string (pcSessionId);
> }
> const char * HTTPTransport::getSessionId()
> {
>     return m_strSessionKey.c_str();
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


[jira] Updated: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS

Posted by "Arcangelo Di Balsamo (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXISCPP-518?page=history ]

Arcangelo Di Balsamo updated AXISCPP-518:
-----------------------------------------

    Attachment: HTTPTrasportTestClient.zip
                HTTPTransport.cpp

> Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
> -------------------------------------------------------------------------------------------------------------
>
>          Key: AXISCPP-518
>          URL: http://issues.apache.org/jira/browse/AXISCPP-518
>      Project: Axis-C++
>         Type: Bug
>   Components: Transport (axis3)
>     Versions: unspecified
>  Environment: The bug affects all platforms
>     Reporter: Arcangelo Di Balsamo
>  Attachments: HTTPTransport.cpp, HTTPTrasportTestClient.zip
>
> I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
> The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
> I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation. 
> The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
> I've already made a fix: the affected module is HTTPTransport.cpp.
> The modified code is :
> /*
> *   Copyright 2003-2004 The Apache Software Foundation.
> *
> *   Licensed under the Apache License, Version 2.0 (the "License");
> *   you may not use this file except in compliance with the License.
> *   You may obtain a copy of the License at
> *
> *       http://www.apache.org/licenses/LICENSE-2.0
> *
> *   Unless required by applicable law or agreed to in writing, software
> *   distributed under the License is distributed on an "AS IS" BASIS,
> *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> *   See the License for the specific language governing permissions and
> *   limitations under the License.
> */
> /*
>  * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
>  *
>  */
> #ifdef WIN32
> #pragma warning (disable : 4786)
> #pragma warning (disable : 4101)
> #endif
> #include "HTTPTransport.hpp"
> #include <stdio.h>
> #include <iostream>
> /*
>  * HTTPTransport constuctor
>  */
> HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
> m_strHTTPProtocol ("HTTP/1.1"),
> m_strHTTPMethod ("POST"),
> m_bChunked (false),
> m_bReadPastHTTPHeaders (false),
> m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
> m_bMaintainSession (false)
> {
>     m_pcEndpointUri = NULL;
>     m_pReleaseBufferCallback = 0;
>     m_eProtocolType = APTHTTP1_1;
>     m_strBytesToSend = "";
>     m_strHeaderBytesToSend = "";
>     m_iBytesLeft = 0;
>     m_iContentLength = 0;
>     m_pcReceived = 0;
> 	m_bChannelSecure = false;
>     m_pNormalChannel = 0;
>     m_pSecureChannel = 0;
> 	m_pActiveChannel = 0;
>     m_pChannelFactory = new ChannelFactory();
>     m_bMimeTrue = false;
>     m_viCurrentHeader = m_vHTTPHeaders.begin();
> 	m_pszRxBuffer = new char [BUF_SIZE];
> #ifdef WIN32
> 	m_lChannelTimeout = 10;
> #else
> 	m_lChannelTimeout = 0;
> #endif
> }
> /*
>  * HTTPTransport destuctor
>  */
> HTTPTransport::~HTTPTransport()
> {
>     if( m_pcEndpointUri)
>     {
> 	delete[] m_pcEndpointUri;
>     }
>     if( m_pChannelFactory)
> 	{
> 		delete m_pChannelFactory;
> 		m_pChannelFactory = 0;
> 	}
> 	delete [] m_pszRxBuffer;
> }
> /*
>  * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
>  * Everytime the endpoint changes then currently connected channel is closed
>  * and a new channel connection is opened.
>  *
>  * @param	EndpointURI - char * to a null terminated string that holds the
>  *			new URI. 
>  */
> void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
> {
>     bool bUpdateURL = false;
>     // Get the current channel URI
>     if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
>     {
> 	// Does the new URI equal the existing channel URI?
> 		if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
> 		{
> 	    // There is a new URI.
> 			bUpdateURL = true;
> 		}
>     }
>     else
>     {
> 		bUpdateURL = true;
>     }
>     // If there is a new URI, then this flag will be set.  Depending on whether
>     // there is an SSL implementation available, if the new URI is a secure
> 	// connection, a secure channel will be opened.  If an SSL implementation
> 	// is not available and the URL requires a secure connection then an
> 	// exception will be thrown.
>     if( bUpdateURL)
>     {
> 		if( m_pActiveChannel == NULL)
> 		{
> 			m_pActiveChannel = m_pNormalChannel;
> 		}
> 		m_pActiveChannel->setURL( pcEndpointUri);
> 		m_bReopenConnection = true;
> 	// Check if the new URI requires SSL (denoted by the https prefix).
> 		if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
> 		{
> 			if( m_pSecureChannel != NULL)
> 			{
> 				m_pNormalChannel->close();
> 				m_pActiveChannel = m_pSecureChannel;
> 				m_pActiveChannel->setURL( pcEndpointUri);
> 				m_bChannelSecure = true;
> 			}
> 			if( !m_bChannelSecure)
> 			{
> 				throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
> 			}
> 		}
> 		else
> 		{
> 	    // URI does not require a secure channel.  Delete the existing
> 	    // channel if it is secure and create a new unsecure
> 	    // channel.
> 			if (m_bChannelSecure)
> 			{
> 				if( m_pNormalChannel != NULL)
> 				{
> 					m_pSecureChannel->close();
> 					m_pActiveChannel = m_pNormalChannel;
> 					m_pActiveChannel->setURL( pcEndpointUri);
> 					m_bChannelSecure = false;
> 				}
> 				if( m_bChannelSecure)
> 				{
> 					throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
> 				}
> 			}
> 		}
>     }
> // Need this code to set the channel timeout.  If the timeout was changed
> // before the channel was created, then it may not have the correct timeout.
> // By setting it here, the channel is sure to have the correct timeout value
> // next time the channel is read.
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( m_lChannelTimeout);
> 	}
> }
> /*
>  * HTTPTransport::openConnection().
>  */
> int HTTPTransport::openConnection()
> {
> 	return m_pActiveChannel->open();
> }
> /*
>  * HTTPTransport::closeConnection().
>  */
> void HTTPTransport::closeConnection()
> {
>     // get ready for a new message.
>     m_bReadPastHTTPHeaders = false;
>     //clear the message buffer in preperation of the next read.
>     m_strReceived = "";
>     m_iContentLength = 0;
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->close();
> 	}
> }
> /*
>  * HTTPTransport::flushOutput() Is called when the message construction is
>  * complete.  The message is ready to be 'flushed out' onto the network.  
>  * Check if the URI has changed.  If it has, then need to open a new Channel
>  * instance before transmitting the message.
>  *
>  * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
>  * this will be set to TRANSPORT_FINISHED.  Otherwise, an exception will have
>  * been thrown.
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
> {
>     if( m_bReopenConnection)
>     {
> 		m_bReopenConnection = false;
> 		if( m_pActiveChannel->open() != AXIS_SUCCESS)
> 		{
> 		    int				iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
> 			const char *	pszLastError = new char[iStringLength];
> 		    memcpy( (void *) pszLastError,
> 					m_pActiveChannel->GetLastErrorMsg().c_str(),
> 					iStringLength);
> 		    throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
> 										  (char *) pszLastError);
> 			}
> 		}
>     // In preperation for sending the message, calculate the size of the message
>     // by using the string length method.
>     // NB: This calculation may not necessarily be correct when dealing with SSL
>     //     messages as the length of the encoded message is not necessarily the
>     //         same as the length of the uncoded message.
>     char buff[8];
> 	sprintf( buff, "%d", m_strBytesToSend.length ());
>     this->setTransportProperty ("Content-Length", buff);
>     // The header is now complete.  The message header and message can now be
>     // transmitted.
> 	try
> 	{
> 		*m_pActiveChannel << this->getHTTPHeaders ();
> 		*m_pActiveChannel << this->m_strBytesToSend.c_str ();
> 	}
> 	catch( HTTPTransportException & e)
> 	{
> 		throw;
> 	}
> 	catch( AxisException & e)
> 	{
> 		throw;
> 	}
> 	catch(...)
> 	{
> 		throw;
> 	}
>     // Empty the bytes to send string.
> 	m_strBytesToSend = "";
> 	m_strHeaderBytesToSend = "";
> 	return TRANSPORT_FINISHED;
> }
> /* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
>  * information block that will preceed the SOAP message.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP header block of information.
>  */
> const char * HTTPTransport::getHTTPHeaders()
> {
>     URL &			url = m_pActiveChannel->getURLObject();
>     unsigned short	uiPort = url.getPort();
>     char			buff[8];
>     m_strHeaderBytesToSend = m_strHTTPMethod + " ";
>     m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
>     m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
>     m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();
>     sprintf (buff, "%u", uiPort);
>     m_strHeaderBytesToSend += ":";
>     m_strHeaderBytesToSend += buff;
>     m_strHeaderBytesToSend += "\r\n";
>     m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";
>     // Set other HTTP headers
>     for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
>     {
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     // Set session cookie
>     if (m_bMaintainSession && (m_strSessionKey.size () > 0))
>     {
> 		m_strHeaderBytesToSend += "Cookie";
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_strSessionKey;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     m_strHeaderBytesToSend += "\r\n";
>     return m_strHeaderBytesToSend.c_str ();
> }
> /* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
>  * (i.e. GET or POST) that will be part of the HTTP header block.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP method.
>  */
> const char * HTTPTransport::getHTTPMethod()
> {
>     return m_strHTTPMethod.c_str ();
> }
> /* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
>  * method (i.e. POST or GET) that will be part of the HTTP header block.
>  *
>  * @param const char* Pointer to a NULL terminated character string containing
>  * the new HTTP method.
>  */
> void HTTPTransport::setHTTPMethod( const char *cpMethod)
> {
>     m_strHTTPMethod = std::string( cpMethod);
> }
> /* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
>  * concatinates the new send buffer to the bytes to send string.  This message
>  * will only be sent when a flush buffer is received.
>  *
>  * @param const char* SendBufer - Pointer to a NULL terminated character string
>  * containing all or some of the transmission message.
>  * @param const void* BufferId - Pointer.  This parameter is ignored.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
>  * always be TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
> {
>     m_strBytesToSend += std::string (pcSendBuffer);
>     return TRANSPORT_IN_PROGRESS;
> }
> /* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
>  * receive the synchronous reply to the sent message.
>  *
>  * @param const char* ReceiveBuffer - Pointer to a character string that on
>  * return will containing all or part of the received message.
>  * @param int* Size - Pointer to an integer value that on return will contain
>  * the length of the received message.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
>  * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
> {
>     if (0 >= m_iBytesLeft)
>     {
> 		try
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 			m_strReceived = m_pszRxBuffer;
> 		    if( !m_bReadPastHTTPHeaders)
> 		    {
> 				unsigned int start = std::string::npos;
> 				do
> 				{
> 					do
> 					{
> 						if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 						    m_strReceived += m_pszRxBuffer;
> 						}
> 					} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 					if( m_strReceived.find ("HTTP") == std::string::npos)
> 					{
> 			// Most probably what we read was left overs from earlier reads
> 			// Skip this \r\n\r\n
> 						m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 						do
> 						{
> 							if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 							{
> 								m_pszRxBuffer [0] = '\0';
> 								*m_pActiveChannel >> m_pszRxBuffer;
> 								m_strReceived += m_pszRxBuffer;
> 							}
> 						} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 			// now this must contain HTTP. Else there is a conent error.
> 					}
> 		    //now we have found the end of headers
> 					m_bReadPastHTTPHeaders = true;
> 				    unsigned int pos = 0;
> 		    // Look for content lenght
> 				    if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
> 					{
> 						m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
> 																	   m_strReceived.find( "\n", pos)).c_str());
> 				    }
> 		    // Check if the message is chunked
> 				    if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
> 					{
> 						m_bChunked = true;
> 					}
> 					else
> 					{
> 						m_bChunked = false;
> 					}
> 		    // check if there is HTTP header. If not, there must be an error and 
> 		    // will be detected by processResponseHTTPHeaders()
> 		    // However, must make sure that the left overs from eatlier reads
> 		    // do not appear before HTTP/1.x
> 					start = m_strReceived.find( "HTTP");
> 					if( start == std::string::npos)
> 					{
> 						start = 0;
> 					}
> 		    // Extract HTTP headers and process them
> 				    m_strResponseHTTPHeaders = m_strReceived.substr( start,
> 																     m_strReceived.find( "\r\n\r\n") + 2 - start);
> 				    processResponseHTTPHeaders();
> 				    if( m_iResponseHTTPStatusCode == 100)
> 				    {
> 			// Samisa: We found Continue. Keep on reading and processing headers
> 			// till we get a HTTP code other than 100
> 			// Here it is assumed that the whole of the request is already sent
> 						m_pszRxBuffer [0] = '\0';
> 						*m_pActiveChannel >> m_pszRxBuffer;
> 						m_strReceived = m_pszRxBuffer;
> 					}
> 				} while( m_iResponseHTTPStatusCode == 100);
>                 if ( m_iResponseHTTPStatusCode != 500 &&
>                     ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
> 				{
> 				    throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
> 												  const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
> 				}
> 		// Done with HTTP headers, get payload
> 				m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
> 		    }
> 	    // Read past headers. Deal with payload
> 	    // make sure we have a message with some content
> 		    if( m_strReceived.length () == 0)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived = m_pszRxBuffer;
> 			}
> 			if( m_strReceived.length () > 0) 
> 			{
> 			    if( m_bChunked && m_iContentLength < 1)	// Read first chunk
> 				{
> 			/*
> 			 *Chunked data looks like ->
> 			 *      Chunked-Body   = *chunk
> 			 *                       "0" CRLF
> 			 *                       footer
> 			 *                       CRLF
> 			 *
> 			 *      chunk          = chunk-size [ chunk-ext ] CRLF
> 			 *                         chunk-data CRLF
> 			 *
> 			 *      hex-no-zero    = <HEX excluding "0">
> 			 *
> 			 *      chunk-size     = hex-no-zero *HEX
> 			 *      chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
> 			 *      chunk-ext-name = token
> 			 *      chunk-ext-val  = token | quoted-string
> 			 *      chunk-data     = chunk-size(OCTET)
> 			 *
> 			 *      footer         = *entity-header
> 			 */
> 			// firstly read in the chunk size line.
> 			//There might be chunk extensions in there too but we may not need them
> 					unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 			// make sure we have read at least some part of the message
> 					if( endOfChunkData == std::string::npos)
> 					{
> 						do
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived = m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						} while( endOfChunkData == std::string::npos);
> 					}
> 					int endOfChunkSize = endOfChunkData;
> 			// now get the size of the chunk from the data
> 			// look to see if there are any extensions - these are put in brackets so look for those
> 					if( m_strReceived.substr( 0, endOfChunkData).find( "(") != string::npos)
> 					{
> 						endOfChunkSize = m_strReceived.find( "(");
> 					}
> 			// convert the hex String into the length of the chunk
> 					m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 			// if the chunk size is zero then we have reached the footer
> 			// If we have reached the footer then we can throw it away because we don't need it
> 					if( m_iContentLength > 0)
> 					{
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 						if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
> 						}
> 						else	// we have read lesser than chunk length
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 						}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 					else
> 					{
> 						m_strReceived = "";
> 					}
> 				}
> 				else if( m_bChunked)	// read continued portions of a chunk
> 				{
> 			// Samisa - NOTE: It looks as if there is some logic duplication
> 			// in this block, where we read continued chunks and the block
> 			// above, where we read the first chunk. However, there are slight
> 			// logical differences here, and that is necessary to enable the
> 			// pull model used by the parser - this logic makes pulling more
> 			// efficient (30th Sept 2004)
> 					if( m_strReceived.length () >= m_iContentLength)	// We have reached end of current chunk
> 					{
> 				// Get remainder of current chunk
> 						std::string strTemp = m_strReceived.substr( 0, m_iContentLength);
> 				// Start looking for the next chunk
> 				// The format we are expecting here is:
> 				// <previous chunk>\r\n<chunk size>\r\n<next chunk>
> 						unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 				// Make sure that we have the found the end of previous chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						m_strReceived = m_strReceived.substr( endOfChunkData + 2);	// Skip end of previous chunk
> 						endOfChunkData = m_strReceived.find( "\r\n");	// Locate the start of next chunk
> 				// Make sure that we have the starting line of next chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						int endOfChunkSize = endOfChunkData;
> 				// look to see if there are any extensions - these are put in brackets so look for those
> 						if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
> 						{
> 							endOfChunkSize = m_strReceived.find ("(");
> 						}
> 				// convert the hex String into the length of the chunk
> 						int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 				// if the chunk size is zero then we have reached the footer
> 				// If we have reached the footer then we can throw it away because we don't need it
> 						if( iTempContentLength > 0)
> 						{
> 				// Update the content lenght to be remainde of previous chunk and lenght of new chunk
> 							m_iContentLength += iTempContentLength;
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 							if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
> 							}
> 							else
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 							}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 							if( m_bMimeTrue)
> 							{
> 								processRootMimeBody();
> 							}
> 						}
> 						else
> 						{
> 							m_strReceived = "";
> 						}
> 				// Append the data of new chunk to data from previous chunk
> 						m_strReceived = strTemp + m_strReceived;
> 						}		// End of if (m_strReceived.length() >= m_iContentLength)
> 			// If we have not reached end of current chunk, nothing to be done
> 					}
> 					else		// Not chunked
> 					{
> 				//nothing to do here
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 				}
> 				m_pcReceived = m_strReceived.c_str();
> 				if( m_pcReceived)
> 				{
> 					m_iBytesLeft = strlen( m_pcReceived);
> 				}
> 				else
> 				{
> 					throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
> 				}
> 				m_iContentLength -= m_iBytesLeft;
> 		}
> 		catch( HTTPTransportException & e)
> 		{
> 			throw;
> 		}
> 		catch( AxisException & e)
> 		{
> 		    throw;
> 		}
> 		catch(...)
> 		{
> 		    throw;
> 		}
>     }
>     if (( m_pcReceived) && (*m_pcReceived))
>     {
> 		int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;
> 		strncpy( pcBuffer, m_pcReceived, iToCopy);
> 		m_iBytesLeft -= iToCopy;
> 		m_pcReceived += iToCopy;
> 		*pSize = iToCopy;
> 		return TRANSPORT_IN_PROGRESS;
> 	}
> 	else
> 	{
> 		m_bReadPastHTTPHeaders = false;	// get ready for a new message
> 		m_strReceived = "";	//clear the message buffer in preperation of the next read
> 		return TRANSPORT_FINISHED;
>     }
> }
> /* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
> {
>     const char *key = NULL;
>     switch (type)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			key = "SOAPAction";
> 		    break;
> 		}
> 		case SERVICE_URI:		// need to set ?
> 		{
> 			break;
> 		}
> 		case OPERATION_NAME:	// need to set ?
> 		{
> 			break;
> 		}
> 		case SOAP_MESSAGE_LENGTH:
> 		{
> 			key = "Content-Length";	// this Axis transport handles only HTTP
> 			break;
> 		}
> 		case TRANSPORT_PROPERTIES:
> 		{
> 			m_pActiveChannel->setTransportProperty( type, value);
> 			break;
> 		}
> 		case SECURE_PROPERTIES:
> 		{
> 			m_pActiveChannel->setSecureProperties( value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_SSL_DLL_NAME:
> 		{
> 			m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
> 			break;
> 		}
> 		default:
> 		{
> 			break;
> 		}
>     }
>     if( key)
>     {
> 		setTransportProperty( key, value);
>     }
> }
> /* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param const char* Key is a NULL terminated character string containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
> {
>     if( !pcKey || !pcValue)	// Samisa - fix for AXISCPP-295. We must check for valid values here.
> 	{
> 		return;
> 	}
>     bool b_KeyFound = false;
>     if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
>     {
> 		std::string strKeyToFind = std::string( pcKey);
> 		for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
> 		{
> 		    if (m_vHTTPHeaders[i].first == strKeyToFind)
> 			{
> 				m_vHTTPHeaders[i].second = (string) pcValue;
> 				b_KeyFound = true;
> 				break;
> 		    }
> 		}
>     }
>     if( !b_KeyFound)
>     {
> 		m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
>     }
> }
> /* HTTPTransport::getTransportProperty( Type) Is a public method that will
>  * return the HTTP Header/SSL implementation value associated with type.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header or SSL
>  * implementation settings.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
> {
>     const char *pszPropValue = NULL;
>     switch( eType)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "SOAPAction");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	    case SERVICE_URI:
> 		{
> 			break;
> 		}
> 	    case OPERATION_NAME:
> 		{
> 			break;
> 		}
> 	    case SOAP_MESSAGE_LENGTH:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "Content-Length");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	case TRANSPORT_PROPERTIES:
>     case SECURE_PROPERTIES:
> 		{
> 			pszPropValue = m_pActiveChannel->getTransportProperty( eType);
> 			break;
> 		}
> 	case CHANNEL_HTTP_SSL_DLL_NAME:
> 	case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			break;
> 		}
>     }
>     return pszPropValue;
> }
> /* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
>  * return the HTTP Header index associated with Key.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header settings.
>  *
>  * @return int Index is an index to the key within the HTTP Header list.  If
>  * the return value is -1, then the key was not found.
>  */
> int HTTPTransport::FindTransportPropertyIndex( string sKey)
> {
>     bool	bKeyFound = false;
>     int		iIndex = 0;
>     do
>     {
> 		if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
> 		{
> 			bKeyFound = true;
> 		}
> 		else
> 		{
> 			iIndex++;
> 		}
>     } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);
>     if( !bKeyFound)
>     {
> 		iIndex = -1;
>     }
>     return iIndex;
> }
> /* HTTPTransport::getServiceName() Is a public method to return the HTTP
>  * Header service name.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the service name.
>  */
> const char * HTTPTransport::getServiceName()
> {
>     //Assume SOAPAction header to contain service name
>     int		iIndex = FindTransportPropertyIndex( "SOAPAction");
>     if (iIndex > -1)
>     {
> 		return m_vHTTPHeaders[iIndex].second.c_str();
>     }
>     return NULL;
> }
> AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
> {
>     return m_eProtocolType;
> }
> int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
> {
>     if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
>     {
> 		m_eProtocolType = eProtocol;
> 		m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";
> 		return AXIS_SUCCESS;
>     }
>     else
> 	{
> 		return AXIS_FAIL;
> 	}
> }
> /**
>  * HTTPTransport::getSubProtocol() is a public method that is supposed to
>  * return the sub protocol (currently this method always return 0).
>  * This method is supposed to return whether it is http GET or POST
>  */
> int HTTPTransport::getSubProtocol()
> {
>     //TODO
>     // for SimpleAxisServer assume POST
>     return AXIS_HTTP_POST;
>     //return 0;
> }
> /* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
>  * updating the proxy for the connection.
>  *
>  * @param const char* Host is a NULL terminated character string containing the new
>  * proxy host.
>  * @param unsigned int Port is the new proxy port number.
>  */
> void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
> {
>     m_strProxyHost = pcProxyHost;
>     m_uiProxyPort = uiProxyPort;
>     m_bUseProxy = true;
> }
> /* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
>  * current maximum timeout period between that can elapse between receiving
>  * message parts.
>  *
>  * @param const long Timeout is a long value in seconds.
>  */
> void HTTPTransport::setTimeout( const long lSeconds)
> {
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( lSeconds);
> 	}
> 	m_lChannelTimeout = lSeconds;
> }
> /* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
>  * current HTTP protocol settings.
>  *
>  * @return const char* HTTPProtocol is a NULL terminated character string
>  * containing the HTTP protocol.
>  */
> const char * HTTPTransport::getHTTPProtocol()
> {
>     return m_strHTTPProtocol.c_str ();
> }
> /* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
>  */
> int axtoi( char *pcHexStg)
> {
>     int		iN = 0;			// position in string
>     int		iM = 0;			// position in digit[] to shift
>     int		iCount;			// loop index
>     int		intValue = 0;	// integer value of hex string
>     int		iDigit[32];		// hold values to convert
>     while( iN < 32)
>     {
> 		if( pcHexStg[iN] == '\0')
> 		{
> 			break;
> 		}
> 	
> 		if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40)	//if 0 to 9
> 		{
> 			iDigit[iN] = pcHexStg[iN] & 0x0f;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f')	//if a to f
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F')	//if A to F
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else
> 		{
> 			break;
> 		}
> 	iN++;
>     }
>     iCount = iN;
>     iM = iN - 1;
>     iN = 0;
>     while( iN < iCount)
>     {
> 	// digit[n] is value of hex digit at position n
> 	// (m << 2) is the number of positions to shift
> 	// OR the bits into return value
> 		intValue = intValue | (iDigit[iN] << (iM << 2));
> 		iM--;			// adjust the position to set
> 		iN++;			// next digit to process
>     }
>     return intValue;
> }
> /* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
>  * parse the HTTP header of the response message.
>  */
> void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
> {
>     unsigned int iPosition = std::string::npos;
>     unsigned int iStartPosition = iPosition;
>     if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
>     {
> 		m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
> 		iPosition += strlen( "HTTP/1.x");
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
> 		{
> 			iPosition++;
> 		}
> 		iStartPosition = iPosition;
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
> 		{
> 			iPosition++;
> 		}
> 		std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																				 iPosition - iStartPosition);
> 		m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());
> 		iStartPosition = ++iPosition;
> 		iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																		  iPosition - iStartPosition - 1);
> 	// reached the end of the first line
> 		iStartPosition = m_strResponseHTTPHeaders.find( "\n");
> 		iStartPosition++;
> 	// read header fields and add to vector
> 		do
> 		{
> 		    m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
> 			iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		    if( iPosition == std::string::npos)
> 		    {
> 				break;
> 			}
> 			std::string		strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
> 			unsigned int	iSeperator = strHeaderLine.find(":");
> 		    if( iSeperator == std::string::npos)
> 			{
> 				break;
> 			}
> 			iStartPosition = iPosition + 1;
> 			string	key = strHeaderLine.substr( 0, iSeperator);
> 			string	value = strHeaderLine.substr( iSeperator + 1,
> 												  strHeaderLine.length () - iSeperator - 1 - 1);
> 			m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
> 	    // if HTTP/1.0 we have to always close the connection by default
> 		    if( m_eProtocolType == APTHTTP1_0)
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // if HTTP/1.1 we have to assume persistant connection by default
> 	    // We need to close the connection and open a new one if we have 'Connection: close'
> 			if( key == "Connection" && value == " close")
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // For both HTTP/1.0 and HTTP/1.1,
> 	    // We need to keep the connection if we have 'Connection: Keep-Alive'
> 			if( key == "Connection" && value == " Keep-Alive")
> 			{
> 				m_bReopenConnection = false;
> 			}
> 	    // Look for cookies
> 			if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
> 		    {
> 				if( key == "Set-Cookie")
> 				{
> 					m_strSessionKey = value;
> 		    // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
> 		    // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
> 		    // And discards stuff after first ';'
> 		    // This is the same assumption used in Axis Java
> 					unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
> 		    
> 					if( ulKeyEndsAt != std::string::npos)
> 				    {
> 						m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
> 				    }
> 				}
> 		    }
> 	    /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
> 	       start="<content id>" */
> 			if( key == "Content-Type")
> 			{
> 				m_strContentType = value;
> 		
> 				unsigned long	ulMimePos = m_strContentType.find( ";");
> 				std::string		strTypePart;
> 				if( ulMimePos != std::string::npos)
> 				{
> 					strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
> 				}
> 		
> 				if( "Multipart/Related" == strTypePart)
> 				{
> 					m_bMimeTrue = true;
> 					m_strContentType = m_strContentType.substr( ulMimePos + 1,
> 																m_strContentType.length());
> 				    ulMimePos = m_strContentType.find( "boundary=");
> 					m_strMimeBoundary = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeBoundary.find( ";");
> 					m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
> 					ulMimePos = m_strContentType.find( "type=");
> 					m_strMimeType = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeType.find( ";");
> 					m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);
> 				    ulMimePos = m_strContentType.find( "start=");
> 					m_strMimeStart = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeStart.find( ";");
> 					m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
> 				}
> 			}
> 		} while( iPosition != std::string::npos);
>     }
>     else
>     {
> 		throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
> 									  "Protocol is not HTTP.");
>     }
> }
> /* HTTPTransport::processRootMimeBody() Is a public method used to
>  * parse the mime attachments.
>  */
> void HTTPTransport::processRootMimeBody()
> {
>     if( false == m_bReadPastRootMimeHeader)
>     {
> 		do
> 		{
> 			if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived += m_pszRxBuffer;
> 			}
> 		} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 	//now we have found the end of root mime header
> 		m_bReadPastRootMimeHeader = true;
> 	//processMimeHeader(); For the time being we don't process this
> 	// Done with root mime body headers, get rest of the payload 
> 	// which contain the soap message
> 		m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 	
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		if (intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
>     }
>     else
>     {
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		
> 		if( intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
> 	return;
>     }
> }
> /* HTTPTransport::processMimeHeaders() Is a public method used to
>  * parse the Mime headers of the response message.
>  */
> void HTTPTransport::processMimeHeader()
> {
>     unsigned int pos = 0;
>     unsigned int temppos = 0;
>     // Look for content lenght
>     if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
> 	{
> 		m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
> 														 m_strMimeReceived.find( "\n", pos));
> 		pos = m_strMimeContentType.find( ";");
> 		temppos = m_strMimeContentType.find( "\r\n");
> 		if( pos < temppos)
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
> 		}
> 		else
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
> 		}
>     }
>     // Look for mime root body's content transfer encoding
>     if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
> 	{
> 		m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
> 																     m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentTransferEncoding.find( "\r\n");
> 		m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
>     }
>     // Look for mime root body's content id
>     if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
> 	{
> 		m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
> 													   m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentID.find( "\r\n");
> 		m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
>     }
>     // Look for mime root body's content location
>     if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
>     {
> 		m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
> 																   m_strMimeReceived.find( "\n", pos)).c_str());
> 		temppos = m_strMimeContentLocation.find( "\r\n");
> 		m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
>     }
> }
> void HTTPTransport::processMimeBody ()
> {
> }
> void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
> {
> 	m_pszRxBuffer [0] = '\0';
> 	*m_pActiveChannel >> m_pszRxBuffer;
>     m_strMimeReceived += m_pszRxBuffer;
>     do
>     {
> 		if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 		    m_strMimeReceived += m_pszRxBuffer;
> 		}
>     } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);
>     //now we have found the end of next mime header
>     processMimeHeader();
>     m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
>     processMimeBody();
> }
> void HTTPTransport::setSocket( unsigned int uiNewSocket)
> {
>     m_pActiveChannel->setSocket( uiNewSocket);
> }
> const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
> {
>     std::string strKeyToFind = std::string( pcKey);
>     for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
> 	{
> 		if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
> 		{
> 			return ((string) m_vResponseHTTPHeaders[i].second).c_str();
> 		}
>     }
>     return NULL;
> }
> const char * HTTPTransport::getFirstTransportPropertyKey()
> {
>     m_viCurrentHeader = m_vHTTPHeaders.begin ();
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getNextTransportPropertyKey()
> {
>     //already at the end?
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     m_viCurrentHeader++;
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyKey()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyValue()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).second.c_str();
> 	}
> }
> void HTTPTransport::deleteCurrentTransportProperty()
> {
>     if( m_viCurrentHeader != m_vHTTPHeaders.end())
>     {
> 		m_vHTTPHeaders.erase( m_viCurrentHeader);
>     }
> }
> void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
> {
>     vector < std::pair < std::string,
> 	std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
>     unsigned int uiCount = 1;
>     while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
>     {
> 		if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
> 		{
> 			if( uiCount == uiOccurance)
> 			{
> 				m_vHTTPHeaders.erase( currentHeader);
> 				break;
> 			}
> 	    
> 			uiCount++;
> 		}
> 	
> 		currentHeader++;
>     }
> }
> void HTTPTransport::setMaintainSession( bool bSession)
> {
>     m_bMaintainSession = bSession;
> }
> void HTTPTransport::setSessionId( const char * pcSessionId)
> {
>     m_strSessionKey = std::string (pcSessionId);
> }
> const char * HTTPTransport::getSessionId()
> {
>     return m_strSessionKey.c_str();
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


[jira] Updated: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS

Posted by "Chinthana Danapala (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXISCPP-518?page=history ]

Chinthana Danapala updated AXISCPP-518:
---------------------------------------

    Attachment: HTTPTransportcpp diff.txt

i have add some changes here it will help to solve this problem.

> Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
> -------------------------------------------------------------------------------------------------------------
>
>          Key: AXISCPP-518
>          URL: http://issues.apache.org/jira/browse/AXISCPP-518
>      Project: Axis-C++
>         Type: Bug
>   Components: Transport (axis3)
>     Versions: unspecified
>  Environment: The bug affects all platforms
>     Reporter: Arcangelo Di Balsamo
>  Attachments: HTTPTransport.cpp, HTTPTransportcpp diff.txt, HTTPTrasportTestClient.zip
>
> I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
> The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
> I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation. 
> The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
> I've already made a fix: the affected module is HTTPTransport.cpp.
> The modified code is :
> /*
> *   Copyright 2003-2004 The Apache Software Foundation.
> *
> *   Licensed under the Apache License, Version 2.0 (the "License");
> *   you may not use this file except in compliance with the License.
> *   You may obtain a copy of the License at
> *
> *       http://www.apache.org/licenses/LICENSE-2.0
> *
> *   Unless required by applicable law or agreed to in writing, software
> *   distributed under the License is distributed on an "AS IS" BASIS,
> *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> *   See the License for the specific language governing permissions and
> *   limitations under the License.
> */
> /*
>  * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
>  *
>  */
> #ifdef WIN32
> #pragma warning (disable : 4786)
> #pragma warning (disable : 4101)
> #endif
> #include "HTTPTransport.hpp"
> #include <stdio.h>
> #include <iostream>
> /*
>  * HTTPTransport constuctor
>  */
> HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
> m_strHTTPProtocol ("HTTP/1.1"),
> m_strHTTPMethod ("POST"),
> m_bChunked (false),
> m_bReadPastHTTPHeaders (false),
> m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
> m_bMaintainSession (false)
> {
>     m_pcEndpointUri = NULL;
>     m_pReleaseBufferCallback = 0;
>     m_eProtocolType = APTHTTP1_1;
>     m_strBytesToSend = "";
>     m_strHeaderBytesToSend = "";
>     m_iBytesLeft = 0;
>     m_iContentLength = 0;
>     m_pcReceived = 0;
> 	m_bChannelSecure = false;
>     m_pNormalChannel = 0;
>     m_pSecureChannel = 0;
> 	m_pActiveChannel = 0;
>     m_pChannelFactory = new ChannelFactory();
>     m_bMimeTrue = false;
>     m_viCurrentHeader = m_vHTTPHeaders.begin();
> 	m_pszRxBuffer = new char [BUF_SIZE];
> #ifdef WIN32
> 	m_lChannelTimeout = 10;
> #else
> 	m_lChannelTimeout = 0;
> #endif
> }
> /*
>  * HTTPTransport destuctor
>  */
> HTTPTransport::~HTTPTransport()
> {
>     if( m_pcEndpointUri)
>     {
> 	delete[] m_pcEndpointUri;
>     }
>     if( m_pChannelFactory)
> 	{
> 		delete m_pChannelFactory;
> 		m_pChannelFactory = 0;
> 	}
> 	delete [] m_pszRxBuffer;
> }
> /*
>  * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
>  * Everytime the endpoint changes then currently connected channel is closed
>  * and a new channel connection is opened.
>  *
>  * @param	EndpointURI - char * to a null terminated string that holds the
>  *			new URI. 
>  */
> void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
> {
>     bool bUpdateURL = false;
>     // Get the current channel URI
>     if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
>     {
> 	// Does the new URI equal the existing channel URI?
> 		if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
> 		{
> 	    // There is a new URI.
> 			bUpdateURL = true;
> 		}
>     }
>     else
>     {
> 		bUpdateURL = true;
>     }
>     // If there is a new URI, then this flag will be set.  Depending on whether
>     // there is an SSL implementation available, if the new URI is a secure
> 	// connection, a secure channel will be opened.  If an SSL implementation
> 	// is not available and the URL requires a secure connection then an
> 	// exception will be thrown.
>     if( bUpdateURL)
>     {
> 		if( m_pActiveChannel == NULL)
> 		{
> 			m_pActiveChannel = m_pNormalChannel;
> 		}
> 		m_pActiveChannel->setURL( pcEndpointUri);
> 		m_bReopenConnection = true;
> 	// Check if the new URI requires SSL (denoted by the https prefix).
> 		if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
> 		{
> 			if( m_pSecureChannel != NULL)
> 			{
> 				m_pNormalChannel->close();
> 				m_pActiveChannel = m_pSecureChannel;
> 				m_pActiveChannel->setURL( pcEndpointUri);
> 				m_bChannelSecure = true;
> 			}
> 			if( !m_bChannelSecure)
> 			{
> 				throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
> 			}
> 		}
> 		else
> 		{
> 	    // URI does not require a secure channel.  Delete the existing
> 	    // channel if it is secure and create a new unsecure
> 	    // channel.
> 			if (m_bChannelSecure)
> 			{
> 				if( m_pNormalChannel != NULL)
> 				{
> 					m_pSecureChannel->close();
> 					m_pActiveChannel = m_pNormalChannel;
> 					m_pActiveChannel->setURL( pcEndpointUri);
> 					m_bChannelSecure = false;
> 				}
> 				if( m_bChannelSecure)
> 				{
> 					throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
> 				}
> 			}
> 		}
>     }
> // Need this code to set the channel timeout.  If the timeout was changed
> // before the channel was created, then it may not have the correct timeout.
> // By setting it here, the channel is sure to have the correct timeout value
> // next time the channel is read.
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( m_lChannelTimeout);
> 	}
> }
> /*
>  * HTTPTransport::openConnection().
>  */
> int HTTPTransport::openConnection()
> {
> 	return m_pActiveChannel->open();
> }
> /*
>  * HTTPTransport::closeConnection().
>  */
> void HTTPTransport::closeConnection()
> {
>     // get ready for a new message.
>     m_bReadPastHTTPHeaders = false;
>     //clear the message buffer in preperation of the next read.
>     m_strReceived = "";
>     m_iContentLength = 0;
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->close();
> 	}
> }
> /*
>  * HTTPTransport::flushOutput() Is called when the message construction is
>  * complete.  The message is ready to be 'flushed out' onto the network.  
>  * Check if the URI has changed.  If it has, then need to open a new Channel
>  * instance before transmitting the message.
>  *
>  * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
>  * this will be set to TRANSPORT_FINISHED.  Otherwise, an exception will have
>  * been thrown.
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
> {
>     if( m_bReopenConnection)
>     {
> 		m_bReopenConnection = false;
> 		if( m_pActiveChannel->open() != AXIS_SUCCESS)
> 		{
> 		    int				iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
> 			const char *	pszLastError = new char[iStringLength];
> 		    memcpy( (void *) pszLastError,
> 					m_pActiveChannel->GetLastErrorMsg().c_str(),
> 					iStringLength);
> 		    throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
> 										  (char *) pszLastError);
> 			}
> 		}
>     // In preperation for sending the message, calculate the size of the message
>     // by using the string length method.
>     // NB: This calculation may not necessarily be correct when dealing with SSL
>     //     messages as the length of the encoded message is not necessarily the
>     //         same as the length of the uncoded message.
>     char buff[8];
> 	sprintf( buff, "%d", m_strBytesToSend.length ());
>     this->setTransportProperty ("Content-Length", buff);
>     // The header is now complete.  The message header and message can now be
>     // transmitted.
> 	try
> 	{
> 		*m_pActiveChannel << this->getHTTPHeaders ();
> 		*m_pActiveChannel << this->m_strBytesToSend.c_str ();
> 	}
> 	catch( HTTPTransportException & e)
> 	{
> 		throw;
> 	}
> 	catch( AxisException & e)
> 	{
> 		throw;
> 	}
> 	catch(...)
> 	{
> 		throw;
> 	}
>     // Empty the bytes to send string.
> 	m_strBytesToSend = "";
> 	m_strHeaderBytesToSend = "";
> 	return TRANSPORT_FINISHED;
> }
> /* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
>  * information block that will preceed the SOAP message.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP header block of information.
>  */
> const char * HTTPTransport::getHTTPHeaders()
> {
>     URL &			url = m_pActiveChannel->getURLObject();
>     unsigned short	uiPort = url.getPort();
>     char			buff[8];
>     m_strHeaderBytesToSend = m_strHTTPMethod + " ";
>     m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
>     m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
>     m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();
>     sprintf (buff, "%u", uiPort);
>     m_strHeaderBytesToSend += ":";
>     m_strHeaderBytesToSend += buff;
>     m_strHeaderBytesToSend += "\r\n";
>     m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";
>     // Set other HTTP headers
>     for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
>     {
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     // Set session cookie
>     if (m_bMaintainSession && (m_strSessionKey.size () > 0))
>     {
> 		m_strHeaderBytesToSend += "Cookie";
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_strSessionKey;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     m_strHeaderBytesToSend += "\r\n";
>     return m_strHeaderBytesToSend.c_str ();
> }
> /* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
>  * (i.e. GET or POST) that will be part of the HTTP header block.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP method.
>  */
> const char * HTTPTransport::getHTTPMethod()
> {
>     return m_strHTTPMethod.c_str ();
> }
> /* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
>  * method (i.e. POST or GET) that will be part of the HTTP header block.
>  *
>  * @param const char* Pointer to a NULL terminated character string containing
>  * the new HTTP method.
>  */
> void HTTPTransport::setHTTPMethod( const char *cpMethod)
> {
>     m_strHTTPMethod = std::string( cpMethod);
> }
> /* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
>  * concatinates the new send buffer to the bytes to send string.  This message
>  * will only be sent when a flush buffer is received.
>  *
>  * @param const char* SendBufer - Pointer to a NULL terminated character string
>  * containing all or some of the transmission message.
>  * @param const void* BufferId - Pointer.  This parameter is ignored.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
>  * always be TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
> {
>     m_strBytesToSend += std::string (pcSendBuffer);
>     return TRANSPORT_IN_PROGRESS;
> }
> /* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
>  * receive the synchronous reply to the sent message.
>  *
>  * @param const char* ReceiveBuffer - Pointer to a character string that on
>  * return will containing all or part of the received message.
>  * @param int* Size - Pointer to an integer value that on return will contain
>  * the length of the received message.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
>  * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
> {
>     if (0 >= m_iBytesLeft)
>     {
> 		try
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 			m_strReceived = m_pszRxBuffer;
> 		    if( !m_bReadPastHTTPHeaders)
> 		    {
> 				unsigned int start = std::string::npos;
> 				do
> 				{
> 					do
> 					{
> 						if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 						    m_strReceived += m_pszRxBuffer;
> 						}
> 					} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 					if( m_strReceived.find ("HTTP") == std::string::npos)
> 					{
> 			// Most probably what we read was left overs from earlier reads
> 			// Skip this \r\n\r\n
> 						m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 						do
> 						{
> 							if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 							{
> 								m_pszRxBuffer [0] = '\0';
> 								*m_pActiveChannel >> m_pszRxBuffer;
> 								m_strReceived += m_pszRxBuffer;
> 							}
> 						} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 			// now this must contain HTTP. Else there is a conent error.
> 					}
> 		    //now we have found the end of headers
> 					m_bReadPastHTTPHeaders = true;
> 				    unsigned int pos = 0;
> 		    // Look for content lenght
> 				    if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
> 					{
> 						m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
> 																	   m_strReceived.find( "\n", pos)).c_str());
> 				    }
> 		    // Check if the message is chunked
> 				    if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
> 					{
> 						m_bChunked = true;
> 					}
> 					else
> 					{
> 						m_bChunked = false;
> 					}
> 		    // check if there is HTTP header. If not, there must be an error and 
> 		    // will be detected by processResponseHTTPHeaders()
> 		    // However, must make sure that the left overs from eatlier reads
> 		    // do not appear before HTTP/1.x
> 					start = m_strReceived.find( "HTTP");
> 					if( start == std::string::npos)
> 					{
> 						start = 0;
> 					}
> 		    // Extract HTTP headers and process them
> 				    m_strResponseHTTPHeaders = m_strReceived.substr( start,
> 																     m_strReceived.find( "\r\n\r\n") + 2 - start);
> 				    processResponseHTTPHeaders();
> 				    if( m_iResponseHTTPStatusCode == 100)
> 				    {
> 			// Samisa: We found Continue. Keep on reading and processing headers
> 			// till we get a HTTP code other than 100
> 			// Here it is assumed that the whole of the request is already sent
> 						m_pszRxBuffer [0] = '\0';
> 						*m_pActiveChannel >> m_pszRxBuffer;
> 						m_strReceived = m_pszRxBuffer;
> 					}
> 				} while( m_iResponseHTTPStatusCode == 100);
>                 if ( m_iResponseHTTPStatusCode != 500 &&
>                     ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
> 				{
> 				    throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
> 												  const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
> 				}
> 		// Done with HTTP headers, get payload
> 				m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
> 		    }
> 	    // Read past headers. Deal with payload
> 	    // make sure we have a message with some content
> 		    if( m_strReceived.length () == 0)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived = m_pszRxBuffer;
> 			}
> 			if( m_strReceived.length () > 0) 
> 			{
> 			    if( m_bChunked && m_iContentLength < 1)	// Read first chunk
> 				{
> 			/*
> 			 *Chunked data looks like ->
> 			 *      Chunked-Body   = *chunk
> 			 *                       "0" CRLF
> 			 *                       footer
> 			 *                       CRLF
> 			 *
> 			 *      chunk          = chunk-size [ chunk-ext ] CRLF
> 			 *                         chunk-data CRLF
> 			 *
> 			 *      hex-no-zero    = <HEX excluding "0">
> 			 *
> 			 *      chunk-size     = hex-no-zero *HEX
> 			 *      chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
> 			 *      chunk-ext-name = token
> 			 *      chunk-ext-val  = token | quoted-string
> 			 *      chunk-data     = chunk-size(OCTET)
> 			 *
> 			 *      footer         = *entity-header
> 			 */
> 			// firstly read in the chunk size line.
> 			//There might be chunk extensions in there too but we may not need them
> 					unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 			// make sure we have read at least some part of the message
> 					if( endOfChunkData == std::string::npos)
> 					{
> 						do
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived = m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						} while( endOfChunkData == std::string::npos);
> 					}
> 					int endOfChunkSize = endOfChunkData;
> 			// now get the size of the chunk from the data
> 			// look to see if there are any extensions - these are put in brackets so look for those
> 					if( m_strReceived.substr( 0, endOfChunkData).find( "(") != string::npos)
> 					{
> 						endOfChunkSize = m_strReceived.find( "(");
> 					}
> 			// convert the hex String into the length of the chunk
> 					m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 			// if the chunk size is zero then we have reached the footer
> 			// If we have reached the footer then we can throw it away because we don't need it
> 					if( m_iContentLength > 0)
> 					{
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 						if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
> 						}
> 						else	// we have read lesser than chunk length
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 						}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 					else
> 					{
> 						m_strReceived = "";
> 					}
> 				}
> 				else if( m_bChunked)	// read continued portions of a chunk
> 				{
> 			// Samisa - NOTE: It looks as if there is some logic duplication
> 			// in this block, where we read continued chunks and the block
> 			// above, where we read the first chunk. However, there are slight
> 			// logical differences here, and that is necessary to enable the
> 			// pull model used by the parser - this logic makes pulling more
> 			// efficient (30th Sept 2004)
> 					if( m_strReceived.length () >= m_iContentLength)	// We have reached end of current chunk
> 					{
> 				// Get remainder of current chunk
> 						std::string strTemp = m_strReceived.substr( 0, m_iContentLength);
> 				// Start looking for the next chunk
> 				// The format we are expecting here is:
> 				// <previous chunk>\r\n<chunk size>\r\n<next chunk>
> 						unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 				// Make sure that we have the found the end of previous chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						m_strReceived = m_strReceived.substr( endOfChunkData + 2);	// Skip end of previous chunk
> 						endOfChunkData = m_strReceived.find( "\r\n");	// Locate the start of next chunk
> 				// Make sure that we have the starting line of next chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						int endOfChunkSize = endOfChunkData;
> 				// look to see if there are any extensions - these are put in brackets so look for those
> 						if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
> 						{
> 							endOfChunkSize = m_strReceived.find ("(");
> 						}
> 				// convert the hex String into the length of the chunk
> 						int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 				// if the chunk size is zero then we have reached the footer
> 				// If we have reached the footer then we can throw it away because we don't need it
> 						if( iTempContentLength > 0)
> 						{
> 				// Update the content lenght to be remainde of previous chunk and lenght of new chunk
> 							m_iContentLength += iTempContentLength;
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 							if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
> 							}
> 							else
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 							}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 							if( m_bMimeTrue)
> 							{
> 								processRootMimeBody();
> 							}
> 						}
> 						else
> 						{
> 							m_strReceived = "";
> 						}
> 				// Append the data of new chunk to data from previous chunk
> 						m_strReceived = strTemp + m_strReceived;
> 						}		// End of if (m_strReceived.length() >= m_iContentLength)
> 			// If we have not reached end of current chunk, nothing to be done
> 					}
> 					else		// Not chunked
> 					{
> 				//nothing to do here
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 				}
> 				m_pcReceived = m_strReceived.c_str();
> 				if( m_pcReceived)
> 				{
> 					m_iBytesLeft = strlen( m_pcReceived);
> 				}
> 				else
> 				{
> 					throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
> 				}
> 				m_iContentLength -= m_iBytesLeft;
> 		}
> 		catch( HTTPTransportException & e)
> 		{
> 			throw;
> 		}
> 		catch( AxisException & e)
> 		{
> 		    throw;
> 		}
> 		catch(...)
> 		{
> 		    throw;
> 		}
>     }
>     if (( m_pcReceived) && (*m_pcReceived))
>     {
> 		int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;
> 		strncpy( pcBuffer, m_pcReceived, iToCopy);
> 		m_iBytesLeft -= iToCopy;
> 		m_pcReceived += iToCopy;
> 		*pSize = iToCopy;
> 		return TRANSPORT_IN_PROGRESS;
> 	}
> 	else
> 	{
> 		m_bReadPastHTTPHeaders = false;	// get ready for a new message
> 		m_strReceived = "";	//clear the message buffer in preperation of the next read
> 		return TRANSPORT_FINISHED;
>     }
> }
> /* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
> {
>     const char *key = NULL;
>     switch (type)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			key = "SOAPAction";
> 		    break;
> 		}
> 		case SERVICE_URI:		// need to set ?
> 		{
> 			break;
> 		}
> 		case OPERATION_NAME:	// need to set ?
> 		{
> 			break;
> 		}
> 		case SOAP_MESSAGE_LENGTH:
> 		{
> 			key = "Content-Length";	// this Axis transport handles only HTTP
> 			break;
> 		}
> 		case TRANSPORT_PROPERTIES:
> 		{
> 			m_pActiveChannel->setTransportProperty( type, value);
> 			break;
> 		}
> 		case SECURE_PROPERTIES:
> 		{
> 			m_pActiveChannel->setSecureProperties( value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_SSL_DLL_NAME:
> 		{
> 			m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
> 			break;
> 		}
> 		default:
> 		{
> 			break;
> 		}
>     }
>     if( key)
>     {
> 		setTransportProperty( key, value);
>     }
> }
> /* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param const char* Key is a NULL terminated character string containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
> {
>     if( !pcKey || !pcValue)	// Samisa - fix for AXISCPP-295. We must check for valid values here.
> 	{
> 		return;
> 	}
>     bool b_KeyFound = false;
>     if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
>     {
> 		std::string strKeyToFind = std::string( pcKey);
> 		for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
> 		{
> 		    if (m_vHTTPHeaders[i].first == strKeyToFind)
> 			{
> 				m_vHTTPHeaders[i].second = (string) pcValue;
> 				b_KeyFound = true;
> 				break;
> 		    }
> 		}
>     }
>     if( !b_KeyFound)
>     {
> 		m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
>     }
> }
> /* HTTPTransport::getTransportProperty( Type) Is a public method that will
>  * return the HTTP Header/SSL implementation value associated with type.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header or SSL
>  * implementation settings.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
> {
>     const char *pszPropValue = NULL;
>     switch( eType)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "SOAPAction");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	    case SERVICE_URI:
> 		{
> 			break;
> 		}
> 	    case OPERATION_NAME:
> 		{
> 			break;
> 		}
> 	    case SOAP_MESSAGE_LENGTH:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "Content-Length");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	case TRANSPORT_PROPERTIES:
>     case SECURE_PROPERTIES:
> 		{
> 			pszPropValue = m_pActiveChannel->getTransportProperty( eType);
> 			break;
> 		}
> 	case CHANNEL_HTTP_SSL_DLL_NAME:
> 	case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			break;
> 		}
>     }
>     return pszPropValue;
> }
> /* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
>  * return the HTTP Header index associated with Key.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header settings.
>  *
>  * @return int Index is an index to the key within the HTTP Header list.  If
>  * the return value is -1, then the key was not found.
>  */
> int HTTPTransport::FindTransportPropertyIndex( string sKey)
> {
>     bool	bKeyFound = false;
>     int		iIndex = 0;
>     do
>     {
> 		if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
> 		{
> 			bKeyFound = true;
> 		}
> 		else
> 		{
> 			iIndex++;
> 		}
>     } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);
>     if( !bKeyFound)
>     {
> 		iIndex = -1;
>     }
>     return iIndex;
> }
> /* HTTPTransport::getServiceName() Is a public method to return the HTTP
>  * Header service name.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the service name.
>  */
> const char * HTTPTransport::getServiceName()
> {
>     //Assume SOAPAction header to contain service name
>     int		iIndex = FindTransportPropertyIndex( "SOAPAction");
>     if (iIndex > -1)
>     {
> 		return m_vHTTPHeaders[iIndex].second.c_str();
>     }
>     return NULL;
> }
> AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
> {
>     return m_eProtocolType;
> }
> int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
> {
>     if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
>     {
> 		m_eProtocolType = eProtocol;
> 		m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";
> 		return AXIS_SUCCESS;
>     }
>     else
> 	{
> 		return AXIS_FAIL;
> 	}
> }
> /**
>  * HTTPTransport::getSubProtocol() is a public method that is supposed to
>  * return the sub protocol (currently this method always return 0).
>  * This method is supposed to return whether it is http GET or POST
>  */
> int HTTPTransport::getSubProtocol()
> {
>     //TODO
>     // for SimpleAxisServer assume POST
>     return AXIS_HTTP_POST;
>     //return 0;
> }
> /* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
>  * updating the proxy for the connection.
>  *
>  * @param const char* Host is a NULL terminated character string containing the new
>  * proxy host.
>  * @param unsigned int Port is the new proxy port number.
>  */
> void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
> {
>     m_strProxyHost = pcProxyHost;
>     m_uiProxyPort = uiProxyPort;
>     m_bUseProxy = true;
> }
> /* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
>  * current maximum timeout period between that can elapse between receiving
>  * message parts.
>  *
>  * @param const long Timeout is a long value in seconds.
>  */
> void HTTPTransport::setTimeout( const long lSeconds)
> {
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( lSeconds);
> 	}
> 	m_lChannelTimeout = lSeconds;
> }
> /* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
>  * current HTTP protocol settings.
>  *
>  * @return const char* HTTPProtocol is a NULL terminated character string
>  * containing the HTTP protocol.
>  */
> const char * HTTPTransport::getHTTPProtocol()
> {
>     return m_strHTTPProtocol.c_str ();
> }
> /* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
>  */
> int axtoi( char *pcHexStg)
> {
>     int		iN = 0;			// position in string
>     int		iM = 0;			// position in digit[] to shift
>     int		iCount;			// loop index
>     int		intValue = 0;	// integer value of hex string
>     int		iDigit[32];		// hold values to convert
>     while( iN < 32)
>     {
> 		if( pcHexStg[iN] == '\0')
> 		{
> 			break;
> 		}
> 	
> 		if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40)	//if 0 to 9
> 		{
> 			iDigit[iN] = pcHexStg[iN] & 0x0f;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f')	//if a to f
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F')	//if A to F
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else
> 		{
> 			break;
> 		}
> 	iN++;
>     }
>     iCount = iN;
>     iM = iN - 1;
>     iN = 0;
>     while( iN < iCount)
>     {
> 	// digit[n] is value of hex digit at position n
> 	// (m << 2) is the number of positions to shift
> 	// OR the bits into return value
> 		intValue = intValue | (iDigit[iN] << (iM << 2));
> 		iM--;			// adjust the position to set
> 		iN++;			// next digit to process
>     }
>     return intValue;
> }
> /* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
>  * parse the HTTP header of the response message.
>  */
> void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
> {
>     unsigned int iPosition = std::string::npos;
>     unsigned int iStartPosition = iPosition;
>     if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
>     {
> 		m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
> 		iPosition += strlen( "HTTP/1.x");
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
> 		{
> 			iPosition++;
> 		}
> 		iStartPosition = iPosition;
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
> 		{
> 			iPosition++;
> 		}
> 		std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																				 iPosition - iStartPosition);
> 		m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());
> 		iStartPosition = ++iPosition;
> 		iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																		  iPosition - iStartPosition - 1);
> 	// reached the end of the first line
> 		iStartPosition = m_strResponseHTTPHeaders.find( "\n");
> 		iStartPosition++;
> 	// read header fields and add to vector
> 		do
> 		{
> 		    m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
> 			iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		    if( iPosition == std::string::npos)
> 		    {
> 				break;
> 			}
> 			std::string		strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
> 			unsigned int	iSeperator = strHeaderLine.find(":");
> 		    if( iSeperator == std::string::npos)
> 			{
> 				break;
> 			}
> 			iStartPosition = iPosition + 1;
> 			string	key = strHeaderLine.substr( 0, iSeperator);
> 			string	value = strHeaderLine.substr( iSeperator + 1,
> 												  strHeaderLine.length () - iSeperator - 1 - 1);
> 			m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
> 	    // if HTTP/1.0 we have to always close the connection by default
> 		    if( m_eProtocolType == APTHTTP1_0)
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // if HTTP/1.1 we have to assume persistant connection by default
> 	    // We need to close the connection and open a new one if we have 'Connection: close'
> 			if( key == "Connection" && value == " close")
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // For both HTTP/1.0 and HTTP/1.1,
> 	    // We need to keep the connection if we have 'Connection: Keep-Alive'
> 			if( key == "Connection" && value == " Keep-Alive")
> 			{
> 				m_bReopenConnection = false;
> 			}
> 	    // Look for cookies
> 			if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
> 		    {
> 				if( key == "Set-Cookie")
> 				{
> 					m_strSessionKey = value;
> 		    // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
> 		    // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
> 		    // And discards stuff after first ';'
> 		    // This is the same assumption used in Axis Java
> 					unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
> 		    
> 					if( ulKeyEndsAt != std::string::npos)
> 				    {
> 						m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
> 				    }
> 				}
> 		    }
> 	    /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
> 	       start="<content id>" */
> 			if( key == "Content-Type")
> 			{
> 				m_strContentType = value;
> 		
> 				unsigned long	ulMimePos = m_strContentType.find( ";");
> 				std::string		strTypePart;
> 				if( ulMimePos != std::string::npos)
> 				{
> 					strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
> 				}
> 		
> 				if( "Multipart/Related" == strTypePart)
> 				{
> 					m_bMimeTrue = true;
> 					m_strContentType = m_strContentType.substr( ulMimePos + 1,
> 																m_strContentType.length());
> 				    ulMimePos = m_strContentType.find( "boundary=");
> 					m_strMimeBoundary = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeBoundary.find( ";");
> 					m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
> 					ulMimePos = m_strContentType.find( "type=");
> 					m_strMimeType = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeType.find( ";");
> 					m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);
> 				    ulMimePos = m_strContentType.find( "start=");
> 					m_strMimeStart = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeStart.find( ";");
> 					m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
> 				}
> 			}
> 		} while( iPosition != std::string::npos);
>     }
>     else
>     {
> 		throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
> 									  "Protocol is not HTTP.");
>     }
> }
> /* HTTPTransport::processRootMimeBody() Is a public method used to
>  * parse the mime attachments.
>  */
> void HTTPTransport::processRootMimeBody()
> {
>     if( false == m_bReadPastRootMimeHeader)
>     {
> 		do
> 		{
> 			if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived += m_pszRxBuffer;
> 			}
> 		} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 	//now we have found the end of root mime header
> 		m_bReadPastRootMimeHeader = true;
> 	//processMimeHeader(); For the time being we don't process this
> 	// Done with root mime body headers, get rest of the payload 
> 	// which contain the soap message
> 		m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 	
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		if (intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
>     }
>     else
>     {
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		
> 		if( intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
> 	return;
>     }
> }
> /* HTTPTransport::processMimeHeaders() Is a public method used to
>  * parse the Mime headers of the response message.
>  */
> void HTTPTransport::processMimeHeader()
> {
>     unsigned int pos = 0;
>     unsigned int temppos = 0;
>     // Look for content lenght
>     if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
> 	{
> 		m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
> 														 m_strMimeReceived.find( "\n", pos));
> 		pos = m_strMimeContentType.find( ";");
> 		temppos = m_strMimeContentType.find( "\r\n");
> 		if( pos < temppos)
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
> 		}
> 		else
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
> 		}
>     }
>     // Look for mime root body's content transfer encoding
>     if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
> 	{
> 		m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
> 																     m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentTransferEncoding.find( "\r\n");
> 		m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
>     }
>     // Look for mime root body's content id
>     if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
> 	{
> 		m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
> 													   m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentID.find( "\r\n");
> 		m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
>     }
>     // Look for mime root body's content location
>     if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
>     {
> 		m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
> 																   m_strMimeReceived.find( "\n", pos)).c_str());
> 		temppos = m_strMimeContentLocation.find( "\r\n");
> 		m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
>     }
> }
> void HTTPTransport::processMimeBody ()
> {
> }
> void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
> {
> 	m_pszRxBuffer [0] = '\0';
> 	*m_pActiveChannel >> m_pszRxBuffer;
>     m_strMimeReceived += m_pszRxBuffer;
>     do
>     {
> 		if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 		    m_strMimeReceived += m_pszRxBuffer;
> 		}
>     } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);
>     //now we have found the end of next mime header
>     processMimeHeader();
>     m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
>     processMimeBody();
> }
> void HTTPTransport::setSocket( unsigned int uiNewSocket)
> {
>     m_pActiveChannel->setSocket( uiNewSocket);
> }
> const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
> {
>     std::string strKeyToFind = std::string( pcKey);
>     for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
> 	{
> 		if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
> 		{
> 			return ((string) m_vResponseHTTPHeaders[i].second).c_str();
> 		}
>     }
>     return NULL;
> }
> const char * HTTPTransport::getFirstTransportPropertyKey()
> {
>     m_viCurrentHeader = m_vHTTPHeaders.begin ();
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getNextTransportPropertyKey()
> {
>     //already at the end?
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     m_viCurrentHeader++;
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyKey()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyValue()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).second.c_str();
> 	}
> }
> void HTTPTransport::deleteCurrentTransportProperty()
> {
>     if( m_viCurrentHeader != m_vHTTPHeaders.end())
>     {
> 		m_vHTTPHeaders.erase( m_viCurrentHeader);
>     }
> }
> void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
> {
>     vector < std::pair < std::string,
> 	std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
>     unsigned int uiCount = 1;
>     while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
>     {
> 		if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
> 		{
> 			if( uiCount == uiOccurance)
> 			{
> 				m_vHTTPHeaders.erase( currentHeader);
> 				break;
> 			}
> 	    
> 			uiCount++;
> 		}
> 	
> 		currentHeader++;
>     }
> }
> void HTTPTransport::setMaintainSession( bool bSession)
> {
>     m_bMaintainSession = bSession;
> }
> void HTTPTransport::setSessionId( const char * pcSessionId)
> {
>     m_strSessionKey = std::string (pcSessionId);
> }
> const char * HTTPTransport::getSessionId()
> {
>     return m_strSessionKey.c_str();
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


[jira] Assigned: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS

Posted by "Samisa Abeysinghe (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXISCPP-518?page=history ]

Samisa Abeysinghe reassigned AXISCPP-518:
-----------------------------------------

    Assign To: Samisa Abeysinghe

> Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
> -------------------------------------------------------------------------------------------------------------
>
>          Key: AXISCPP-518
>          URL: http://issues.apache.org/jira/browse/AXISCPP-518
>      Project: Axis-C++
>         Type: Bug
>   Components: Transport (axis3)
>     Versions: unspecified
>  Environment: The bug affects all platforms
>     Reporter: Arcangelo Di Balsamo
>     Assignee: Samisa Abeysinghe
>  Attachments: HTTPTransport.cpp, HTTPTransportcpp diff.txt, HTTPTrasportTestClient.zip
>
> I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
> The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
> I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation. 
> The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
> I've already made a fix: the affected module is HTTPTransport.cpp.
> The modified code is :
> /*
> *   Copyright 2003-2004 The Apache Software Foundation.
> *
> *   Licensed under the Apache License, Version 2.0 (the "License");
> *   you may not use this file except in compliance with the License.
> *   You may obtain a copy of the License at
> *
> *       http://www.apache.org/licenses/LICENSE-2.0
> *
> *   Unless required by applicable law or agreed to in writing, software
> *   distributed under the License is distributed on an "AS IS" BASIS,
> *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> *   See the License for the specific language governing permissions and
> *   limitations under the License.
> */
> /*
>  * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
>  *
>  */
> #ifdef WIN32
> #pragma warning (disable : 4786)
> #pragma warning (disable : 4101)
> #endif
> #include "HTTPTransport.hpp"
> #include <stdio.h>
> #include <iostream>
> /*
>  * HTTPTransport constuctor
>  */
> HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
> m_strHTTPProtocol ("HTTP/1.1"),
> m_strHTTPMethod ("POST"),
> m_bChunked (false),
> m_bReadPastHTTPHeaders (false),
> m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
> m_bMaintainSession (false)
> {
>     m_pcEndpointUri = NULL;
>     m_pReleaseBufferCallback = 0;
>     m_eProtocolType = APTHTTP1_1;
>     m_strBytesToSend = "";
>     m_strHeaderBytesToSend = "";
>     m_iBytesLeft = 0;
>     m_iContentLength = 0;
>     m_pcReceived = 0;
> 	m_bChannelSecure = false;
>     m_pNormalChannel = 0;
>     m_pSecureChannel = 0;
> 	m_pActiveChannel = 0;
>     m_pChannelFactory = new ChannelFactory();
>     m_bMimeTrue = false;
>     m_viCurrentHeader = m_vHTTPHeaders.begin();
> 	m_pszRxBuffer = new char [BUF_SIZE];
> #ifdef WIN32
> 	m_lChannelTimeout = 10;
> #else
> 	m_lChannelTimeout = 0;
> #endif
> }
> /*
>  * HTTPTransport destuctor
>  */
> HTTPTransport::~HTTPTransport()
> {
>     if( m_pcEndpointUri)
>     {
> 	delete[] m_pcEndpointUri;
>     }
>     if( m_pChannelFactory)
> 	{
> 		delete m_pChannelFactory;
> 		m_pChannelFactory = 0;
> 	}
> 	delete [] m_pszRxBuffer;
> }
> /*
>  * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
>  * Everytime the endpoint changes then currently connected channel is closed
>  * and a new channel connection is opened.
>  *
>  * @param	EndpointURI - char * to a null terminated string that holds the
>  *			new URI. 
>  */
> void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
> {
>     bool bUpdateURL = false;
>     // Get the current channel URI
>     if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
>     {
> 	// Does the new URI equal the existing channel URI?
> 		if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
> 		{
> 	    // There is a new URI.
> 			bUpdateURL = true;
> 		}
>     }
>     else
>     {
> 		bUpdateURL = true;
>     }
>     // If there is a new URI, then this flag will be set.  Depending on whether
>     // there is an SSL implementation available, if the new URI is a secure
> 	// connection, a secure channel will be opened.  If an SSL implementation
> 	// is not available and the URL requires a secure connection then an
> 	// exception will be thrown.
>     if( bUpdateURL)
>     {
> 		if( m_pActiveChannel == NULL)
> 		{
> 			m_pActiveChannel = m_pNormalChannel;
> 		}
> 		m_pActiveChannel->setURL( pcEndpointUri);
> 		m_bReopenConnection = true;
> 	// Check if the new URI requires SSL (denoted by the https prefix).
> 		if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
> 		{
> 			if( m_pSecureChannel != NULL)
> 			{
> 				m_pNormalChannel->close();
> 				m_pActiveChannel = m_pSecureChannel;
> 				m_pActiveChannel->setURL( pcEndpointUri);
> 				m_bChannelSecure = true;
> 			}
> 			if( !m_bChannelSecure)
> 			{
> 				throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
> 			}
> 		}
> 		else
> 		{
> 	    // URI does not require a secure channel.  Delete the existing
> 	    // channel if it is secure and create a new unsecure
> 	    // channel.
> 			if (m_bChannelSecure)
> 			{
> 				if( m_pNormalChannel != NULL)
> 				{
> 					m_pSecureChannel->close();
> 					m_pActiveChannel = m_pNormalChannel;
> 					m_pActiveChannel->setURL( pcEndpointUri);
> 					m_bChannelSecure = false;
> 				}
> 				if( m_bChannelSecure)
> 				{
> 					throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
> 				}
> 			}
> 		}
>     }
> // Need this code to set the channel timeout.  If the timeout was changed
> // before the channel was created, then it may not have the correct timeout.
> // By setting it here, the channel is sure to have the correct timeout value
> // next time the channel is read.
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( m_lChannelTimeout);
> 	}
> }
> /*
>  * HTTPTransport::openConnection().
>  */
> int HTTPTransport::openConnection()
> {
> 	return m_pActiveChannel->open();
> }
> /*
>  * HTTPTransport::closeConnection().
>  */
> void HTTPTransport::closeConnection()
> {
>     // get ready for a new message.
>     m_bReadPastHTTPHeaders = false;
>     //clear the message buffer in preperation of the next read.
>     m_strReceived = "";
>     m_iContentLength = 0;
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->close();
> 	}
> }
> /*
>  * HTTPTransport::flushOutput() Is called when the message construction is
>  * complete.  The message is ready to be 'flushed out' onto the network.  
>  * Check if the URI has changed.  If it has, then need to open a new Channel
>  * instance before transmitting the message.
>  *
>  * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
>  * this will be set to TRANSPORT_FINISHED.  Otherwise, an exception will have
>  * been thrown.
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
> {
>     if( m_bReopenConnection)
>     {
> 		m_bReopenConnection = false;
> 		if( m_pActiveChannel->open() != AXIS_SUCCESS)
> 		{
> 		    int				iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
> 			const char *	pszLastError = new char[iStringLength];
> 		    memcpy( (void *) pszLastError,
> 					m_pActiveChannel->GetLastErrorMsg().c_str(),
> 					iStringLength);
> 		    throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
> 										  (char *) pszLastError);
> 			}
> 		}
>     // In preperation for sending the message, calculate the size of the message
>     // by using the string length method.
>     // NB: This calculation may not necessarily be correct when dealing with SSL
>     //     messages as the length of the encoded message is not necessarily the
>     //         same as the length of the uncoded message.
>     char buff[8];
> 	sprintf( buff, "%d", m_strBytesToSend.length ());
>     this->setTransportProperty ("Content-Length", buff);
>     // The header is now complete.  The message header and message can now be
>     // transmitted.
> 	try
> 	{
> 		*m_pActiveChannel << this->getHTTPHeaders ();
> 		*m_pActiveChannel << this->m_strBytesToSend.c_str ();
> 	}
> 	catch( HTTPTransportException & e)
> 	{
> 		throw;
> 	}
> 	catch( AxisException & e)
> 	{
> 		throw;
> 	}
> 	catch(...)
> 	{
> 		throw;
> 	}
>     // Empty the bytes to send string.
> 	m_strBytesToSend = "";
> 	m_strHeaderBytesToSend = "";
> 	return TRANSPORT_FINISHED;
> }
> /* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
>  * information block that will preceed the SOAP message.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP header block of information.
>  */
> const char * HTTPTransport::getHTTPHeaders()
> {
>     URL &			url = m_pActiveChannel->getURLObject();
>     unsigned short	uiPort = url.getPort();
>     char			buff[8];
>     m_strHeaderBytesToSend = m_strHTTPMethod + " ";
>     m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
>     m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
>     m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();
>     sprintf (buff, "%u", uiPort);
>     m_strHeaderBytesToSend += ":";
>     m_strHeaderBytesToSend += buff;
>     m_strHeaderBytesToSend += "\r\n";
>     m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";
>     // Set other HTTP headers
>     for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
>     {
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     // Set session cookie
>     if (m_bMaintainSession && (m_strSessionKey.size () > 0))
>     {
> 		m_strHeaderBytesToSend += "Cookie";
> 		m_strHeaderBytesToSend += ": ";
> 		m_strHeaderBytesToSend += m_strSessionKey;
> 		m_strHeaderBytesToSend += "\r\n";
>     }
>     m_strHeaderBytesToSend += "\r\n";
>     return m_strHeaderBytesToSend.c_str ();
> }
> /* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
>  * (i.e. GET or POST) that will be part of the HTTP header block.
>  *
>  * @return const char* Pointer to a NULL terminated character string containing
>  * the HTTP method.
>  */
> const char * HTTPTransport::getHTTPMethod()
> {
>     return m_strHTTPMethod.c_str ();
> }
> /* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
>  * method (i.e. POST or GET) that will be part of the HTTP header block.
>  *
>  * @param const char* Pointer to a NULL terminated character string containing
>  * the new HTTP method.
>  */
> void HTTPTransport::setHTTPMethod( const char *cpMethod)
> {
>     m_strHTTPMethod = std::string( cpMethod);
> }
> /* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
>  * concatinates the new send buffer to the bytes to send string.  This message
>  * will only be sent when a flush buffer is received.
>  *
>  * @param const char* SendBufer - Pointer to a NULL terminated character string
>  * containing all or some of the transmission message.
>  * @param const void* BufferId - Pointer.  This parameter is ignored.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
>  * always be TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
> {
>     m_strBytesToSend += std::string (pcSendBuffer);
>     return TRANSPORT_IN_PROGRESS;
> }
> /* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
>  * receive the synchronous reply to the sent message.
>  *
>  * @param const char* ReceiveBuffer - Pointer to a character string that on
>  * return will containing all or part of the received message.
>  * @param int* Size - Pointer to an integer value that on return will contain
>  * the length of the received message.
>  *
>  * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
>  * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
>  */
> AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
> {
>     if (0 >= m_iBytesLeft)
>     {
> 		try
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 			m_strReceived = m_pszRxBuffer;
> 		    if( !m_bReadPastHTTPHeaders)
> 		    {
> 				unsigned int start = std::string::npos;
> 				do
> 				{
> 					do
> 					{
> 						if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 						    m_strReceived += m_pszRxBuffer;
> 						}
> 					} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 					if( m_strReceived.find ("HTTP") == std::string::npos)
> 					{
> 			// Most probably what we read was left overs from earlier reads
> 			// Skip this \r\n\r\n
> 						m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 						do
> 						{
> 							if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 							{
> 								m_pszRxBuffer [0] = '\0';
> 								*m_pActiveChannel >> m_pszRxBuffer;
> 								m_strReceived += m_pszRxBuffer;
> 							}
> 						} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 			// now this must contain HTTP. Else there is a conent error.
> 					}
> 		    //now we have found the end of headers
> 					m_bReadPastHTTPHeaders = true;
> 				    unsigned int pos = 0;
> 		    // Look for content lenght
> 				    if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
> 					{
> 						m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
> 																	   m_strReceived.find( "\n", pos)).c_str());
> 				    }
> 		    // Check if the message is chunked
> 				    if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
> 					{
> 						m_bChunked = true;
> 					}
> 					else
> 					{
> 						m_bChunked = false;
> 					}
> 		    // check if there is HTTP header. If not, there must be an error and 
> 		    // will be detected by processResponseHTTPHeaders()
> 		    // However, must make sure that the left overs from eatlier reads
> 		    // do not appear before HTTP/1.x
> 					start = m_strReceived.find( "HTTP");
> 					if( start == std::string::npos)
> 					{
> 						start = 0;
> 					}
> 		    // Extract HTTP headers and process them
> 				    m_strResponseHTTPHeaders = m_strReceived.substr( start,
> 																     m_strReceived.find( "\r\n\r\n") + 2 - start);
> 				    processResponseHTTPHeaders();
> 				    if( m_iResponseHTTPStatusCode == 100)
> 				    {
> 			// Samisa: We found Continue. Keep on reading and processing headers
> 			// till we get a HTTP code other than 100
> 			// Here it is assumed that the whole of the request is already sent
> 						m_pszRxBuffer [0] = '\0';
> 						*m_pActiveChannel >> m_pszRxBuffer;
> 						m_strReceived = m_pszRxBuffer;
> 					}
> 				} while( m_iResponseHTTPStatusCode == 100);
>                 if ( m_iResponseHTTPStatusCode != 500 &&
>                     ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
> 				{
> 				    throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
> 												  const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
> 				}
> 		// Done with HTTP headers, get payload
> 				m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
> 		    }
> 	    // Read past headers. Deal with payload
> 	    // make sure we have a message with some content
> 		    if( m_strReceived.length () == 0)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived = m_pszRxBuffer;
> 			}
> 			if( m_strReceived.length () > 0) 
> 			{
> 			    if( m_bChunked && m_iContentLength < 1)	// Read first chunk
> 				{
> 			/*
> 			 *Chunked data looks like ->
> 			 *      Chunked-Body   = *chunk
> 			 *                       "0" CRLF
> 			 *                       footer
> 			 *                       CRLF
> 			 *
> 			 *      chunk          = chunk-size [ chunk-ext ] CRLF
> 			 *                         chunk-data CRLF
> 			 *
> 			 *      hex-no-zero    = <HEX excluding "0">
> 			 *
> 			 *      chunk-size     = hex-no-zero *HEX
> 			 *      chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
> 			 *      chunk-ext-name = token
> 			 *      chunk-ext-val  = token | quoted-string
> 			 *      chunk-data     = chunk-size(OCTET)
> 			 *
> 			 *      footer         = *entity-header
> 			 */
> 			// firstly read in the chunk size line.
> 			//There might be chunk extensions in there too but we may not need them
> 					unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 			// make sure we have read at least some part of the message
> 					if( endOfChunkData == std::string::npos)
> 					{
> 						do
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived = m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						} while( endOfChunkData == std::string::npos);
> 					}
> 					int endOfChunkSize = endOfChunkData;
> 			// now get the size of the chunk from the data
> 			// look to see if there are any extensions - these are put in brackets so look for those
> 					if( m_strReceived.substr( 0, endOfChunkData).find( "(") != string::npos)
> 					{
> 						endOfChunkSize = m_strReceived.find( "(");
> 					}
> 			// convert the hex String into the length of the chunk
> 					m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 			// if the chunk size is zero then we have reached the footer
> 			// If we have reached the footer then we can throw it away because we don't need it
> 					if( m_iContentLength > 0)
> 					{
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 						if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
> 						}
> 						else	// we have read lesser than chunk length
> 						{
> 							m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 						}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 					else
> 					{
> 						m_strReceived = "";
> 					}
> 				}
> 				else if( m_bChunked)	// read continued portions of a chunk
> 				{
> 			// Samisa - NOTE: It looks as if there is some logic duplication
> 			// in this block, where we read continued chunks and the block
> 			// above, where we read the first chunk. However, there are slight
> 			// logical differences here, and that is necessary to enable the
> 			// pull model used by the parser - this logic makes pulling more
> 			// efficient (30th Sept 2004)
> 					if( m_strReceived.length () >= m_iContentLength)	// We have reached end of current chunk
> 					{
> 				// Get remainder of current chunk
> 						std::string strTemp = m_strReceived.substr( 0, m_iContentLength);
> 				// Start looking for the next chunk
> 				// The format we are expecting here is:
> 				// <previous chunk>\r\n<chunk size>\r\n<next chunk>
> 						unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> 				// Make sure that we have the found the end of previous chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						m_strReceived = m_strReceived.substr( endOfChunkData + 2);	// Skip end of previous chunk
> 						endOfChunkData = m_strReceived.find( "\r\n");	// Locate the start of next chunk
> 				// Make sure that we have the starting line of next chunk
> 						while( endOfChunkData == std::string::npos)
> 						{
> 							m_pszRxBuffer [0] = '\0';
> 							*m_pActiveChannel >> m_pszRxBuffer;
> 							m_strReceived += m_pszRxBuffer;
> 							endOfChunkData = m_strReceived.find( "\r\n");
> 						}
> 						int endOfChunkSize = endOfChunkData;
> 				// look to see if there are any extensions - these are put in brackets so look for those
> 						if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
> 						{
> 							endOfChunkSize = m_strReceived.find ("(");
> 						}
> 				// convert the hex String into the length of the chunk
> 						int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> 				// if the chunk size is zero then we have reached the footer
> 				// If we have reached the footer then we can throw it away because we don't need it
> 						if( iTempContentLength > 0)
> 						{
> 				// Update the content lenght to be remainde of previous chunk and lenght of new chunk
> 							m_iContentLength += iTempContentLength;
> 				// now get the chunk without the CRLF
> 				// check if we have read past chunk length
> 							if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
> 							}
> 							else
> 							{
> 								m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> 							}
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 							if( m_bMimeTrue)
> 							{
> 								processRootMimeBody();
> 							}
> 						}
> 						else
> 						{
> 							m_strReceived = "";
> 						}
> 				// Append the data of new chunk to data from previous chunk
> 						m_strReceived = strTemp + m_strReceived;
> 						}		// End of if (m_strReceived.length() >= m_iContentLength)
> 			// If we have not reached end of current chunk, nothing to be done
> 					}
> 					else		// Not chunked
> 					{
> 				//nothing to do here
> 				/* We have received part of chunk data. If received payload
> 				 *  is a mime struct, process it
> 				 */
> 						if( m_bMimeTrue)
> 						{
> 							processRootMimeBody();
> 						}
> 					}
> 				}
> 				m_pcReceived = m_strReceived.c_str();
> 				if( m_pcReceived)
> 				{
> 					m_iBytesLeft = strlen( m_pcReceived);
> 				}
> 				else
> 				{
> 					throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
> 				}
> 				m_iContentLength -= m_iBytesLeft;
> 		}
> 		catch( HTTPTransportException & e)
> 		{
> 			throw;
> 		}
> 		catch( AxisException & e)
> 		{
> 		    throw;
> 		}
> 		catch(...)
> 		{
> 		    throw;
> 		}
>     }
>     if (( m_pcReceived) && (*m_pcReceived))
>     {
> 		int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;
> 		strncpy( pcBuffer, m_pcReceived, iToCopy);
> 		m_iBytesLeft -= iToCopy;
> 		m_pcReceived += iToCopy;
> 		*pSize = iToCopy;
> 		return TRANSPORT_IN_PROGRESS;
> 	}
> 	else
> 	{
> 		m_bReadPastHTTPHeaders = false;	// get ready for a new message
> 		m_strReceived = "";	//clear the message buffer in preperation of the next read
> 		return TRANSPORT_FINISHED;
>     }
> }
> /* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
> {
>     const char *key = NULL;
>     switch (type)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			key = "SOAPAction";
> 		    break;
> 		}
> 		case SERVICE_URI:		// need to set ?
> 		{
> 			break;
> 		}
> 		case OPERATION_NAME:	// need to set ?
> 		{
> 			break;
> 		}
> 		case SOAP_MESSAGE_LENGTH:
> 		{
> 			key = "Content-Length";	// this Axis transport handles only HTTP
> 			break;
> 		}
> 		case TRANSPORT_PROPERTIES:
> 		{
> 			m_pActiveChannel->setTransportProperty( type, value);
> 			break;
> 		}
> 		case SECURE_PROPERTIES:
> 		{
> 			m_pActiveChannel->setSecureProperties( value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
> 			break;
> 		}
> 		case CHANNEL_HTTP_SSL_DLL_NAME:
> 		{
> 			m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
> 			break;
> 		}
> 		default:
> 		{
> 			break;
> 		}
>     }
>     if( key)
>     {
> 		setTransportProperty( key, value);
>     }
> }
> /* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
>  * method used to set a HTTP transport or SSL implementation property.
>  *
>  * @param const char* Key is a NULL terminated character string containing
>  * the type of information to be stored in either the HTTP Header or SSL
>  * implementation settings.
>  * @param const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
> {
>     if( !pcKey || !pcValue)	// Samisa - fix for AXISCPP-295. We must check for valid values here.
> 	{
> 		return;
> 	}
>     bool b_KeyFound = false;
>     if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
>     {
> 		std::string strKeyToFind = std::string( pcKey);
> 		for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
> 		{
> 		    if (m_vHTTPHeaders[i].first == strKeyToFind)
> 			{
> 				m_vHTTPHeaders[i].second = (string) pcValue;
> 				b_KeyFound = true;
> 				break;
> 		    }
> 		}
>     }
>     if( !b_KeyFound)
>     {
> 		m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
>     }
> }
> /* HTTPTransport::getTransportProperty( Type) Is a public method that will
>  * return the HTTP Header/SSL implementation value associated with type.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header or SSL
>  * implementation settings.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the type.
>  */
> const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
> {
>     const char *pszPropValue = NULL;
>     switch( eType)
>     {
> 	    case SOAPACTION_HEADER:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "SOAPAction");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	    case SERVICE_URI:
> 		{
> 			break;
> 		}
> 	    case OPERATION_NAME:
> 		{
> 			break;
> 		}
> 	    case SOAP_MESSAGE_LENGTH:
> 		{
> 			int iIndex = FindTransportPropertyIndex( "Content-Length");
> 		    if (iIndex > -1)
> 		    {
> 				pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> 		    }
> 		    break;
> 		}
> 	case TRANSPORT_PROPERTIES:
>     case SECURE_PROPERTIES:
> 		{
> 			pszPropValue = m_pActiveChannel->getTransportProperty( eType);
> 			break;
> 		}
> 	case CHANNEL_HTTP_SSL_DLL_NAME:
> 	case CHANNEL_HTTP_DLL_NAME:
> 		{
> 			break;
> 		}
>     }
>     return pszPropValue;
> }
> /* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
>  * return the HTTP Header index associated with Key.
>  *
>  * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
>  * the type of information to be retrieved in either the HTTP Header settings.
>  *
>  * @return int Index is an index to the key within the HTTP Header list.  If
>  * the return value is -1, then the key was not found.
>  */
> int HTTPTransport::FindTransportPropertyIndex( string sKey)
> {
>     bool	bKeyFound = false;
>     int		iIndex = 0;
>     do
>     {
> 		if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
> 		{
> 			bKeyFound = true;
> 		}
> 		else
> 		{
> 			iIndex++;
> 		}
>     } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);
>     if( !bKeyFound)
>     {
> 		iIndex = -1;
>     }
>     return iIndex;
> }
> /* HTTPTransport::getServiceName() Is a public method to return the HTTP
>  * Header service name.
>  *
>  * @return const char* Value is a NULL terminated character string containing
>  * the value associated with the service name.
>  */
> const char * HTTPTransport::getServiceName()
> {
>     //Assume SOAPAction header to contain service name
>     int		iIndex = FindTransportPropertyIndex( "SOAPAction");
>     if (iIndex > -1)
>     {
> 		return m_vHTTPHeaders[iIndex].second.c_str();
>     }
>     return NULL;
> }
> AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
> {
>     return m_eProtocolType;
> }
> int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
> {
>     if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
>     {
> 		m_eProtocolType = eProtocol;
> 		m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";
> 		return AXIS_SUCCESS;
>     }
>     else
> 	{
> 		return AXIS_FAIL;
> 	}
> }
> /**
>  * HTTPTransport::getSubProtocol() is a public method that is supposed to
>  * return the sub protocol (currently this method always return 0).
>  * This method is supposed to return whether it is http GET or POST
>  */
> int HTTPTransport::getSubProtocol()
> {
>     //TODO
>     // for SimpleAxisServer assume POST
>     return AXIS_HTTP_POST;
>     //return 0;
> }
> /* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
>  * updating the proxy for the connection.
>  *
>  * @param const char* Host is a NULL terminated character string containing the new
>  * proxy host.
>  * @param unsigned int Port is the new proxy port number.
>  */
> void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
> {
>     m_strProxyHost = pcProxyHost;
>     m_uiProxyPort = uiProxyPort;
>     m_bUseProxy = true;
> }
> /* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
>  * current maximum timeout period between that can elapse between receiving
>  * message parts.
>  *
>  * @param const long Timeout is a long value in seconds.
>  */
> void HTTPTransport::setTimeout( const long lSeconds)
> {
> 	if( m_pActiveChannel != NULL)
> 	{
> 		m_pActiveChannel->setTimeout( lSeconds);
> 	}
> 	m_lChannelTimeout = lSeconds;
> }
> /* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
>  * current HTTP protocol settings.
>  *
>  * @return const char* HTTPProtocol is a NULL terminated character string
>  * containing the HTTP protocol.
>  */
> const char * HTTPTransport::getHTTPProtocol()
> {
>     return m_strHTTPProtocol.c_str ();
> }
> /* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
>  */
> int axtoi( char *pcHexStg)
> {
>     int		iN = 0;			// position in string
>     int		iM = 0;			// position in digit[] to shift
>     int		iCount;			// loop index
>     int		intValue = 0;	// integer value of hex string
>     int		iDigit[32];		// hold values to convert
>     while( iN < 32)
>     {
> 		if( pcHexStg[iN] == '\0')
> 		{
> 			break;
> 		}
> 	
> 		if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40)	//if 0 to 9
> 		{
> 			iDigit[iN] = pcHexStg[iN] & 0x0f;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f')	//if a to f
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F')	//if A to F
> 		{
> 			iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9;	//convert to int
> 		}
> 		else
> 		{
> 			break;
> 		}
> 	iN++;
>     }
>     iCount = iN;
>     iM = iN - 1;
>     iN = 0;
>     while( iN < iCount)
>     {
> 	// digit[n] is value of hex digit at position n
> 	// (m << 2) is the number of positions to shift
> 	// OR the bits into return value
> 		intValue = intValue | (iDigit[iN] << (iM << 2));
> 		iM--;			// adjust the position to set
> 		iN++;			// next digit to process
>     }
>     return intValue;
> }
> /* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
>  * parse the HTTP header of the response message.
>  */
> void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
> {
>     unsigned int iPosition = std::string::npos;
>     unsigned int iStartPosition = iPosition;
>     if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
>     {
> 		m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
> 		iPosition += strlen( "HTTP/1.x");
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
> 		{
> 			iPosition++;
> 		}
> 		iStartPosition = iPosition;
> 		while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
> 		{
> 			iPosition++;
> 		}
> 		std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																				 iPosition - iStartPosition);
> 		m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());
> 		iStartPosition = ++iPosition;
> 		iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
> 																		  iPosition - iStartPosition - 1);
> 	// reached the end of the first line
> 		iStartPosition = m_strResponseHTTPHeaders.find( "\n");
> 		iStartPosition++;
> 	// read header fields and add to vector
> 		do
> 		{
> 		    m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
> 			iPosition = m_strResponseHTTPHeaders.find( "\n");
> 		    if( iPosition == std::string::npos)
> 		    {
> 				break;
> 			}
> 			std::string		strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
> 			unsigned int	iSeperator = strHeaderLine.find(":");
> 		    if( iSeperator == std::string::npos)
> 			{
> 				break;
> 			}
> 			iStartPosition = iPosition + 1;
> 			string	key = strHeaderLine.substr( 0, iSeperator);
> 			string	value = strHeaderLine.substr( iSeperator + 1,
> 												  strHeaderLine.length () - iSeperator - 1 - 1);
> 			m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
> 	    // if HTTP/1.0 we have to always close the connection by default
> 		    if( m_eProtocolType == APTHTTP1_0)
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // if HTTP/1.1 we have to assume persistant connection by default
> 	    // We need to close the connection and open a new one if we have 'Connection: close'
> 			if( key == "Connection" && value == " close")
> 			{
> 				m_bReopenConnection = true;
> 			}
> 	    // For both HTTP/1.0 and HTTP/1.1,
> 	    // We need to keep the connection if we have 'Connection: Keep-Alive'
> 			if( key == "Connection" && value == " Keep-Alive")
> 			{
> 				m_bReopenConnection = false;
> 			}
> 	    // Look for cookies
> 			if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
> 		    {
> 				if( key == "Set-Cookie")
> 				{
> 					m_strSessionKey = value;
> 		    // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
> 		    // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
> 		    // And discards stuff after first ';'
> 		    // This is the same assumption used in Axis Java
> 					unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
> 		    
> 					if( ulKeyEndsAt != std::string::npos)
> 				    {
> 						m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
> 				    }
> 				}
> 		    }
> 	    /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
> 	       start="<content id>" */
> 			if( key == "Content-Type")
> 			{
> 				m_strContentType = value;
> 		
> 				unsigned long	ulMimePos = m_strContentType.find( ";");
> 				std::string		strTypePart;
> 				if( ulMimePos != std::string::npos)
> 				{
> 					strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
> 				}
> 		
> 				if( "Multipart/Related" == strTypePart)
> 				{
> 					m_bMimeTrue = true;
> 					m_strContentType = m_strContentType.substr( ulMimePos + 1,
> 																m_strContentType.length());
> 				    ulMimePos = m_strContentType.find( "boundary=");
> 					m_strMimeBoundary = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeBoundary.find( ";");
> 					m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
> 					ulMimePos = m_strContentType.find( "type=");
> 					m_strMimeType = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeType.find( ";");
> 					m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);
> 				    ulMimePos = m_strContentType.find( "start=");
> 					m_strMimeStart = m_strContentType.substr( ulMimePos);
> 					ulMimePos = m_strMimeStart.find( ";");
> 					m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
> 				}
> 			}
> 		} while( iPosition != std::string::npos);
>     }
>     else
>     {
> 		throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
> 									  "Protocol is not HTTP.");
>     }
> }
> /* HTTPTransport::processRootMimeBody() Is a public method used to
>  * parse the mime attachments.
>  */
> void HTTPTransport::processRootMimeBody()
> {
>     if( false == m_bReadPastRootMimeHeader)
>     {
> 		do
> 		{
> 			if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> 			{
> 				m_pszRxBuffer [0] = '\0';
> 				*m_pActiveChannel >> m_pszRxBuffer;
> 				m_strReceived += m_pszRxBuffer;
> 			}
> 		} while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> 	//now we have found the end of root mime header
> 		m_bReadPastRootMimeHeader = true;
> 	//processMimeHeader(); For the time being we don't process this
> 	// Done with root mime body headers, get rest of the payload 
> 	// which contain the soap message
> 		m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> 	
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		if (intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
>     }
>     else
>     {
> 		unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> 		
> 		if( intMimeTemp != std::string::npos)
> 		{
> 			m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> 			m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> 	    /* Using m_strMimeReceived will be 
> 	     * continued when getAttachment is called.
> 	     */
> 			m_bMimeTrue = false;
> 		}
> 	return;
>     }
> }
> /* HTTPTransport::processMimeHeaders() Is a public method used to
>  * parse the Mime headers of the response message.
>  */
> void HTTPTransport::processMimeHeader()
> {
>     unsigned int pos = 0;
>     unsigned int temppos = 0;
>     // Look for content lenght
>     if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
> 	{
> 		m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
> 														 m_strMimeReceived.find( "\n", pos));
> 		pos = m_strMimeContentType.find( ";");
> 		temppos = m_strMimeContentType.find( "\r\n");
> 		if( pos < temppos)
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
> 		}
> 		else
> 		{
> 			m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
> 		}
>     }
>     // Look for mime root body's content transfer encoding
>     if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
> 	{
> 		m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
> 																     m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentTransferEncoding.find( "\r\n");
> 		m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
>     }
>     // Look for mime root body's content id
>     if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
> 	{
> 		m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
> 													   m_strMimeReceived.find( "\n", pos));
> 		temppos = m_strMimeContentID.find( "\r\n");
> 		m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
>     }
>     // Look for mime root body's content location
>     if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
>     {
> 		m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
> 																   m_strMimeReceived.find( "\n", pos)).c_str());
> 		temppos = m_strMimeContentLocation.find( "\r\n");
> 		m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
>     }
> }
> void HTTPTransport::processMimeBody ()
> {
> }
> void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
> {
> 	m_pszRxBuffer [0] = '\0';
> 	*m_pActiveChannel >> m_pszRxBuffer;
>     m_strMimeReceived += m_pszRxBuffer;
>     do
>     {
> 		if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
> 		{
> 			m_pszRxBuffer [0] = '\0';
> 			*m_pActiveChannel >> m_pszRxBuffer;
> 		    m_strMimeReceived += m_pszRxBuffer;
> 		}
>     } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);
>     //now we have found the end of next mime header
>     processMimeHeader();
>     m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
>     processMimeBody();
> }
> void HTTPTransport::setSocket( unsigned int uiNewSocket)
> {
>     m_pActiveChannel->setSocket( uiNewSocket);
> }
> const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
> {
>     std::string strKeyToFind = std::string( pcKey);
>     for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
> 	{
> 		if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
> 		{
> 			return ((string) m_vResponseHTTPHeaders[i].second).c_str();
> 		}
>     }
>     return NULL;
> }
> const char * HTTPTransport::getFirstTransportPropertyKey()
> {
>     m_viCurrentHeader = m_vHTTPHeaders.begin ();
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getNextTransportPropertyKey()
> {
>     //already at the end?
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     m_viCurrentHeader++;
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyKey()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).first.c_str();
> 	}
> }
> const char * HTTPTransport::getCurrentTransportPropertyValue()
> {
>     if( m_viCurrentHeader == m_vHTTPHeaders.end())
> 	{
> 		return NULL;
> 	}
>     else
> 	{
> 		return (*m_viCurrentHeader).second.c_str();
> 	}
> }
> void HTTPTransport::deleteCurrentTransportProperty()
> {
>     if( m_viCurrentHeader != m_vHTTPHeaders.end())
>     {
> 		m_vHTTPHeaders.erase( m_viCurrentHeader);
>     }
> }
> void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
> {
>     vector < std::pair < std::string,
> 	std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
>     unsigned int uiCount = 1;
>     while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
>     {
> 		if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
> 		{
> 			if( uiCount == uiOccurance)
> 			{
> 				m_vHTTPHeaders.erase( currentHeader);
> 				break;
> 			}
> 	    
> 			uiCount++;
> 		}
> 	
> 		currentHeader++;
>     }
> }
> void HTTPTransport::setMaintainSession( bool bSession)
> {
>     m_bMaintainSession = bSession;
> }
> void HTTPTransport::setSessionId( const char * pcSessionId)
> {
>     m_strSessionKey = std::string (pcSessionId);
> }
> const char * HTTPTransport::getSessionId()
> {
>     return m_strSessionKey.c_str();
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira