Commit 8f426d7d by Philip Kelley Committed by Tony Kelman

Win32: Enable WinHTTP for MinGW

parent d675982a
...@@ -27,7 +27,7 @@ matrix: ...@@ -27,7 +27,7 @@ matrix:
compiler: gcc compiler: gcc
include: include:
- compiler: i586-mingw32msvc-gcc - compiler: i586-mingw32msvc-gcc
env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON -DUSE_SSH=OFF" env: OPTIONS="-DCMAKE_TOOLCHAIN_FILE=../script/toolchain-mingw32.cmake" SKIP_TESTS=1
os: linux os: linux
- compiler: gcc - compiler: gcc
env: COVERITY=1 env: COVERITY=1
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
PROJECT(libgit2 C) PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
CMAKE_POLICY(SET CMP0015 NEW)
# Add find modules to the path # Add find modules to the path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
...@@ -58,10 +59,6 @@ IF(MSVC) ...@@ -58,10 +59,6 @@ IF(MSVC)
# are linking statically # are linking statically
OPTION( STATIC_CRT "Link the static CRT libraries" ON ) OPTION( STATIC_CRT "Link the static CRT libraries" ON )
# By default, libgit2 is built with WinHTTP. To use the built-in
# HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
OPTION( WINHTTP "Use Win32 WinHTTP routines" ON )
# If you want to embed a copy of libssh2 into libgit2, pass a # If you want to embed a copy of libssh2 into libgit2, pass a
# path to libssh2 # path to libssh2
OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF ) OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF )
...@@ -71,6 +68,12 @@ IF(MSVC) ...@@ -71,6 +68,12 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE) ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
ENDIF() ENDIF()
IF(WIN32)
# By default, libgit2 is built with WinHTTP. To use the built-in
# HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
OPTION( WINHTTP "Use Win32 WinHTTP routines" ON )
ENDIF()
# This variable will contain the libraries we need to put into # This variable will contain the libraries we need to put into
# libgit2.pc's Requires.private. That is, what we're linking to or # libgit2.pc's Requires.private. That is, what we're linking to or
# what someone who's statically linking us needs to link to. # what someone who's statically linking us needs to link to.
...@@ -147,10 +150,38 @@ IF (WIN32 AND EMBED_SSH_PATH) ...@@ -147,10 +150,38 @@ IF (WIN32 AND EMBED_SSH_PATH)
ADD_DEFINITIONS(-DGIT_SSH) ADD_DEFINITIONS(-DGIT_SSH)
ENDIF() ENDIF()
IF (WIN32 AND WINHTTP AND NOT MINGW) IF (WIN32 AND WINHTTP)
ADD_DEFINITIONS(-DGIT_WINHTTP) ADD_DEFINITIONS(-DGIT_WINHTTP)
INCLUDE_DIRECTORIES(deps/http-parser) INCLUDE_DIRECTORIES(deps/http-parser)
FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
IF (MINGW)
FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH)
IF (NOT DLLTOOL)
MESSAGE(FATAL_ERROR "Could not find dlltool command")
ENDIF ()
SET(LIBWINHTTP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps/winhttp")
ADD_CUSTOM_COMMAND(
OUTPUT ${LIBWINHTTP_PATH}/libwinhttp.a
COMMAND ${DLLTOOL} -d winhttp.def -k -D winhttp.dll -l libwinhttp.a
DEPENDS ${LIBWINHTTP_PATH}/winhttp.def
WORKING_DIRECTORY ${LIBWINHTTP_PATH}
)
SET_SOURCE_FILES_PROPERTIES(
${CMAKE_CURRENT_SOURCE_DIR}/src/transports/winhttp.c
PROPERTIES OBJECT_DEPENDS ${LIBWINHTTP_PATH}/libwinhttp.a
)
INCLUDE_DIRECTORIES(deps/winhttp)
LINK_DIRECTORIES(deps/winhttp)
ENDIF ()
LINK_LIBRARIES(winhttp rpcrt4)
ELSE () ELSE ()
IF (NOT AMIGA AND USE_OPENSSL) IF (NOT AMIGA AND USE_OPENSSL)
FIND_PACKAGE(OpenSSL) FIND_PACKAGE(OpenSSL)
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef __CUSTOM_URLMON_H
#define __CUSTOM_URLMON_H
typedef struct IInternetSecurityManager IInternetSecurityManager;
typedef struct IInternetSecurityManagerVtbl
{
HRESULT(STDMETHODCALLTYPE *QueryInterface)(IInternetSecurityManager *, REFIID, void **);
ULONG(STDMETHODCALLTYPE *AddRef)(IInternetSecurityManager *);
ULONG(STDMETHODCALLTYPE *Release)(IInternetSecurityManager *);
LPVOID SetSecuritySite;
LPVOID GetSecuritySite;
HRESULT(STDMETHODCALLTYPE *MapUrlToZone)(IInternetSecurityManager *, LPCWSTR, DWORD *, DWORD);
LPVOID GetSecurityId;
LPVOID ProcessUrlAction;
LPVOID QueryCustomPolicy;
LPVOID SetZoneMapping;
LPVOID GetZoneMappings;
} IInternetSecurityManagerVtbl;
struct IInternetSecurityManager
{
CONST_VTBL struct IInternetSecurityManagerVtbl *lpVtbl;
};
#define URLZONE_LOCAL_MACHINE 0
#define URLZONE_INTRANET 1
#define URLZONE_TRUSTED 2
#endif /* __CUSTOM_URLMON_H */
LIBRARY WINHTTP
EXPORTS
WinHttpAddRequestHeaders@16
WinHttpCheckPlatform@0
WinHttpCloseHandle@4
WinHttpConnect@16
WinHttpCrackUrl@16
WinHttpCreateUrl@16
WinHttpDetectAutoProxyConfigUrl@8
WinHttpGetDefaultProxyConfiguration@4
WinHttpGetIEProxyConfigForCurrentUser@4
WinHttpGetProxyForUrl@16
WinHttpOpen@20
WinHttpOpenRequest@28
WinHttpQueryAuthSchemes@16
WinHttpQueryDataAvailable@8
WinHttpQueryHeaders@24
WinHttpQueryOption@16
WinHttpReadData@16
WinHttpReceiveResponse@8
WinHttpSendRequest@28
WinHttpSetCredentials@24
WinHttpSetDefaultProxyConfiguration@4
WinHttpSetOption@16
WinHttpSetStatusCallback@16
WinHttpSetTimeouts@20
WinHttpTimeFromSystemTime@8
WinHttpTimeToSystemTime@8
WinHttpWriteData@16
...@@ -6,17 +6,25 @@ then ...@@ -6,17 +6,25 @@ then
exit $?; exit $?;
fi fi
mkdir _build
cd _build
# shellcheck disable=SC2086
cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
make -j2 install || exit $?
# If this platform doesn't support test execution, bail out now
if [ -n "$SKIP_TESTS" ];
then
exit $?;
fi
# Create a test repo which we can use for the online::push tests # Create a test repo which we can use for the online::push tests
mkdir "$HOME"/_temp mkdir "$HOME"/_temp
git init --bare "$HOME"/_temp/test.git git init --bare "$HOME"/_temp/test.git
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="$HOME"/_temp "$HOME"/_temp 2>/dev/null & git daemon --listen=localhost --export-all --enable=receive-pack --base-path="$HOME"/_temp "$HOME"/_temp 2>/dev/null &
export GITTEST_REMOTE_URL="git://localhost/test.git" export GITTEST_REMOTE_URL="git://localhost/test.git"
mkdir _build # Run the test suite
cd _build
# shellcheck disable=SC2086
cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
make -j2 install || exit $?
ctest -V . || exit $? ctest -V . || exit $?
# Now that we've tested the raw git protocol, let's set up ssh to we # Now that we've tested the raw git protocol, let's set up ssh to we
......
# CMake toolchain file for Win32 cross-compile
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_C_COMPILER i586-mingw32msvc-gcc)
SET(CMAKE_RC_COMPILER i586-mingw32msvc-windres)
SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
...@@ -19,17 +19,9 @@ ...@@ -19,17 +19,9 @@
#include <wincrypt.h> #include <wincrypt.h>
#pragma comment(lib, "crypt32") #pragma comment(lib, "crypt32")
#include <winhttp.h> #include <winhttp.h>
#pragma comment(lib, "winhttp")
#include <strsafe.h>
/* For IInternetSecurityManager zone check */
#include <objbase.h> #include <objbase.h>
#include <urlmon.h> #include <urlmon.h>
/* For UuidCreate */
#pragma comment(lib, "rpcrt4")
#define WIDEN2(s) L ## s #define WIDEN2(s) L ## s
#define WIDEN(s) WIDEN2(s) #define WIDEN(s) WIDEN2(s)
...@@ -43,7 +35,6 @@ ...@@ -43,7 +35,6 @@
#define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0 #define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0
#endif #endif
static const char *prefix_http = "http://";
static const char *prefix_https = "https://"; static const char *prefix_https = "https://";
static const char *upload_pack_service = "upload-pack"; static const char *upload_pack_service = "upload-pack";
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack"; static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
...@@ -59,6 +50,13 @@ static const int no_check_cert_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | ...@@ -59,6 +50,13 @@ static const int no_check_cert_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_UNKNOWN_CA; SECURITY_FLAG_IGNORE_UNKNOWN_CA;
#if defined(__MINGW32__)
static const CLSID CLSID_InternetSecurityManager = { 0x7B8A2D94, 0x0AC9, 0x11D1,
{ 0x89, 0x6C, 0x00, 0xC0, 0x4F, 0xB6, 0xBF, 0xC4 } };
static const IID IID_IInternetSecurityManager = { 0x79EAC9EE, 0xBAF9, 0x11CE,
{ 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B } };
#endif
#define OWNING_SUBTRANSPORT(s) ((winhttp_subtransport *)(s)->parent.subtransport) #define OWNING_SUBTRANSPORT(s) ((winhttp_subtransport *)(s)->parent.subtransport)
typedef enum { typedef enum {
...@@ -272,7 +270,7 @@ static int winhttp_stream_connect(winhttp_stream *s) ...@@ -272,7 +270,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
char *proxy_url = NULL; char *proxy_url = NULL;
wchar_t ct[MAX_CONTENT_TYPE_LEN]; wchar_t ct[MAX_CONTENT_TYPE_LEN];
wchar_t *types[] = { L"*/*", NULL }; LPCWSTR types[] = { L"*/*", NULL };
BOOL peerdist = FALSE; BOOL peerdist = FALSE;
int error = -1; int error = -1;
unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS; unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
...@@ -551,8 +549,7 @@ static int winhttp_close_connection(winhttp_subtransport *t) ...@@ -551,8 +549,7 @@ static int winhttp_close_connection(winhttp_subtransport *t)
} }
static int winhttp_connect( static int winhttp_connect(
winhttp_subtransport *t, winhttp_subtransport *t)
const char *url)
{ {
wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
wchar_t *wide_host; wchar_t *wide_host;
...@@ -561,8 +558,6 @@ static int winhttp_connect( ...@@ -561,8 +558,6 @@ static int winhttp_connect(
int default_timeout = TIMEOUT_INFINITE; int default_timeout = TIMEOUT_INFINITE;
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
GIT_UNUSED(url);
t->session = NULL; t->session = NULL;
t->connection = NULL; t->connection = NULL;
...@@ -860,7 +855,7 @@ replay: ...@@ -860,7 +855,7 @@ replay:
winhttp_close_connection(t); winhttp_close_connection(t);
if (winhttp_connect(t, location8) < 0) if (winhttp_connect(t) < 0)
return -1; return -1;
} }
...@@ -963,7 +958,6 @@ static int winhttp_stream_write_single( ...@@ -963,7 +958,6 @@ static int winhttp_stream_write_single(
size_t len) size_t len)
{ {
winhttp_stream *s = (winhttp_stream *)stream; winhttp_stream *s = (winhttp_stream *)stream;
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
DWORD bytes_written; DWORD bytes_written;
int error; int error;
...@@ -998,7 +992,7 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch) ...@@ -998,7 +992,7 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
{ {
UUID uuid; UUID uuid;
RPC_STATUS status = UuidCreate(&uuid); RPC_STATUS status = UuidCreate(&uuid);
HRESULT result; int result;
if (RPC_S_OK != status && if (RPC_S_OK != status &&
RPC_S_UUID_LOCAL_ONLY != status && RPC_S_UUID_LOCAL_ONLY != status &&
...@@ -1012,14 +1006,14 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch) ...@@ -1012,14 +1006,14 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
return -1; return -1;
} }
result = StringCbPrintfW( result = wsprintfW(
buffer, buffer_len_cch, buffer,
L"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", L"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x",
uuid.Data1, uuid.Data2, uuid.Data3, uuid.Data1, uuid.Data2, uuid.Data3,
uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3], uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3],
uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]); uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
if (FAILED(result)) { if (result < UUID_LENGTH_CCH) {
giterr_set(GITERR_OS, "Unable to generate name for temp file"); giterr_set(GITERR_OS, "Unable to generate name for temp file");
return -1; return -1;
} }
...@@ -1053,7 +1047,6 @@ static int winhttp_stream_write_buffered( ...@@ -1053,7 +1047,6 @@ static int winhttp_stream_write_buffered(
size_t len) size_t len)
{ {
winhttp_stream *s = (winhttp_stream *)stream; winhttp_stream *s = (winhttp_stream *)stream;
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
DWORD bytes_written; DWORD bytes_written;
if (!s->request && winhttp_stream_connect(s) < 0) if (!s->request && winhttp_stream_connect(s) < 0)
...@@ -1135,7 +1128,7 @@ static int winhttp_stream_write_chunked( ...@@ -1135,7 +1128,7 @@ static int winhttp_stream_write_chunked(
} }
else { else {
/* Append as much to the buffer as we can */ /* Append as much to the buffer as we can */
int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, (int)len); int count = (int)min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, len);
if (!s->chunk_buffer) if (!s->chunk_buffer)
s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE); s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE);
...@@ -1195,6 +1188,8 @@ static int winhttp_uploadpack_ls( ...@@ -1195,6 +1188,8 @@ static int winhttp_uploadpack_ls(
winhttp_subtransport *t, winhttp_subtransport *t,
winhttp_stream *s) winhttp_stream *s)
{ {
GIT_UNUSED(t);
s->service = upload_pack_service; s->service = upload_pack_service;
s->service_url = upload_pack_ls_service_url; s->service_url = upload_pack_ls_service_url;
s->verb = get_verb; s->verb = get_verb;
...@@ -1206,6 +1201,8 @@ static int winhttp_uploadpack( ...@@ -1206,6 +1201,8 @@ static int winhttp_uploadpack(
winhttp_subtransport *t, winhttp_subtransport *t,
winhttp_stream *s) winhttp_stream *s)
{ {
GIT_UNUSED(t);
s->service = upload_pack_service; s->service = upload_pack_service;
s->service_url = upload_pack_service_url; s->service_url = upload_pack_service_url;
s->verb = post_verb; s->verb = post_verb;
...@@ -1217,6 +1214,8 @@ static int winhttp_receivepack_ls( ...@@ -1217,6 +1214,8 @@ static int winhttp_receivepack_ls(
winhttp_subtransport *t, winhttp_subtransport *t,
winhttp_stream *s) winhttp_stream *s)
{ {
GIT_UNUSED(t);
s->service = receive_pack_service; s->service = receive_pack_service;
s->service_url = receive_pack_ls_service_url; s->service_url = receive_pack_ls_service_url;
s->verb = get_verb; s->verb = get_verb;
...@@ -1228,6 +1227,8 @@ static int winhttp_receivepack( ...@@ -1228,6 +1227,8 @@ static int winhttp_receivepack(
winhttp_subtransport *t, winhttp_subtransport *t,
winhttp_stream *s) winhttp_stream *s)
{ {
GIT_UNUSED(t);
/* WinHTTP only supports Transfer-Encoding: chunked /* WinHTTP only supports Transfer-Encoding: chunked
* on Windows Vista (NT 6.0) and higher. */ * on Windows Vista (NT 6.0) and higher. */
s->chunked = git_has_win32_version(6, 0, 0); s->chunked = git_has_win32_version(6, 0, 0);
...@@ -1256,7 +1257,7 @@ static int winhttp_action( ...@@ -1256,7 +1257,7 @@ static int winhttp_action(
if (!t->connection) if (!t->connection)
if ((ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0 || if ((ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0 ||
(ret = winhttp_connect(t, url)) < 0) (ret = winhttp_connect(t)) < 0)
return ret; return ret;
if (winhttp_stream_alloc(t, &s) < 0) if (winhttp_stream_alloc(t, &s) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment