Logo Search packages:      
Sourcecode: sblim-wbemcli version File versions  Download package

CimWinHttp.cpp

/*
 * CimWinHttp.cpp
 *
 * (C) Copyright IBM Corp. 2004
 *
 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE COMMON PUBLIC LICENSE
 * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
 * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
 *
 * You can obtain a current copy of the Common Public License from
 * http://oss.software.ibm.com/developerworks/opensource/license-cpl.html
 *
 * Author:       Adrian Schuur <schuur@de.ibm.com>
 * Contributors: Viktor Mihajlovski <mihajlov@de.ibm.com>
 *               Markus Mueller <markus_mueller@de.ibm.com>
 *               Steve Shepherd <steve.shepherd@configuresoft.com>
 *               Heidi Neumann  <heidineu@de.ibm.com>
 *
 * Description: Line command interface to DMTF conforming WBEM servers
*/
#include "stdafx.h"
#include "CimWinHttp.h"

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::CimomWinHttp( )
//  CimomWinHttp::~CimomWinHttp( )
//
//  Default constructor & destructor.
//
////////////////////////////////////////////////////////////////////////
extern int useNl;

CimomWinHttp::CimomWinHttp()
{
      m_hSession = NULL;
      m_hConnect = NULL;
      m_hRequest = NULL;
      m_lpPayload = NULL;
      m_dwPayloadSize = 0;
}

CimomWinHttp::~CimomWinHttp()
{
      if (m_lpPayload) delete m_lpPayload;
      if (m_hRequest)   ::WinHttpCloseHandle(m_hRequest);
      if (m_hConnect)   ::WinHttpCloseHandle(m_hConnect);
      if (m_hSession)   ::WinHttpCloseHandle(m_hSession);
}

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::SetTimeouts( )
//
//  Change the timeouts for HTTP messages.
//
////////////////////////////////////////////////////////////////////////
bool CimomWinHttp::SetTimeouts(int Connect, int Send, int Receive)
{
      bool bReturn = false;

      if (m_hSession)
      {
            if (WinHttpSetTimeouts(m_hSession, 0, Connect, Send, Receive))
            {
                  bReturn = true;
            }
      }

      return bReturn;
}

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::addPayload( )
//
//  Add the message payload to the HTTP message.
//
////////////////////////////////////////////////////////////////////////
void CimomWinHttp::addPayload(char *pl)
{
      addPayload(pl, strlen(pl));
}

void CimomWinHttp::addPayload(LPCVOID lpPayload, DWORD dwSize)
{
      if (m_lpPayload) delete m_lpPayload;
      m_lpPayload = new char[dwSize];
      m_dwPayloadSize = dwSize;
      if (m_lpPayload)
      {
            memcpy(m_lpPayload, lpPayload, dwSize);
      }
      else
      {
            throw("addPayload failed: could not allocate a buffer.");
      }
}

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::genRequest( )
//
//  Create the HTTP message.
//
////////////////////////////////////////////////////////////////////////
void CimomWinHttp::genRequest(URL &url, char *op, bool cls, bool keys)
{
      if (!supportsSSL() && url.scheme == "https")
            throw HttpException("WinHttp does not support https urls.");
      
      DWORD dwLen, dwMBLen;
      WCHAR pszSingle[512];
      BOOL  bResult = FALSE;
      LPCWSTR sHeaders =      L"Content-type: application/xml; charset=\"utf-8\"\r\n"
                                    L"Connection: Keep-Alive, TE\r\n"
                                    L"CIMProtocolVersion: 1.0\r\n"
                                    L"CIMOperation: MethodCall\r\n";

      m_hSession = ::WinHttpOpen(L"EcmXpdTool", WINHTTP_ACCESS_TYPE_NO_PROXY,
                                    WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);

      if (!m_hSession)
      {
            throw("::WinHttpOpen failed");
      }


      INTERNET_PORT iPort;

      if (sscanf(url.port, "%hui", &iPort) != 1)
      {
            iPort = 5988;
      }

      dwLen = strlen(url.host) + 1;
      wchar_t *wpHost = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t)));
      if (!wpHost)
      {
            throw("Insufficient memory available");
      }
      dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.host, dwLen, wpHost, dwLen);
      m_hConnect = ::WinHttpConnect(m_hSession, wpHost, iPort, 0);
      free(wpHost);

      if (!m_hConnect || dwMBLen == 0)
      {
            throw("::WinHttpConnect failed");
      }

      // Create an HTTP Request handle.
      m_hRequest = ::WinHttpOpenRequest(m_hConnect, L"POST", L"/cimom",
                                                         NULL, WINHTTP_NO_REFERER,
                                                         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
      if (!m_hRequest)
      {
            throw("::WinHttpOpenRequest failed");
      }

      bResult = ::WinHttpAddRequestHeaders(m_hRequest, sHeaders,
                                                      ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD);


      dwLen = strlen(op) + 1;
      wchar_t *wpCimOp = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t)));
      if (!wpCimOp)
      {
            throw("Insufficient memory available");
      }
      dwMBLen = MultiByteToWideChar(CP_UTF8, 0, op, dwLen, wpCimOp, dwLen);

      memset(pszSingle, '\0', sizeof(pszSingle));
      wcscat(pszSingle, L"CIMMethod: ");
      wcscat(pszSingle, wpCimOp);
      wcscat(pszSingle, L"\r\n");
      free(wpCimOp);

      bResult = ::WinHttpAddRequestHeaders(m_hRequest, pszSingle,
                                                      ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD);

      string sb;
      url.ns.toStringBuffer(sb,"%2F");
      if (cls)
      {
            sb = sb + "%3A" + url.cName;
            if (keys)
            {
                  char sep = '.';
                  int t=useNl;
                  useNl=0;
                  for ( unsigned i = 0 ; i < url.keys.size() ; i++ )
                  {
                        string sk;
                        url.keys[i].toStringBuffer(sk, "");
                        sb = sb + sep + sk;
                        sep = ',';
                  }
                  useNl=t;
            }
      }
      dwLen = strlen(sb.c_str()) + 1;
      wchar_t *wpNS = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t)));
      if (!wpNS)
      {
            throw("Insufficient memory available");
      }
      dwMBLen = MultiByteToWideChar(CP_UTF8, 0, sb.c_str(), dwLen, wpNS, dwLen);

      memset(pszSingle, '\0', sizeof(pszSingle));
      wcscat(pszSingle, L"CIMObject: ");
      wcscat(pszSingle, wpNS);
      wcscat(pszSingle, L"\r\n");
      free(wpNS);

      bResult = ::WinHttpAddRequestHeaders(m_hRequest, pszSingle,
                                                      ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD);

      dwLen = strlen(url.password) + 1;
      wchar_t *wpPswd = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t)));
      if (!wpPswd)
      {
            throw("Insufficient memory available");
      }
      dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.password, dwLen, wpPswd, dwLen);

      dwLen = strlen(url.user) + 1;
      wchar_t *wpUser = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t)));
      if (!wpUser)
      {
            throw("Insufficient memory available");
      }
      dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.user, dwLen, wpUser, dwLen);

      bResult = WinHttpSetCredentials(m_hRequest, WINHTTP_AUTH_TARGET_SERVER,
                                                      WINHTTP_AUTH_SCHEME_BASIC,
                                                      wpUser, wpPswd, NULL);
      free(wpPswd);
      free(wpUser);
}

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::getResponse( )
//
//  Send the message and get the response.
//
////////////////////////////////////////////////////////////////////////
#ifdef OLD
string CimomWinHttp::getResponse()
{
      BOOL bResult;
      LPSTR pszOutBuffer = NULL;

    if (m_hRequest)
      {
        bResult = WinHttpSendRequest(m_hRequest,
                                       WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                       WINHTTP_NO_REQUEST_DATA, 0,
                                       m_dwPayloadSize, 0);

            // Write data to the server.
            if (bResult)
            {
                  DWORD dwBytesWritten = 0;
                  bResult = WinHttpWriteData(m_hRequest, m_lpPayload,
                                                            m_dwPayloadSize, &dwBytesWritten);
            }

            // End the request.
            if (bResult)
            {
                  bResult = WinHttpReceiveResponse(m_hRequest, NULL);
            }

            // Keep checking for data until there is nothing left.
            if (bResult)
            {
                  DWORD dwContentLength = 0;
                  DWORD dwCLSize = sizeof(dwContentLength);

                  if (!WinHttpQueryHeaders(m_hRequest,
                              WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
                              WINHTTP_HEADER_NAME_BY_INDEX, &dwContentLength, &dwCLSize,
                              WINHTTP_NO_HEADER_INDEX))
                  {
                        DWORD dwLastError = ::GetLastError();
                        LPVOID lpvMessageBuffer = NULL;
                        DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                                FORMAT_MESSAGE_FROM_HMODULE |
                                                FORMAT_MESSAGE_FROM_SYSTEM;

                        if (::FormatMessage(dwFlags, m_hRequest, dwLastError, 0,
                                                      (LPTSTR)&lpvMessageBuffer, 10, NULL) > 0)
                        {
                              throw((char *)lpvMessageBuffer);
                        }
                        else
                        {
                              throw("WinHttpQueryHeaders() failed");
                        }
                  }

                  if (dwContentLength > 0)
                  {
                        DWORD dwSize = 0;
                        DWORD dwTotal = 0;

                        // Allocate space for the buffer.
                        pszOutBuffer = new char[dwContentLength+1];
                        if (!pszOutBuffer)
                        {
                              throw("Out of memory");
                        }
                        else
                        {
                              ::ZeroMemory(pszOutBuffer, dwContentLength+1);
                              do
                              {
                                    // Check for available data.
                                    dwSize = 0;
                                    if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize))
                                    {
                                          throw("WinHttpQueryDataAvailable failed");
                                    }

                                    // Read the Data.
                                    DWORD dwDownloaded = 0;
                                    if (!WinHttpReadData(m_hRequest,
                                                                        (LPVOID)(pszOutBuffer+dwTotal),
                                                                        dwSize, &dwDownloaded))
                                    {
                                          throw("WinHttpReadData failed");
                                    }
                                    else
                                    {
                                          dwTotal += dwSize;
                                    }

                              } while (dwSize>0);

                              // NULL terminate
                              pszOutBuffer[dwTotal] = '\0';
                        }
                  }
            }

            // Report any errors.
            if (!bResult)
            {
                  throw("GetResponse failed");
            }
      }
      else
      {
            throw("GetResponse failed: Request object not prepared.");
      }

   return (char *)(pszOutBuffer ? pszOutBuffer : "");
}
#endif      /* OLD */

////////////////////////////////////////////////////////////////////////
//
//  CimomWinHttp::getResponse( )
//
//  Send the message and get the response.
//
////////////////////////////////////////////////////////////////////////
string CimomWinHttp::getResponse()
{
      BOOL bResult;
    LPSTR pszOutBuffer = NULL;

      if (m_hRequest)
      {
        bResult = WinHttpSendRequest(m_hRequest,
                                       WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                       WINHTTP_NO_REQUEST_DATA, 0,
                                       m_dwPayloadSize, 0);

            // Write data to the server.
            if (bResult)
            {
                  DWORD dwBytesWritten = 0;
                  bResult = WinHttpWriteData(m_hRequest, m_lpPayload,
                                                            m_dwPayloadSize, &dwBytesWritten);
            }

            // End the request.
            if (bResult)
            {
                  bResult = WinHttpReceiveResponse(m_hRequest, NULL);
            }

            // Keep checking for data until there is nothing left.
            if (bResult)
            {
                  DWORD dwSize = 0;
                  DWORD dwTotal = 0;

                  do 
                  {
                        // Check for available data.
                        dwSize = 0;
                        if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize))
                        {
                              throw("WinHttpQueryDataAvailable failed");
                        }

                        if (dwSize <= 0)
                        {
                              continue;
                        }

                        // Allocate space for the buffer.
                        LPSTR pszNewBuffer = new char[dwSize + 1];
                        if (!pszNewBuffer)
                        {
                              throw("Out of memory");
                        }
                        else
                        {
                              DWORD dwDownloaded = 0;

                              // Read the Data.
                              ::ZeroMemory(pszNewBuffer, dwSize + 1);

                              if (!WinHttpReadData(m_hRequest, (LPVOID)pszNewBuffer, 
                                                              dwSize, &dwDownloaded))
                              {
                                    throw("WinHttpReadData failed");
                              }

                              if (!pszOutBuffer)
                              {
                                    pszOutBuffer = pszNewBuffer;
                              }
                              else
                              {
                                    LPSTR pszTmpBuffer = new char[dwTotal + dwSize + 1];
                                    if (!pszTmpBuffer)
                                    {
                                          throw("Out of memory");
                                    }

                                    ::CopyMemory(pszTmpBuffer, pszOutBuffer, dwTotal);
                                    ::CopyMemory(pszTmpBuffer + dwTotal, pszNewBuffer, dwSize);

                                    delete [] pszOutBuffer;
                                    delete [] pszNewBuffer;

                                    pszOutBuffer = pszTmpBuffer;
                              }
                              dwTotal += dwSize;
                        }
                  } while (dwSize > 0);
            }

            // Report any errors.
            if (!bResult)
            {
                  throw("GetResponse failed");
            }
      }
      else
      {
            throw("GetResponse failed: Request object not prepared.");
      }

   return (char *)(pszOutBuffer ? pszOutBuffer : "");
}

void CimomWinHttp::setClientCertificates(const char * cacert, int noverify,
                               const char * certificate,
                               const char * key) 
{
   if (!supportsSSL())
      throw HttpException("CimWinHttp does not support https urls.");
}

Generated by  Doxygen 1.6.0   Back to index