Win32: UTF-8 <-> WCHAR conversion overhaul · nodegit/libgit2@c2c8161 · GitHub
Skip to content

Commit c2c8161

Browse files
committed
Win32: UTF-8 <-> WCHAR conversion overhaul
1 parent bfc50f8 commit c2c8161

18 files changed

Lines changed: 659 additions & 431 deletions

File tree

‎src/path.c‎

Lines changed: 26 additions & 25 deletions

‎src/repository.c‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#include "merge.h"
2828
#include "diff_driver.h"
2929

30+
#ifdef GIT_WIN32
31+
# include "win32/w32_util.h"
32+
#endif
33+
3034
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
3135

3236
#define GIT_BRANCH_MASTER "master"
@@ -1149,7 +1153,7 @@ static int repo_write_template(
11491153

11501154
#ifdef GIT_WIN32
11511155
if (!error && hidden) {
1152-
if (p_hide_directory__w32(path.ptr) < 0)
1156+
if (git_win32__sethidden(path.ptr) < 0)
11531157
error = -1;
11541158
}
11551159
#else
@@ -1234,8 +1238,8 @@ static int repo_init_structure(
12341238
/* Hide the ".git" directory */
12351239
#ifdef GIT_WIN32
12361240
if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) {
1237-
if (p_hide_directory__w32(repo_dir) < 0) {
1238-
giterr_set(GITERR_REPOSITORY,
1241+
if (git_win32__sethidden(repo_dir) < 0) {
1242+
giterr_set(GITERR_OS,
12391243
"Failed to mark Git repository folder as hidden");
12401244
return -1;
12411245
}

‎src/transports/winhttp.c‎

Lines changed: 50 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static int apply_basic_credential(HINTERNET request, git_cred *cred)
9191
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
9292
git_buf buf = GIT_BUF_INIT, raw = GIT_BUF_INIT;
9393
wchar_t *wide = NULL;
94-
int error = -1, wide_len = 0;
94+
int error = -1, wide_len;
9595

9696
git_buf_printf(&raw, "%s:%s", c->username, c->password);
9797

@@ -100,21 +100,7 @@ static int apply_basic_credential(HINTERNET request, git_cred *cred)
100100
git_buf_put_base64(&buf, git_buf_cstr(&raw), raw.size) < 0)
101101
goto on_error;
102102

103-
wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
104-
git_buf_cstr(&buf), -1, NULL, 0);
105-
106-
if (!wide_len) {
107-
giterr_set(GITERR_OS, "Failed to measure string for wide conversion");
108-
goto on_error;
109-
}
110-
111-
wide = git__malloc(wide_len * sizeof(wchar_t));
112-
113-
if (!wide)
114-
goto on_error;
115-
116-
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
117-
git_buf_cstr(&buf), -1, wide, wide_len)) {
103+
if ((wide_len = git__utf8_to_16_alloc(&wide, git_buf_cstr(&buf))) < 0) {
118104
giterr_set(GITERR_OS, "Failed to convert string to wide form");
119105
goto on_error;
120106
}
@@ -171,23 +157,11 @@ static int fallback_cred_acquire_cb(
171157
/* If the target URI supports integrated Windows authentication
172158
* as an authentication mechanism */
173159
if (GIT_CREDTYPE_DEFAULT & allowed_types) {
174-
LPWSTR wide_url;
175-
DWORD wide_len;
160+
wchar_t *wide_url;
176161

177162
/* Convert URL to wide characters */
178-
wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, url, -1, NULL, 0);
179-
180-
if (!wide_len) {
181-
giterr_set(GITERR_OS, "Failed to measure string for wide conversion");
182-
return -1;
183-
}
184-
185-
wide_url = git__malloc(wide_len * sizeof(WCHAR));
186-
GITERR_CHECK_ALLOC(wide_url);
187-
188-
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, url, -1, wide_url, wide_len)) {
163+
if (git__utf8_to_16_alloc(&wide_url, url) < 0) {
189164
giterr_set(GITERR_OS, "Failed to convert string to wide form");
190-
git__free(wide_url);
191165
return -1;
192166
}
193167

@@ -232,7 +206,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
232206
wchar_t ct[MAX_CONTENT_TYPE_LEN];
233207
wchar_t *types[] = { L"*/*", NULL };
234208
BOOL peerdist = FALSE;
235-
int error = -1, wide_len;
209+
int error = -1;
236210
unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
237211

238212
/* Prepare URL */
@@ -242,21 +216,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
242216
return -1;
243217

244218
/* Convert URL to wide characters */
245-
wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
246-
git_buf_cstr(&buf), -1, NULL, 0);
247-
248-
if (!wide_len) {
249-
giterr_set(GITERR_OS, "Failed to measure string for wide conversion");
250-
goto on_error;
251-
}
252-
253-
s->request_uri = git__malloc(wide_len * sizeof(wchar_t));
254-
255-
if (!s->request_uri)
256-
goto on_error;
257-
258-
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
259-
git_buf_cstr(&buf), -1, s->request_uri, wide_len)) {
219+
if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
260220
giterr_set(GITERR_OS, "Failed to convert string to wide form");
261221
goto on_error;
262222
}
@@ -285,30 +245,17 @@ static int winhttp_stream_connect(winhttp_stream *s)
285245
wchar_t *proxy_wide;
286246

287247
/* Convert URL to wide characters */
288-
wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
289-
proxy_url, -1, NULL, 0);
290-
291-
if (!wide_len) {
292-
giterr_set(GITERR_OS, "Failed to measure string for wide conversion");
293-
goto on_error;
294-
}
295-
296-
proxy_wide = git__malloc(wide_len * sizeof(wchar_t));
297-
298-
if (!proxy_wide)
299-
goto on_error;
248+
int proxy_wide_len = git__utf8_to_16_alloc(&proxy_wide, proxy_url);
300249

301-
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
302-
proxy_url, -1, proxy_wide, wide_len)) {
250+
if (proxy_wide_len < 0) {
303251
giterr_set(GITERR_OS, "Failed to convert string to wide form");
304-
git__free(proxy_wide);
305252
goto on_error;
306253
}
307254

308255
/* Strip any trailing forward slash on the proxy URL;
309256
* WinHTTP doesn't like it if one is present */
310-
if (wide_len > 1 && L'/' == proxy_wide[wide_len - 2])
311-
proxy_wide[wide_len - 2] = L'\0';
257+
if (proxy_wide_len > 1 && L'/' == proxy_wide[proxy_wide_len - 2])
258+
proxy_wide[proxy_wide_len - 2] = L'\0';
312259

313260
proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
314261
proxy_info.lpszProxy = proxy_wide;
@@ -359,7 +306,10 @@ static int winhttp_stream_connect(winhttp_stream *s)
359306
s->service) < 0)
360307
goto on_error;
361308

362-
git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf));
309+
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
310+
giterr_set(GITERR_OS, "Failed to convert content-type to wide characters");
311+
goto on_error;
312+
}
363313

364314
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
365315
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
@@ -373,7 +323,10 @@ static int winhttp_stream_connect(winhttp_stream *s)
373323
s->service) < 0)
374324
goto on_error;
375325

376-
git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf));
326+
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
327+
giterr_set(GITERR_OS, "Failed to convert accept header to wide characters");
328+
goto on_error;
329+
}
377330

378331
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
379332
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
@@ -506,16 +459,20 @@ static int winhttp_connect(
506459
const char *url)
507460
{
508461
wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
509-
git_win32_path host;
462+
wchar_t *wide_host;
510463
int32_t port;
511464
const char *default_port = "80";
465+
int error = -1;
512466

513467
/* Prepare port */
514468
if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
515469
return -1;
516470

517471
/* Prepare host */
518-
git_win32_path_from_c(host, t->connection_data.host);
472+
if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) {
473+
giterr_set(GITERR_OS, "Unable to convert host to wide characters");
474+
return -1;
475+
}
519476

520477
/* Establish session */
521478
t->session = WinHttpOpen(
@@ -527,22 +484,27 @@ static int winhttp_connect(
527484

528485
if (!t->session) {
529486
giterr_set(GITERR_OS, "Failed to init WinHTTP");
530-
return -1;
487+
goto on_error;
531488
}
532489

533490
/* Establish connection */
534491
t->connection = WinHttpConnect(
535492
t->session,
536-
host,
493+
wide_host,
537494
(INTERNET_PORT) port,
538495
0);
539496

540497
if (!t->connection) {
541498
giterr_set(GITERR_OS, "Failed to connect to host");
542-
return -1;
499+
goto on_error;
543500
}
544501

545-
return 0;
502+
error = 0;
503+
504+
on_error:
505+
git__free(wide_host);
506+
507+
return error;
546508
}
547509

548510
static int winhttp_stream_read(
@@ -693,7 +655,6 @@ static int winhttp_stream_read(
693655
}
694656

695657
location = git__malloc(location_length);
696-
location8 = git__malloc(location_length);
697658
GITERR_CHECK_ALLOC(location);
698659

699660
if (!WinHttpQueryHeaders(s->request,
@@ -706,7 +667,14 @@ static int winhttp_stream_read(
706667
git__free(location);
707668
return -1;
708669
}
709-
git__utf16_to_8(location8, location_length, location);
670+
671+
/* Convert the Location header to UTF-8 */
672+
if (git__utf16_to_8_alloc(&location8, location) < 0) {
673+
giterr_set(GITERR_OS, "Failed to convert Location header to UTF-8");
674+
git__free(location);
675+
return -1;
676+
}
677+
710678
git__free(location);
711679

712680
/* Replay the request */
@@ -716,8 +684,11 @@ static int winhttp_stream_read(
716684

717685
if (!git__prefixcmp_icase(location8, prefix_https)) {
718686
/* Upgrade to secure connection; disconnect and start over */
719-
if (gitno_connection_data_from_url(&t->connection_data, location8, s->service_url) < 0)
687+
if (gitno_connection_data_from_url(&t->connection_data, location8, s->service_url) < 0) {
688+
git__free(location8);
720689
return -1;
690+
}
691+
721692
winhttp_connect(t, location8);
722693
}
723694

@@ -778,7 +749,11 @@ static int winhttp_stream_read(
778749
else
779750
snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service);
780751

781-
git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8);
752+
if (git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8) < 0) {
753+
giterr_set(GITERR_OS, "Failed to convert expected content-type to wide characters");
754+
return -1;
755+
}
756+
782757
content_type_length = sizeof(content_type);
783758

784759
if (!WinHttpQueryHeaders(s->request,

‎src/unix/posix.h‎

Lines changed: 0 additions & 1 deletion

0 commit comments

Comments
 (0)