RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pcszProxy, uint32_t uPort, const char *pcszProxyUser, const char *pcszProxyPwd) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); AssertPtrReturn(pcszProxy, VERR_INVALID_PARAMETER); int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, pcszProxy); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; if (uPort != 0) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPORT, (long)uPort); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } if (pcszProxyUser && pcszProxyPwd) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYUSERNAME, pcszProxyUser); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPASSWORD, pcszProxyPwd); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } return VINF_SUCCESS; }
RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); /* * Very limited right now, just enought to make it work for ourselves. */ char szProxy[_1K]; int rc = RTEnvGetEx(RTENV_DEFAULT, "http_proxy", szProxy, sizeof(szProxy), NULL); if (RT_SUCCESS(rc)) { int rcCurl; if (!strncmp(szProxy, RT_STR_TUPLE("http://"))) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPORT, 80); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } else { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } } else if (rc == VERR_ENV_VAR_NOT_FOUND) rc = VINF_SUCCESS; return rc; }
RTR3DECL(int) rtHttpGet(RTHTTP hHttp, const char *pcszUrl, uint8_t **ppvResponse, size_t *pcb) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); pHttpInt->fAbort = false; int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pcszUrl); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #if 0 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_VERBOSE, 1); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #endif const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt"; if (pHttpInt->pcszCAFile) pcszCAFile = pHttpInt->pcszCAFile; if (RTFileExists(pcszCAFile)) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, pcszCAFile); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; } RTHTTPMEMCHUNK chunk = { NULL, 0 }; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void*)&chunk); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void*)pHttpInt); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_NOPROGRESS, (long)0); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; rcCurl = curl_easy_perform(pHttpInt->pCurl); int rc = rtHttpGetCalcStatus(pHttpInt, rcCurl); *ppvResponse = chunk.pu8Mem; *pcb = chunk.cb; return rc; }
RTR3DECL(int) RTHttpCreate(PRTHTTP phHttp) { AssertPtrReturn(phHttp, VERR_INVALID_PARAMETER); CURLcode rcCurl = curl_global_init(CURL_GLOBAL_ALL); if (CURL_FAILED(rcCurl)) return VERR_HTTP_INIT_FAILED; CURL *pCurl = curl_easy_init(); if (!pCurl) return VERR_HTTP_INIT_FAILED; PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)RTMemAllocZ(sizeof(RTHTTPINTERNAL)); if (!pHttpInt) return VERR_NO_MEMORY; pHttpInt->u32Magic = RTHTTP_MAGIC; pHttpInt->pCurl = pCurl; *phHttp = (RTHTTP)pHttpInt; return VINF_SUCCESS; }
RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); if (!cHeaders) { if (pHttpInt->pHeaders) curl_slist_free_all(pHttpInt->pHeaders); pHttpInt->pHeaders = 0; return VINF_SUCCESS; } struct curl_slist *pHeaders = NULL; for (size_t i = 0; i < cHeaders; i++) pHeaders = curl_slist_append(pHeaders, papszHeaders[i]); pHttpInt->pHeaders = pHeaders; int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_HTTPHEADER, pHeaders); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; return VINF_SUCCESS; }
RTR3DECL(int) RTHttpGetFile(RTHTTP hHttp, const char *pszUrl, const char *pszDstFile) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); /* * Set up the request. */ pHttpInt->fAbort = false; int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pszUrl); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #if 0 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_VERBOSE, 1); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #endif const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt"; if (pHttpInt->pcszCAFile) pcszCAFile = pHttpInt->pcszCAFile; if (RTFileExists(pcszCAFile)) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, pcszCAFile); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; } rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteDataToFile); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void*)pHttpInt); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_NOPROGRESS, (long)0); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; /* * Open the output file. */ RTFILE hFile; int rc = RTFileOpen(&hFile, pszDstFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_READWRITE); if (RT_SUCCESS(rc)) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void *)(uintptr_t)hFile); if (!CURL_FAILED(rcCurl)) { /* * Perform the request. */ rcCurl = curl_easy_perform(pHttpInt->pCurl); rc = rtHttpGetCalcStatus(pHttpInt, rcCurl); } else rc = VERR_INTERNAL_ERROR; int rc2 = RTFileClose(hFile); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } return rc; }
RTR3DECL(int) RTHttpGet(RTHTTP hHttp, const char *pcszUrl, char **ppszResponse) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); pHttpInt->fAbort = false; int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pcszUrl); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #if 0 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_VERBOSE, 1); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; #endif const char *pcszCAFile = "/etc/ssl/certs/ca-certificates.crt"; if (pHttpInt->pcszCAFile) pcszCAFile = pHttpInt->pcszCAFile; if (RTFileExists(pcszCAFile)) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, pcszCAFile); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; } RTHTTPMEMCHUNK chunk = { NULL, 0 }; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void*)&chunk); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSFUNCTION, &rtHttpProgress); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void*)pHttpInt); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_NOPROGRESS, (long)0); if (CURL_FAILED(rcCurl)) return VERR_INTERNAL_ERROR; rcCurl = curl_easy_perform(pHttpInt->pCurl); int rc = VERR_INTERNAL_ERROR; if (rcCurl == CURLE_OK) { curl_easy_getinfo(pHttpInt->pCurl, CURLINFO_RESPONSE_CODE, &pHttpInt->lLastResp); switch (pHttpInt->lLastResp) { case 200: /* OK, request was fulfilled */ case 204: /* empty response */ rc = VINF_SUCCESS; break; case 400: /* bad request */ rc = VERR_HTTP_BAD_REQUEST; break; case 403: /* forbidden, authorization will not help */ rc = VERR_HTTP_ACCESS_DENIED; break; case 404: /* URL not found */ rc = VERR_HTTP_NOT_FOUND; break; } } else { switch (rcCurl) { case CURLE_URL_MALFORMAT: case CURLE_COULDNT_RESOLVE_HOST: rc = VERR_HTTP_NOT_FOUND; break; case CURLE_COULDNT_CONNECT: rc = VERR_HTTP_COULDNT_CONNECT; break; case CURLE_SSL_CONNECT_ERROR: rc = VERR_HTTP_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. */ rc = VERR_HTTP_CACERT_CANNOT_AUTHENTICATE; break; case CURLE_SSL_CACERT_BADFILE: /* CAcert file (see RTHttpSetCAFile()) has wrong format */ rc = VERR_HTTP_CACERT_WRONG_FORMAT; break; case CURLE_ABORTED_BY_CALLBACK: /* forcefully aborted */ rc = VERR_HTTP_ABORTED; break; default: break; } } *ppszResponse = chunk.pszMem; return rc; }