http.cpp revision 53782b6babe71076b1bb35e1bc394b4f0b040b70
/* $Id$ */
/** @file
* IPRT - HTTP communication API.
*/
/*
* Copyright (C) 2012-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
typedef struct RTHTTPINTERNAL
{
/** Magic value. */
/** cURL handle. */
/** The last response code. */
long lLastResp;
/** custom headers */
struct curl_slist *pHeaders;
/** CA certificate for HTTPS authentication check. */
char *pcszCAFile;
/** Abort the current HTTP request if true. */
bool fAbort;
/** The location field for 301 responses. */
char *pszRedirLocation;
typedef RTHTTPINTERNAL *PRTHTTPINTERNAL;
typedef struct RTHTTPMEMCHUNK
{
typedef RTHTTPMEMCHUNK *PRTHTTPMEMCHUNK;
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
do { \
} while (0)
/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
/** Validates a handle and returns (void) if not valid. */
#define RTHTTP_VALID_RETURN_VOID(hHttp) \
do { \
} while (0)
{
if (CURL_FAILED(rcCurl))
return VERR_HTTP_INIT_FAILED;
if (!pCurl)
return VERR_HTTP_INIT_FAILED;
if (!pHttpInt)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
}
{
if (!hHttp)
return;
if (pHttpInt->pcszCAFile)
if (pHttpInt->pszRedirLocation)
}
{
{
}
return cbAll;
}
{
}
{
return VINF_SUCCESS;
}
{
if (!pHttpInt->pszRedirLocation)
return VERR_HTTP_NOT_FOUND;
return VINF_SUCCESS;
}
{
/*
* Very limited right now, just enought to make it work for ourselves.
*/
if (RT_SUCCESS(rc))
{
int rcCurl;
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
}
else
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
}
}
else if (rc == VERR_ENV_VAR_NOT_FOUND)
rc = VINF_SUCCESS;
return rc;
}
const char *pcszProxyUser, const char *pcszProxyPwd)
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
if (uPort != 0)
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
}
if (pcszProxyUser && pcszProxyPwd)
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
}
return VINF_SUCCESS;
}
{
if (!cHeaders)
{
return VINF_SUCCESS;
}
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
}
{
int rc = VINF_SUCCESS;
if (cert)
{
{
unsigned cb;
unsigned char md[EVP_MAX_MD_SIZE];
if (rc1 > 0)
{
if (*pabSha1)
{
if (rc1 > 0)
{
if (*pabSha512)
{
}
else
rc = VERR_NO_MEMORY;
}
else
}
else
rc = VERR_NO_MEMORY;
}
else
}
else
}
else
if (RT_FAILURE(rc))
{
}
return rc;
}
{
if (pHttpInt->pcszCAFile)
if (!pHttpInt->pcszCAFile)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
}
/**
* Figures out the IPRT status code for a GET.
*
* @returns IPRT status code.
* @param pHttpInt HTTP instance.
* @param rcCurl What curl returned.
*/
{
int rc = VERR_INTERNAL_ERROR;
if (pHttpInt->pszRedirLocation)
{
}
{
{
case 200:
/* OK, request was fulfilled */
case 204:
/* empty response */
rc = VINF_SUCCESS;
break;
case 301:
{
const char *pszRedirect;
break;
}
case 400:
/* bad request */
break;
case 403:
/* forbidden, authorization will not help */
break;
case 404:
/* URL not found */
break;
}
}
else
{
switch (rcCurl)
{
case CURLE_URL_MALFORMAT:
break;
case CURLE_COULDNT_CONNECT:
break;
case CURLE_SSL_CONNECT_ERROR:
break;
case CURLE_SSL_CACERT:
/* The peer certificate cannot be authenticated with the CA certificates
* set by RTHttpSetCAFile(). We need other or additional CA certificates. */
break;
case CURLE_SSL_CACERT_BADFILE:
/* CAcert file (see RTHttpSetCAFile()) has wrong format */
break;
/* forcefully aborted */
break;
default:
break;
}
}
return rc;
}
{
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
#if 0
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
#endif
const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt";
if (pHttpInt->pcszCAFile)
if (RTFileExists(pcszCAFile))
{
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
}
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
return rc;
}
{
*ppszResponse = (char*)pv;
return rc;
}
{
}
{
if (RT_SUCCESS(rc))
return cbWritten;
return 0;
}
{
/*
* Set up the request.
*/
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
#if 0
if (CURL_FAILED(rcCurl))
return VERR_INVALID_PARAMETER;
#endif
const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt";
if (pHttpInt->pcszCAFile)
if (RTFileExists(pcszCAFile))
{
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
}
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
if (CURL_FAILED(rcCurl))
return VERR_INTERNAL_ERROR;
/*
* Open the output file.
*/
int rc = RTFileOpen(&hFile, pszDstFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_READWRITE);
if (RT_SUCCESS(rc))
{
if (!CURL_FAILED(rcCurl))
{
/*
* Perform the request.
*/
}
else
}
return rc;
}