rugged 0.17.0.b7 → 0.18.0.b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
- data/README.md +88 -32
- data/ext/rugged/extconf.rb +4 -2
- data/ext/rugged/rugged.c +72 -10
- data/ext/rugged/rugged.h +14 -10
- data/ext/rugged/rugged_blob.c +8 -10
- data/ext/rugged/rugged_branch.c +11 -14
- data/ext/rugged/rugged_commit.c +31 -24
- data/ext/rugged/rugged_config.c +2 -2
- data/ext/rugged/rugged_index.c +133 -198
- data/ext/rugged/rugged_note.c +372 -0
- data/ext/rugged/rugged_object.c +50 -22
- data/ext/rugged/rugged_reference.c +122 -130
- data/ext/rugged/rugged_remote.c +72 -29
- data/ext/rugged/rugged_repo.c +402 -20
- data/ext/rugged/rugged_revwalk.c +7 -3
- data/ext/rugged/rugged_settings.c +110 -0
- data/ext/rugged/rugged_signature.c +23 -7
- data/ext/rugged/rugged_tag.c +32 -16
- data/ext/rugged/rugged_tree.c +44 -15
- data/lib/rugged.rb +1 -0
- data/lib/rugged/index.rb +8 -0
- data/lib/rugged/remote.rb +13 -0
- data/lib/rugged/repository.rb +3 -3
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +13 -15
- data/test/branch_test.rb +32 -67
- data/test/commit_test.rb +50 -12
- data/test/config_test.rb +12 -11
- data/test/coverage/HEAD.json +1 -1
- data/test/coverage/cover.rb +40 -21
- data/test/errors_test.rb +34 -0
- data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
- data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
- data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
- data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
- data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
- data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
- data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
- data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
- data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
- data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
- data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
- data/test/index_test.rb +65 -69
- data/test/lib_test.rb +76 -11
- data/test/note_test.rb +158 -0
- data/test/object_test.rb +8 -11
- data/test/reference_test.rb +77 -85
- data/test/remote_test.rb +86 -8
- data/test/repo_pack_test.rb +9 -7
- data/test/repo_reset_test.rb +80 -0
- data/test/repo_test.rb +176 -53
- data/test/tag_test.rb +44 -7
- data/test/test_helper.rb +63 -35
- data/test/tree_test.rb +34 -13
- data/test/walker_test.rb +14 -14
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
- data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
- data/vendor/libgit2/deps/regex/regcomp.c +7 -6
- data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
- data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
- data/vendor/libgit2/deps/regex/regexec.c +5 -5
- data/vendor/libgit2/include/git2.h +5 -1
- data/vendor/libgit2/include/git2/attr.h +4 -2
- data/vendor/libgit2/include/git2/blob.h +39 -12
- data/vendor/libgit2/include/git2/branch.h +123 -35
- data/vendor/libgit2/include/git2/checkout.h +206 -48
- data/vendor/libgit2/include/git2/clone.h +72 -27
- data/vendor/libgit2/include/git2/commit.h +20 -17
- data/vendor/libgit2/include/git2/common.h +67 -1
- data/vendor/libgit2/include/git2/config.h +81 -60
- data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
- data/vendor/libgit2/include/git2/diff.h +459 -150
- data/vendor/libgit2/include/git2/errors.h +9 -1
- data/vendor/libgit2/include/git2/graph.h +41 -0
- data/vendor/libgit2/include/git2/ignore.h +7 -6
- data/vendor/libgit2/include/git2/index.h +323 -97
- data/vendor/libgit2/include/git2/indexer.h +27 -59
- data/vendor/libgit2/include/git2/inttypes.h +4 -0
- data/vendor/libgit2/include/git2/merge.h +13 -3
- data/vendor/libgit2/include/git2/message.h +14 -8
- data/vendor/libgit2/include/git2/net.h +9 -7
- data/vendor/libgit2/include/git2/notes.h +88 -29
- data/vendor/libgit2/include/git2/object.h +16 -6
- data/vendor/libgit2/include/git2/odb.h +80 -17
- data/vendor/libgit2/include/git2/odb_backend.h +47 -11
- data/vendor/libgit2/include/git2/oid.h +26 -17
- data/vendor/libgit2/include/git2/pack.h +62 -8
- data/vendor/libgit2/include/git2/push.h +131 -0
- data/vendor/libgit2/include/git2/refdb.h +103 -0
- data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
- data/vendor/libgit2/include/git2/reflog.h +30 -21
- data/vendor/libgit2/include/git2/refs.h +215 -193
- data/vendor/libgit2/include/git2/refspec.h +22 -2
- data/vendor/libgit2/include/git2/remote.h +158 -37
- data/vendor/libgit2/include/git2/repository.h +150 -31
- data/vendor/libgit2/include/git2/reset.h +43 -9
- data/vendor/libgit2/include/git2/revparse.h +48 -4
- data/vendor/libgit2/include/git2/revwalk.h +25 -10
- data/vendor/libgit2/include/git2/signature.h +20 -12
- data/vendor/libgit2/include/git2/stash.h +121 -0
- data/vendor/libgit2/include/git2/status.h +122 -53
- data/vendor/libgit2/include/git2/strarray.h +17 -11
- data/vendor/libgit2/include/git2/submodule.h +42 -7
- data/vendor/libgit2/include/git2/tag.h +72 -59
- data/vendor/libgit2/include/git2/threads.h +4 -2
- data/vendor/libgit2/include/git2/trace.h +68 -0
- data/vendor/libgit2/include/git2/transport.h +328 -0
- data/vendor/libgit2/include/git2/tree.h +149 -120
- data/vendor/libgit2/include/git2/types.h +13 -12
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/src/amiga/map.c +2 -2
- data/vendor/libgit2/src/attr.c +58 -48
- data/vendor/libgit2/src/attr.h +4 -18
- data/vendor/libgit2/src/attr_file.c +30 -6
- data/vendor/libgit2/src/attr_file.h +6 -8
- data/vendor/libgit2/src/attrcache.h +24 -0
- data/vendor/libgit2/src/blob.c +30 -7
- data/vendor/libgit2/src/blob.h +1 -1
- data/vendor/libgit2/src/branch.c +361 -68
- data/vendor/libgit2/src/branch.h +17 -0
- data/vendor/libgit2/src/bswap.h +1 -1
- data/vendor/libgit2/src/buf_text.c +291 -0
- data/vendor/libgit2/src/buf_text.h +122 -0
- data/vendor/libgit2/src/buffer.c +27 -101
- data/vendor/libgit2/src/buffer.h +54 -39
- data/vendor/libgit2/src/cache.c +15 -6
- data/vendor/libgit2/src/cache.h +1 -1
- data/vendor/libgit2/src/cc-compat.h +3 -1
- data/vendor/libgit2/src/checkout.c +1165 -222
- data/vendor/libgit2/src/checkout.h +24 -0
- data/vendor/libgit2/src/clone.c +171 -86
- data/vendor/libgit2/src/commit.c +44 -45
- data/vendor/libgit2/src/commit.h +3 -3
- data/vendor/libgit2/src/commit_list.c +194 -0
- data/vendor/libgit2/src/commit_list.h +49 -0
- data/vendor/libgit2/src/common.h +44 -10
- data/vendor/libgit2/src/compress.c +1 -1
- data/vendor/libgit2/src/compress.h +1 -1
- data/vendor/libgit2/src/config.c +211 -124
- data/vendor/libgit2/src/config.h +23 -4
- data/vendor/libgit2/src/config_cache.c +2 -2
- data/vendor/libgit2/src/config_file.c +129 -53
- data/vendor/libgit2/src/config_file.h +10 -8
- data/vendor/libgit2/src/crlf.c +66 -67
- data/vendor/libgit2/src/date.c +12 -12
- data/vendor/libgit2/src/delta-apply.c +14 -1
- data/vendor/libgit2/src/delta-apply.h +18 -1
- data/vendor/libgit2/src/delta.c +40 -107
- data/vendor/libgit2/src/delta.h +19 -17
- data/vendor/libgit2/src/diff.c +347 -496
- data/vendor/libgit2/src/diff.h +27 -1
- data/vendor/libgit2/src/diff_output.c +564 -249
- data/vendor/libgit2/src/diff_output.h +15 -8
- data/vendor/libgit2/src/diff_tform.c +687 -0
- data/vendor/libgit2/src/errors.c +27 -36
- data/vendor/libgit2/src/fetch.c +13 -351
- data/vendor/libgit2/src/fetch.h +13 -3
- data/vendor/libgit2/src/fetchhead.c +295 -0
- data/vendor/libgit2/src/fetchhead.h +34 -0
- data/vendor/libgit2/src/filebuf.c +42 -15
- data/vendor/libgit2/src/filebuf.h +4 -2
- data/vendor/libgit2/src/fileops.c +466 -113
- data/vendor/libgit2/src/fileops.h +154 -28
- data/vendor/libgit2/src/filter.c +3 -75
- data/vendor/libgit2/src/filter.h +1 -29
- data/vendor/libgit2/src/fnmatch.c +1 -1
- data/vendor/libgit2/src/fnmatch.h +1 -1
- data/vendor/libgit2/src/global.c +54 -10
- data/vendor/libgit2/src/global.h +10 -1
- data/vendor/libgit2/src/graph.c +178 -0
- data/vendor/libgit2/src/hash.c +25 -52
- data/vendor/libgit2/src/hash.h +21 -9
- data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
- data/vendor/libgit2/src/hash/hash_generic.h +24 -0
- data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
- data/vendor/libgit2/src/hash/hash_win32.c +291 -0
- data/vendor/libgit2/src/hash/hash_win32.h +140 -0
- data/vendor/libgit2/src/hashsig.c +368 -0
- data/vendor/libgit2/src/hashsig.h +72 -0
- data/vendor/libgit2/src/ignore.c +22 -15
- data/vendor/libgit2/src/ignore.h +6 -1
- data/vendor/libgit2/src/index.c +770 -171
- data/vendor/libgit2/src/index.h +13 -5
- data/vendor/libgit2/src/indexer.c +286 -431
- data/vendor/libgit2/src/iterator.c +854 -466
- data/vendor/libgit2/src/iterator.h +134 -109
- data/vendor/libgit2/src/map.h +1 -1
- data/vendor/libgit2/src/merge.c +296 -0
- data/vendor/libgit2/src/merge.h +22 -0
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/message.h +1 -1
- data/vendor/libgit2/src/mwindow.c +35 -30
- data/vendor/libgit2/src/mwindow.h +2 -2
- data/vendor/libgit2/src/netops.c +162 -98
- data/vendor/libgit2/src/netops.h +50 -15
- data/vendor/libgit2/src/notes.c +109 -58
- data/vendor/libgit2/src/notes.h +2 -1
- data/vendor/libgit2/src/object.c +46 -57
- data/vendor/libgit2/src/object.h +1 -8
- data/vendor/libgit2/src/odb.c +151 -40
- data/vendor/libgit2/src/odb.h +5 -1
- data/vendor/libgit2/src/odb_loose.c +4 -5
- data/vendor/libgit2/src/odb_pack.c +122 -80
- data/vendor/libgit2/src/offmap.h +65 -0
- data/vendor/libgit2/src/oid.c +12 -4
- data/vendor/libgit2/src/oidmap.h +1 -1
- data/vendor/libgit2/src/pack-objects.c +88 -61
- data/vendor/libgit2/src/pack-objects.h +8 -8
- data/vendor/libgit2/src/pack.c +293 -28
- data/vendor/libgit2/src/pack.h +49 -4
- data/vendor/libgit2/src/path.c +103 -14
- data/vendor/libgit2/src/path.h +23 -7
- data/vendor/libgit2/src/pathspec.c +168 -0
- data/vendor/libgit2/src/pathspec.h +40 -0
- data/vendor/libgit2/src/pool.c +29 -4
- data/vendor/libgit2/src/pool.h +8 -1
- data/vendor/libgit2/src/posix.c +26 -27
- data/vendor/libgit2/src/posix.h +2 -3
- data/vendor/libgit2/src/pqueue.c +23 -1
- data/vendor/libgit2/src/pqueue.h +23 -1
- data/vendor/libgit2/src/push.c +653 -0
- data/vendor/libgit2/src/push.h +51 -0
- data/vendor/libgit2/src/refdb.c +185 -0
- data/vendor/libgit2/src/refdb.h +46 -0
- data/vendor/libgit2/src/refdb_fs.c +1024 -0
- data/vendor/libgit2/src/refdb_fs.h +15 -0
- data/vendor/libgit2/src/reflog.c +77 -45
- data/vendor/libgit2/src/reflog.h +1 -3
- data/vendor/libgit2/src/refs.c +366 -1326
- data/vendor/libgit2/src/refs.h +22 -13
- data/vendor/libgit2/src/refspec.c +46 -7
- data/vendor/libgit2/src/refspec.h +11 -1
- data/vendor/libgit2/src/remote.c +758 -120
- data/vendor/libgit2/src/remote.h +10 -5
- data/vendor/libgit2/src/repo_template.h +6 -6
- data/vendor/libgit2/src/repository.c +315 -96
- data/vendor/libgit2/src/repository.h +5 -3
- data/vendor/libgit2/src/reset.c +99 -81
- data/vendor/libgit2/src/revparse.c +157 -84
- data/vendor/libgit2/src/revwalk.c +68 -470
- data/vendor/libgit2/src/revwalk.h +44 -0
- data/vendor/libgit2/src/sha1_lookup.c +1 -1
- data/vendor/libgit2/src/sha1_lookup.h +1 -1
- data/vendor/libgit2/src/signature.c +68 -200
- data/vendor/libgit2/src/signature.h +1 -1
- data/vendor/libgit2/src/stash.c +663 -0
- data/vendor/libgit2/src/status.c +101 -79
- data/vendor/libgit2/src/strmap.h +1 -1
- data/vendor/libgit2/src/submodule.c +67 -51
- data/vendor/libgit2/src/submodule.h +1 -1
- data/vendor/libgit2/src/tag.c +35 -29
- data/vendor/libgit2/src/tag.h +1 -1
- data/vendor/libgit2/src/thread-utils.c +1 -1
- data/vendor/libgit2/src/thread-utils.h +2 -2
- data/vendor/libgit2/src/trace.c +39 -0
- data/vendor/libgit2/src/trace.h +56 -0
- data/vendor/libgit2/src/transport.c +81 -34
- data/vendor/libgit2/src/transports/cred.c +60 -0
- data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
- data/vendor/libgit2/src/transports/git.c +234 -127
- data/vendor/libgit2/src/transports/http.c +761 -433
- data/vendor/libgit2/src/transports/local.c +460 -64
- data/vendor/libgit2/src/transports/smart.c +345 -0
- data/vendor/libgit2/src/transports/smart.h +179 -0
- data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
- data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
- data/vendor/libgit2/src/transports/winhttp.c +1136 -0
- data/vendor/libgit2/src/tree-cache.c +2 -2
- data/vendor/libgit2/src/tree-cache.h +1 -1
- data/vendor/libgit2/src/tree.c +239 -166
- data/vendor/libgit2/src/tree.h +11 -2
- data/vendor/libgit2/src/tsort.c +39 -23
- data/vendor/libgit2/src/unix/map.c +1 -1
- data/vendor/libgit2/src/unix/posix.h +12 -2
- data/vendor/libgit2/src/unix/realpath.c +30 -0
- data/vendor/libgit2/src/util.c +250 -13
- data/vendor/libgit2/src/util.h +71 -14
- data/vendor/libgit2/src/vector.c +123 -60
- data/vendor/libgit2/src/vector.h +24 -22
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/dir.h +1 -1
- data/vendor/libgit2/src/win32/error.c +77 -0
- data/vendor/libgit2/src/win32/error.h +13 -0
- data/vendor/libgit2/src/win32/findfile.c +143 -54
- data/vendor/libgit2/src/win32/findfile.h +10 -6
- data/vendor/libgit2/src/win32/map.c +1 -1
- data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
- data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
- data/vendor/libgit2/src/win32/posix.h +10 -1
- data/vendor/libgit2/src/win32/posix_w32.c +132 -63
- data/vendor/libgit2/src/win32/precompiled.c +1 -1
- data/vendor/libgit2/src/win32/pthread.c +1 -1
- data/vendor/libgit2/src/win32/pthread.h +1 -1
- data/vendor/libgit2/src/win32/utf-conv.c +5 -5
- data/vendor/libgit2/src/win32/utf-conv.h +3 -3
- data/vendor/libgit2/src/win32/version.h +20 -0
- metadata +308 -252
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb~ +0 -218
- data/vendor/libgit2/src/pkt.h +0 -91
- data/vendor/libgit2/src/ppc/sha1.c +0 -70
- data/vendor/libgit2/src/ppc/sha1.h +0 -26
- data/vendor/libgit2/src/protocol.c +0 -110
- data/vendor/libgit2/src/protocol.h +0 -21
- data/vendor/libgit2/src/sha1.h +0 -33
- data/vendor/libgit2/src/transport.h +0 -148
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (C)
|
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
|
3
3
|
*
|
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
|
6
6
|
*/
|
|
7
|
-
#
|
|
7
|
+
#ifndef GIT_WINHTTP
|
|
8
|
+
|
|
8
9
|
#include "git2.h"
|
|
9
10
|
#include "http_parser.h"
|
|
10
|
-
|
|
11
|
-
#include "transport.h"
|
|
12
|
-
#include "common.h"
|
|
13
|
-
#include "netops.h"
|
|
14
11
|
#include "buffer.h"
|
|
15
|
-
#include "
|
|
16
|
-
#include "
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
#include "netops.h"
|
|
13
|
+
#include "smart.h"
|
|
14
|
+
|
|
15
|
+
static const char *prefix_http = "http://";
|
|
16
|
+
static const char *prefix_https = "https://";
|
|
17
|
+
static const char *upload_pack_service = "upload-pack";
|
|
18
|
+
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
|
|
19
|
+
static const char *upload_pack_service_url = "/git-upload-pack";
|
|
20
|
+
static const char *receive_pack_service = "receive-pack";
|
|
21
|
+
static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive-pack";
|
|
22
|
+
static const char *receive_pack_service_url = "/git-receive-pack";
|
|
23
|
+
static const char *get_verb = "GET";
|
|
24
|
+
static const char *post_verb = "POST";
|
|
25
|
+
static const char *basic_authtype = "Basic";
|
|
26
|
+
|
|
27
|
+
#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
|
|
28
|
+
|
|
29
|
+
#define PARSE_ERROR_GENERIC -1
|
|
30
|
+
#define PARSE_ERROR_REPLAY -2
|
|
31
|
+
|
|
32
|
+
#define CHUNK_SIZE 4096
|
|
29
33
|
|
|
30
34
|
enum last_cb {
|
|
31
35
|
NONE,
|
|
@@ -33,53 +37,132 @@ enum last_cb {
|
|
|
33
37
|
VALUE
|
|
34
38
|
};
|
|
35
39
|
|
|
40
|
+
typedef enum {
|
|
41
|
+
GIT_HTTP_AUTH_BASIC = 1,
|
|
42
|
+
} http_authmechanism_t;
|
|
43
|
+
|
|
36
44
|
typedef struct {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
git_smart_subtransport_stream parent;
|
|
46
|
+
const char *service;
|
|
47
|
+
const char *service_url;
|
|
48
|
+
char *redirect_url;
|
|
49
|
+
const char *verb;
|
|
50
|
+
char *chunk_buffer;
|
|
51
|
+
unsigned chunk_buffer_len;
|
|
52
|
+
unsigned sent_request : 1,
|
|
53
|
+
received_response : 1,
|
|
54
|
+
chunked : 1,
|
|
55
|
+
redirect_count : 3;
|
|
56
|
+
} http_stream;
|
|
57
|
+
|
|
58
|
+
typedef struct {
|
|
59
|
+
git_smart_subtransport parent;
|
|
60
|
+
transport_smart *owner;
|
|
61
|
+
gitno_socket socket;
|
|
62
|
+
const char *path;
|
|
49
63
|
char *host;
|
|
50
64
|
char *port;
|
|
51
|
-
char *
|
|
52
|
-
char
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
char *user_from_url;
|
|
66
|
+
char *pass_from_url;
|
|
67
|
+
git_cred *cred;
|
|
68
|
+
git_cred *url_cred;
|
|
69
|
+
http_authmechanism_t auth_mechanism;
|
|
70
|
+
unsigned connected : 1,
|
|
71
|
+
use_ssl : 1;
|
|
72
|
+
|
|
73
|
+
/* Parser structures */
|
|
74
|
+
http_parser parser;
|
|
75
|
+
http_parser_settings settings;
|
|
76
|
+
gitno_buffer parse_buffer;
|
|
77
|
+
git_buf parse_header_name;
|
|
78
|
+
git_buf parse_header_value;
|
|
79
|
+
char parse_buffer_data[2048];
|
|
80
|
+
char *content_type;
|
|
81
|
+
char *location;
|
|
82
|
+
git_vector www_authenticate;
|
|
83
|
+
enum last_cb last_cb;
|
|
84
|
+
int parse_error;
|
|
85
|
+
unsigned parse_finished : 1;
|
|
86
|
+
} http_subtransport;
|
|
87
|
+
|
|
88
|
+
typedef struct {
|
|
89
|
+
http_stream *s;
|
|
90
|
+
http_subtransport *t;
|
|
91
|
+
|
|
92
|
+
/* Target buffer details from read() */
|
|
93
|
+
char *buffer;
|
|
94
|
+
size_t buf_size;
|
|
95
|
+
size_t *bytes_read;
|
|
96
|
+
} parser_context;
|
|
97
|
+
|
|
98
|
+
static int apply_basic_credential(git_buf *buf, git_cred *cred)
|
|
65
99
|
{
|
|
66
|
-
|
|
67
|
-
|
|
100
|
+
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
|
|
101
|
+
git_buf raw = GIT_BUF_INIT;
|
|
102
|
+
int error = -1;
|
|
103
|
+
|
|
104
|
+
git_buf_printf(&raw, "%s:%s", c->username, c->password);
|
|
105
|
+
|
|
106
|
+
if (git_buf_oom(&raw) ||
|
|
107
|
+
git_buf_puts(buf, "Authorization: Basic ") < 0 ||
|
|
108
|
+
git_buf_put_base64(buf, git_buf_cstr(&raw), raw.size) < 0 ||
|
|
109
|
+
git_buf_puts(buf, "\r\n") < 0)
|
|
110
|
+
goto on_error;
|
|
111
|
+
|
|
112
|
+
error = 0;
|
|
113
|
+
|
|
114
|
+
on_error:
|
|
115
|
+
if (raw.size)
|
|
116
|
+
memset(raw.ptr, 0x0, raw.size);
|
|
117
|
+
|
|
118
|
+
git_buf_free(&raw);
|
|
119
|
+
return error;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
static int gen_request(
|
|
123
|
+
git_buf *buf,
|
|
124
|
+
http_stream *s,
|
|
125
|
+
size_t content_length)
|
|
126
|
+
{
|
|
127
|
+
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
128
|
+
|
|
129
|
+
if (!t->path)
|
|
130
|
+
t->path = "/";
|
|
131
|
+
|
|
132
|
+
/* If we were redirected, make sure to respect that here */
|
|
133
|
+
if (s->redirect_url)
|
|
134
|
+
git_buf_printf(buf, "%s %s HTTP/1.1\r\n", s->verb, s->redirect_url);
|
|
135
|
+
else
|
|
136
|
+
git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, t->path, s->service_url);
|
|
68
137
|
|
|
69
|
-
if (ls) {
|
|
70
|
-
git_buf_printf(buf, "%s %s/info/refs?service=git-%s HTTP/1.1\r\n", op, path, service);
|
|
71
|
-
} else {
|
|
72
|
-
git_buf_printf(buf, "%s %s/git-%s HTTP/1.1\r\n", op, path, service);
|
|
73
|
-
}
|
|
74
138
|
git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n");
|
|
75
|
-
git_buf_printf(buf, "Host: %s\r\n", host);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
git_buf_printf(buf, "
|
|
79
|
-
git_buf_printf(buf, "Content-
|
|
80
|
-
|
|
139
|
+
git_buf_printf(buf, "Host: %s\r\n", t->host);
|
|
140
|
+
|
|
141
|
+
if (s->chunked || content_length > 0) {
|
|
142
|
+
git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service);
|
|
143
|
+
git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", s->service);
|
|
144
|
+
|
|
145
|
+
if (s->chunked)
|
|
146
|
+
git_buf_puts(buf, "Transfer-Encoding: chunked\r\n");
|
|
147
|
+
else
|
|
148
|
+
git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length);
|
|
149
|
+
} else
|
|
81
150
|
git_buf_puts(buf, "Accept: */*\r\n");
|
|
151
|
+
|
|
152
|
+
/* Apply credentials to the request */
|
|
153
|
+
if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
|
|
154
|
+
t->auth_mechanism == GIT_HTTP_AUTH_BASIC &&
|
|
155
|
+
apply_basic_credential(buf, t->cred) < 0)
|
|
156
|
+
return -1;
|
|
157
|
+
|
|
158
|
+
/* Use url-parsed basic auth if username and password are both provided */
|
|
159
|
+
if (!t->cred && t->user_from_url && t->pass_from_url) {
|
|
160
|
+
if (!t->url_cred &&
|
|
161
|
+
git_cred_userpass_plaintext_new(&t->url_cred, t->user_from_url, t->pass_from_url) < 0)
|
|
162
|
+
return -1;
|
|
163
|
+
if (apply_basic_credential(buf, t->url_cred) < 0) return -1;
|
|
82
164
|
}
|
|
165
|
+
|
|
83
166
|
git_buf_puts(buf, "\r\n");
|
|
84
167
|
|
|
85
168
|
if (git_buf_oom(buf))
|
|
@@ -88,538 +171,783 @@ static int gen_request(git_buf *buf, const char *path, const char *host, const c
|
|
|
88
171
|
return 0;
|
|
89
172
|
}
|
|
90
173
|
|
|
91
|
-
static int
|
|
174
|
+
static int parse_unauthorized_response(
|
|
175
|
+
git_vector *www_authenticate,
|
|
176
|
+
int *allowed_types,
|
|
177
|
+
http_authmechanism_t *auth_mechanism)
|
|
92
178
|
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return -1;
|
|
179
|
+
unsigned i;
|
|
180
|
+
char *entry;
|
|
181
|
+
|
|
182
|
+
git_vector_foreach(www_authenticate, i, entry) {
|
|
183
|
+
if (!strncmp(entry, basic_authtype, 5) &&
|
|
184
|
+
(entry[5] == '\0' || entry[5] == ' ')) {
|
|
185
|
+
*allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
|
|
186
|
+
*auth_mechanism = GIT_HTTP_AUTH_BASIC;
|
|
187
|
+
}
|
|
103
188
|
}
|
|
104
189
|
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
105
192
|
|
|
106
|
-
|
|
107
|
-
|
|
193
|
+
static int on_header_ready(http_subtransport *t)
|
|
194
|
+
{
|
|
195
|
+
git_buf *name = &t->parse_header_name;
|
|
196
|
+
git_buf *value = &t->parse_header_value;
|
|
108
197
|
|
|
109
|
-
if (
|
|
110
|
-
if (
|
|
111
|
-
|
|
198
|
+
if (!strcasecmp("Content-Type", git_buf_cstr(name))) {
|
|
199
|
+
if (!t->content_type) {
|
|
200
|
+
t->content_type = git__strdup(git_buf_cstr(value));
|
|
201
|
+
GITERR_CHECK_ALLOC(t->content_type);
|
|
202
|
+
}
|
|
112
203
|
}
|
|
204
|
+
else if (!strcmp("WWW-Authenticate", git_buf_cstr(name))) {
|
|
205
|
+
char *dup = git__strdup(git_buf_cstr(value));
|
|
206
|
+
GITERR_CHECK_ALLOC(dup);
|
|
113
207
|
|
|
114
|
-
|
|
208
|
+
git_vector_insert(&t->www_authenticate, dup);
|
|
209
|
+
}
|
|
210
|
+
else if (!strcasecmp("Location", git_buf_cstr(name))) {
|
|
211
|
+
if (!t->location) {
|
|
212
|
+
t->location= git__strdup(git_buf_cstr(value));
|
|
213
|
+
GITERR_CHECK_ALLOC(t->location);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
115
216
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static int on_header_field(http_parser *parser, const char *str, size_t len)
|
|
221
|
+
{
|
|
222
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
223
|
+
http_subtransport *t = ctx->t;
|
|
224
|
+
|
|
225
|
+
/* Both parse_header_name and parse_header_value are populated
|
|
226
|
+
* and ready for consumption */
|
|
227
|
+
if (VALUE == t->last_cb)
|
|
228
|
+
if (on_header_ready(t) < 0)
|
|
229
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
230
|
+
|
|
231
|
+
if (NONE == t->last_cb || VALUE == t->last_cb)
|
|
232
|
+
git_buf_clear(&t->parse_header_name);
|
|
233
|
+
|
|
234
|
+
if (git_buf_put(&t->parse_header_name, str, len) < 0)
|
|
235
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
236
|
+
|
|
237
|
+
t->last_cb = FIELD;
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static int on_header_value(http_parser *parser, const char *str, size_t len)
|
|
242
|
+
{
|
|
243
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
244
|
+
http_subtransport *t = ctx->t;
|
|
119
245
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
246
|
+
assert(NONE != t->last_cb);
|
|
247
|
+
|
|
248
|
+
if (FIELD == t->last_cb)
|
|
249
|
+
git_buf_clear(&t->parse_header_value);
|
|
250
|
+
|
|
251
|
+
if (git_buf_put(&t->parse_header_value, str, len) < 0)
|
|
252
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
253
|
+
|
|
254
|
+
t->last_cb = VALUE;
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static int on_headers_complete(http_parser *parser)
|
|
259
|
+
{
|
|
260
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
261
|
+
http_subtransport *t = ctx->t;
|
|
262
|
+
http_stream *s = ctx->s;
|
|
123
263
|
git_buf buf = GIT_BUF_INIT;
|
|
124
|
-
BOOL ret;
|
|
125
|
-
DWORD flags;
|
|
126
|
-
void *buffer;
|
|
127
|
-
wchar_t *types[] = {
|
|
128
|
-
L"*/*",
|
|
129
|
-
NULL,
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
verb = ls ? L"GET" : L"POST";
|
|
133
|
-
buffer = data ? data : WINHTTP_NO_REQUEST_DATA;
|
|
134
|
-
flags = t->parent.use_ssl ? WINHTTP_FLAG_SECURE : 0;
|
|
135
|
-
|
|
136
|
-
if (ls)
|
|
137
|
-
git_buf_printf(&buf, "%s/info/refs?service=git-%s", t->path, service);
|
|
138
|
-
else
|
|
139
|
-
git_buf_printf(&buf, "%s/git-%s", t->path, service);
|
|
140
264
|
|
|
141
|
-
|
|
142
|
-
|
|
265
|
+
/* Both parse_header_name and parse_header_value are populated
|
|
266
|
+
* and ready for consumption. */
|
|
267
|
+
if (VALUE == t->last_cb)
|
|
268
|
+
if (on_header_ready(t) < 0)
|
|
269
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
143
270
|
|
|
144
|
-
|
|
271
|
+
/* Check for an authentication failure. */
|
|
272
|
+
if (parser->status_code == 401 &&
|
|
273
|
+
get_verb == s->verb &&
|
|
274
|
+
t->owner->cred_acquire_cb) {
|
|
275
|
+
int allowed_types = 0;
|
|
145
276
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
giterr_set(GITERR_OS, "Failed to open request");
|
|
150
|
-
return -1;
|
|
151
|
-
}
|
|
277
|
+
if (parse_unauthorized_response(&t->www_authenticate,
|
|
278
|
+
&allowed_types, &t->auth_mechanism) < 0)
|
|
279
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
152
280
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
goto on_error;
|
|
281
|
+
if (allowed_types &&
|
|
282
|
+
(!t->cred || 0 == (t->cred->credtype & allowed_types))) {
|
|
156
283
|
|
|
157
|
-
|
|
284
|
+
if (t->owner->cred_acquire_cb(&t->cred,
|
|
285
|
+
t->owner->url,
|
|
286
|
+
t->user_from_url,
|
|
287
|
+
allowed_types,
|
|
288
|
+
t->owner->cred_acquire_payload) < 0)
|
|
289
|
+
return PARSE_ERROR_GENERIC;
|
|
158
290
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
291
|
+
assert(t->cred);
|
|
292
|
+
|
|
293
|
+
/* Successfully acquired a credential. */
|
|
294
|
+
return t->parse_error = PARSE_ERROR_REPLAY;
|
|
295
|
+
}
|
|
162
296
|
}
|
|
163
297
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
298
|
+
/* Check for a redirect.
|
|
299
|
+
* Right now we only permit a redirect to the same hostname. */
|
|
300
|
+
if ((parser->status_code == 301 ||
|
|
301
|
+
parser->status_code == 302 ||
|
|
302
|
+
(parser->status_code == 303 && get_verb == s->verb) ||
|
|
303
|
+
parser->status_code == 307) &&
|
|
304
|
+
t->location) {
|
|
305
|
+
|
|
306
|
+
if (s->redirect_count >= 7) {
|
|
307
|
+
giterr_set(GITERR_NET, "Too many redirects");
|
|
308
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (t->location[0] != '/') {
|
|
312
|
+
giterr_set(GITERR_NET, "Only relative redirects are supported");
|
|
313
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
169
314
|
}
|
|
315
|
+
|
|
316
|
+
/* Set the redirect URL on the stream. This is a transfer of
|
|
317
|
+
* ownership of the memory. */
|
|
318
|
+
if (s->redirect_url)
|
|
319
|
+
git__free(s->redirect_url);
|
|
320
|
+
|
|
321
|
+
s->redirect_url = t->location;
|
|
322
|
+
t->location = NULL;
|
|
323
|
+
|
|
324
|
+
t->connected = 0;
|
|
325
|
+
s->redirect_count++;
|
|
326
|
+
|
|
327
|
+
return t->parse_error = PARSE_ERROR_REPLAY;
|
|
170
328
|
}
|
|
171
329
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
giterr_set(
|
|
175
|
-
|
|
330
|
+
/* Check for a 200 HTTP status code. */
|
|
331
|
+
if (parser->status_code != 200) {
|
|
332
|
+
giterr_set(GITERR_NET,
|
|
333
|
+
"Unexpected HTTP status code: %d",
|
|
334
|
+
parser->status_code);
|
|
335
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
176
336
|
}
|
|
177
337
|
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
giterr_set(
|
|
181
|
-
|
|
338
|
+
/* The response must contain a Content-Type header. */
|
|
339
|
+
if (!t->content_type) {
|
|
340
|
+
giterr_set(GITERR_NET, "No Content-Type header in response");
|
|
341
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
182
342
|
}
|
|
183
343
|
|
|
184
|
-
|
|
344
|
+
/* The Content-Type header must match our expectation. */
|
|
345
|
+
if (get_verb == s->verb)
|
|
346
|
+
git_buf_printf(&buf,
|
|
347
|
+
"application/x-git-%s-advertisement",
|
|
348
|
+
ctx->s->service);
|
|
349
|
+
else
|
|
350
|
+
git_buf_printf(&buf,
|
|
351
|
+
"application/x-git-%s-result",
|
|
352
|
+
ctx->s->service);
|
|
353
|
+
|
|
354
|
+
if (git_buf_oom(&buf))
|
|
355
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
356
|
+
|
|
357
|
+
if (strcmp(t->content_type, git_buf_cstr(&buf))) {
|
|
358
|
+
git_buf_free(&buf);
|
|
359
|
+
giterr_set(GITERR_NET,
|
|
360
|
+
"Invalid Content-Type: %s",
|
|
361
|
+
t->content_type);
|
|
362
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
363
|
+
}
|
|
185
364
|
|
|
186
|
-
on_error:
|
|
187
365
|
git_buf_free(&buf);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
t->request = NULL;
|
|
191
|
-
return -1;
|
|
192
|
-
#endif
|
|
366
|
+
|
|
367
|
+
return 0;
|
|
193
368
|
}
|
|
194
369
|
|
|
195
|
-
static int
|
|
370
|
+
static int on_message_complete(http_parser *parser)
|
|
196
371
|
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return 0;
|
|
372
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
373
|
+
http_subtransport *t = ctx->t;
|
|
200
374
|
|
|
201
|
-
|
|
202
|
-
return -1;
|
|
203
|
-
|
|
204
|
-
t->parent.connected = 1;
|
|
375
|
+
t->parse_finished = 1;
|
|
205
376
|
|
|
206
377
|
return 0;
|
|
207
|
-
|
|
208
|
-
wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
|
|
209
|
-
wchar_t host[GIT_WIN_PATH];
|
|
210
|
-
int32_t port;
|
|
378
|
+
}
|
|
211
379
|
|
|
212
|
-
|
|
213
|
-
|
|
380
|
+
static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
|
381
|
+
{
|
|
382
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
383
|
+
http_subtransport *t = ctx->t;
|
|
214
384
|
|
|
215
|
-
if (
|
|
216
|
-
giterr_set(
|
|
217
|
-
|
|
385
|
+
if (ctx->buf_size < len) {
|
|
386
|
+
giterr_set(GITERR_NET, "Can't fit data in the buffer");
|
|
387
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
218
388
|
}
|
|
219
389
|
|
|
220
|
-
|
|
390
|
+
memcpy(ctx->buffer, str, len);
|
|
391
|
+
*(ctx->bytes_read) += len;
|
|
392
|
+
ctx->buffer += len;
|
|
393
|
+
ctx->buf_size -= len;
|
|
221
394
|
|
|
222
|
-
|
|
223
|
-
|
|
395
|
+
return 0;
|
|
396
|
+
}
|
|
224
397
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
398
|
+
static void clear_parser_state(http_subtransport *t)
|
|
399
|
+
{
|
|
400
|
+
unsigned i;
|
|
401
|
+
char *entry;
|
|
230
402
|
|
|
231
|
-
t->
|
|
232
|
-
|
|
403
|
+
http_parser_init(&t->parser, HTTP_RESPONSE);
|
|
404
|
+
gitno_buffer_setup(&t->socket,
|
|
405
|
+
&t->parse_buffer,
|
|
406
|
+
t->parse_buffer_data,
|
|
407
|
+
sizeof(t->parse_buffer_data));
|
|
233
408
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
t->session = NULL;
|
|
238
|
-
}
|
|
239
|
-
return -1;
|
|
240
|
-
#endif
|
|
241
|
-
}
|
|
409
|
+
t->last_cb = NONE;
|
|
410
|
+
t->parse_error = 0;
|
|
411
|
+
t->parse_finished = 0;
|
|
242
412
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
* field handler before we can be sure that we can store the previous
|
|
246
|
-
* value. Right now, we only care about the
|
|
247
|
-
* Content-Type. on_header_{field,value} should be kept generic enough
|
|
248
|
-
* to work for any request.
|
|
249
|
-
*/
|
|
413
|
+
git_buf_free(&t->parse_header_name);
|
|
414
|
+
git_buf_init(&t->parse_header_name, 0);
|
|
250
415
|
|
|
251
|
-
|
|
416
|
+
git_buf_free(&t->parse_header_value);
|
|
417
|
+
git_buf_init(&t->parse_header_value, 0);
|
|
252
418
|
|
|
253
|
-
|
|
419
|
+
git__free(t->content_type);
|
|
420
|
+
t->content_type = NULL;
|
|
421
|
+
|
|
422
|
+
git__free(t->location);
|
|
423
|
+
t->location = NULL;
|
|
424
|
+
|
|
425
|
+
git_vector_foreach(&t->www_authenticate, i, entry)
|
|
426
|
+
git__free(entry);
|
|
427
|
+
|
|
428
|
+
git_vector_free(&t->www_authenticate);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
|
|
254
432
|
{
|
|
255
|
-
|
|
256
|
-
git_buf *buf = &t->buf;
|
|
257
|
-
|
|
258
|
-
if (t->last_cb == VALUE && t->ct_found) {
|
|
259
|
-
t->ct_finished = 1;
|
|
260
|
-
t->ct_found = 0;
|
|
261
|
-
t->content_type = git__strdup(git_buf_cstr(buf));
|
|
262
|
-
GITERR_CHECK_ALLOC(t->content_type);
|
|
263
|
-
git_buf_clear(buf);
|
|
264
|
-
}
|
|
433
|
+
git_buf buf = GIT_BUF_INIT;
|
|
265
434
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
435
|
+
/* Chunk header */
|
|
436
|
+
git_buf_printf(&buf, "%X\r\n", (unsigned)len);
|
|
437
|
+
|
|
438
|
+
if (git_buf_oom(&buf))
|
|
439
|
+
return -1;
|
|
440
|
+
|
|
441
|
+
if (gitno_send(socket, buf.ptr, buf.size, 0) < 0) {
|
|
442
|
+
git_buf_free(&buf);
|
|
443
|
+
return -1;
|
|
269
444
|
}
|
|
270
445
|
|
|
271
|
-
|
|
272
|
-
git_buf_clear(buf);
|
|
446
|
+
git_buf_free(&buf);
|
|
273
447
|
|
|
274
|
-
|
|
275
|
-
|
|
448
|
+
/* Chunk body */
|
|
449
|
+
if (len > 0 && gitno_send(socket, buffer, len, 0) < 0)
|
|
450
|
+
return -1;
|
|
276
451
|
|
|
277
|
-
|
|
452
|
+
/* Chunk footer */
|
|
453
|
+
if (gitno_send(socket, "\r\n", 2, 0) < 0)
|
|
454
|
+
return -1;
|
|
455
|
+
|
|
456
|
+
return 0;
|
|
278
457
|
}
|
|
279
458
|
|
|
280
|
-
static int
|
|
459
|
+
static int http_connect(http_subtransport *t)
|
|
281
460
|
{
|
|
282
|
-
|
|
283
|
-
git_buf *buf = &t->buf;
|
|
461
|
+
int flags = 0;
|
|
284
462
|
|
|
285
|
-
if (t->
|
|
286
|
-
t->
|
|
463
|
+
if (t->connected &&
|
|
464
|
+
http_should_keep_alive(&t->parser) &&
|
|
465
|
+
http_body_is_final(&t->parser))
|
|
287
466
|
return 0;
|
|
288
|
-
}
|
|
289
467
|
|
|
290
|
-
if (t->
|
|
291
|
-
|
|
468
|
+
if (t->socket.socket)
|
|
469
|
+
gitno_close(&t->socket);
|
|
470
|
+
|
|
471
|
+
if (t->use_ssl) {
|
|
472
|
+
int tflags;
|
|
292
473
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
474
|
+
if (t->owner->parent.read_flags(&t->owner->parent, &tflags) < 0)
|
|
475
|
+
return -1;
|
|
476
|
+
|
|
477
|
+
flags |= GITNO_CONNECT_SSL;
|
|
478
|
+
|
|
479
|
+
if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & tflags)
|
|
480
|
+
flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT;
|
|
297
481
|
}
|
|
298
482
|
|
|
299
|
-
t->
|
|
483
|
+
if (gitno_connect(&t->socket, t->host, t->port, flags) < 0)
|
|
484
|
+
return -1;
|
|
300
485
|
|
|
301
|
-
|
|
486
|
+
t->connected = 1;
|
|
487
|
+
return 0;
|
|
302
488
|
}
|
|
303
489
|
|
|
304
|
-
static int
|
|
490
|
+
static int http_stream_read(
|
|
491
|
+
git_smart_subtransport_stream *stream,
|
|
492
|
+
char *buffer,
|
|
493
|
+
size_t buf_size,
|
|
494
|
+
size_t *bytes_read)
|
|
305
495
|
{
|
|
306
|
-
|
|
307
|
-
|
|
496
|
+
http_stream *s = (http_stream *)stream;
|
|
497
|
+
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
498
|
+
parser_context ctx;
|
|
499
|
+
size_t bytes_parsed;
|
|
308
500
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
501
|
+
replay:
|
|
502
|
+
*bytes_read = 0;
|
|
503
|
+
|
|
504
|
+
assert(t->connected);
|
|
505
|
+
|
|
506
|
+
if (!s->sent_request) {
|
|
507
|
+
git_buf request = GIT_BUF_INIT;
|
|
508
|
+
|
|
509
|
+
clear_parser_state(t);
|
|
510
|
+
|
|
511
|
+
if (gen_request(&request, s, 0) < 0) {
|
|
512
|
+
giterr_set(GITERR_NET, "Failed to generate request");
|
|
513
|
+
return -1;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
|
517
|
+
git_buf_free(&request);
|
|
518
|
+
return -1;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
git_buf_free(&request);
|
|
522
|
+
|
|
523
|
+
s->sent_request = 1;
|
|
313
524
|
}
|
|
314
525
|
|
|
315
|
-
if (
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
526
|
+
if (!s->received_response) {
|
|
527
|
+
if (s->chunked) {
|
|
528
|
+
assert(s->verb == post_verb);
|
|
529
|
+
|
|
530
|
+
/* Flush, if necessary */
|
|
531
|
+
if (s->chunk_buffer_len > 0 &&
|
|
532
|
+
write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
|
533
|
+
return -1;
|
|
534
|
+
|
|
535
|
+
s->chunk_buffer_len = 0;
|
|
536
|
+
|
|
537
|
+
/* Write the final chunk. */
|
|
538
|
+
if (gitno_send(&t->socket, "0\r\n\r\n", 5, 0) < 0)
|
|
539
|
+
return -1;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
s->received_response = 1;
|
|
319
543
|
}
|
|
320
544
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (git_buf_oom(buf))
|
|
324
|
-
return t->error = -1;
|
|
545
|
+
while (!*bytes_read && !t->parse_finished) {
|
|
546
|
+
t->parse_buffer.offset = 0;
|
|
325
547
|
|
|
326
|
-
|
|
327
|
-
|
|
548
|
+
if (gitno_recv(&t->parse_buffer) < 0)
|
|
549
|
+
return -1;
|
|
328
550
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
551
|
+
/* This call to http_parser_execute will result in invocations of the
|
|
552
|
+
* on_* family of callbacks. The most interesting of these is
|
|
553
|
+
* on_body_fill_buffer, which is called when data is ready to be copied
|
|
554
|
+
* into the target buffer. We need to marshal the buffer, buf_size, and
|
|
555
|
+
* bytes_read parameters to this callback. */
|
|
556
|
+
ctx.t = t;
|
|
557
|
+
ctx.s = s;
|
|
558
|
+
ctx.buffer = buffer;
|
|
559
|
+
ctx.buf_size = buf_size;
|
|
560
|
+
ctx.bytes_read = bytes_read;
|
|
332
561
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
562
|
+
/* Set the context, call the parser, then unset the context. */
|
|
563
|
+
t->parser.data = &ctx;
|
|
564
|
+
|
|
565
|
+
bytes_parsed = http_parser_execute(&t->parser,
|
|
566
|
+
&t->settings,
|
|
567
|
+
t->parse_buffer.data,
|
|
568
|
+
t->parse_buffer.offset);
|
|
569
|
+
|
|
570
|
+
t->parser.data = NULL;
|
|
571
|
+
|
|
572
|
+
/* If there was a handled authentication failure, then parse_error
|
|
573
|
+
* will have signaled us that we should replay the request. */
|
|
574
|
+
if (PARSE_ERROR_REPLAY == t->parse_error) {
|
|
575
|
+
s->sent_request = 0;
|
|
576
|
+
|
|
577
|
+
if (http_connect(t) < 0)
|
|
578
|
+
return -1;
|
|
336
579
|
|
|
337
|
-
|
|
580
|
+
goto replay;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (t->parse_error < 0)
|
|
584
|
+
return -1;
|
|
338
585
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
586
|
+
if (bytes_parsed != t->parse_buffer.offset) {
|
|
587
|
+
giterr_set(GITERR_NET,
|
|
588
|
+
"HTTP parser error: %s",
|
|
589
|
+
http_errno_description((enum http_errno)t->parser.http_errno));
|
|
590
|
+
return -1;
|
|
591
|
+
}
|
|
342
592
|
}
|
|
343
593
|
|
|
344
594
|
return 0;
|
|
345
595
|
}
|
|
346
596
|
|
|
347
|
-
static int
|
|
597
|
+
static int http_stream_write_chunked(
|
|
598
|
+
git_smart_subtransport_stream *stream,
|
|
599
|
+
const char *buffer,
|
|
600
|
+
size_t len)
|
|
348
601
|
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
gitno_buffer *buf = &transport->buffer;
|
|
602
|
+
http_stream *s = (http_stream *)stream;
|
|
603
|
+
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
352
604
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
605
|
+
assert(t->connected);
|
|
606
|
+
|
|
607
|
+
/* Send the request, if necessary */
|
|
608
|
+
if (!s->sent_request) {
|
|
609
|
+
git_buf request = GIT_BUF_INIT;
|
|
610
|
+
|
|
611
|
+
clear_parser_state(t);
|
|
612
|
+
|
|
613
|
+
if (gen_request(&request, s, 0) < 0) {
|
|
614
|
+
giterr_set(GITERR_NET, "Failed to generate request");
|
|
615
|
+
return -1;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
|
619
|
+
git_buf_free(&request);
|
|
620
|
+
return -1;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
git_buf_free(&request);
|
|
624
|
+
|
|
625
|
+
s->sent_request = 1;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (len > CHUNK_SIZE) {
|
|
629
|
+
/* Flush, if necessary */
|
|
630
|
+
if (s->chunk_buffer_len > 0) {
|
|
631
|
+
if (write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
|
632
|
+
return -1;
|
|
633
|
+
|
|
634
|
+
s->chunk_buffer_len = 0;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/* Write chunk directly */
|
|
638
|
+
if (write_chunk(&t->socket, buffer, len) < 0)
|
|
639
|
+
return -1;
|
|
356
640
|
}
|
|
641
|
+
else {
|
|
642
|
+
/* Append as much to the buffer as we can */
|
|
643
|
+
int count = min(CHUNK_SIZE - s->chunk_buffer_len, len);
|
|
644
|
+
|
|
645
|
+
if (!s->chunk_buffer)
|
|
646
|
+
s->chunk_buffer = git__malloc(CHUNK_SIZE);
|
|
647
|
+
|
|
648
|
+
memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count);
|
|
649
|
+
s->chunk_buffer_len += count;
|
|
650
|
+
buffer += count;
|
|
651
|
+
len -= count;
|
|
357
652
|
|
|
358
|
-
|
|
359
|
-
|
|
653
|
+
/* Is the buffer full? If so, then flush */
|
|
654
|
+
if (CHUNK_SIZE == s->chunk_buffer_len) {
|
|
655
|
+
if (write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
|
656
|
+
return -1;
|
|
657
|
+
|
|
658
|
+
s->chunk_buffer_len = 0;
|
|
659
|
+
|
|
660
|
+
if (len > 0) {
|
|
661
|
+
memcpy(s->chunk_buffer, buffer, len);
|
|
662
|
+
s->chunk_buffer_len = len;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
360
666
|
|
|
361
667
|
return 0;
|
|
362
668
|
}
|
|
363
669
|
|
|
364
|
-
static int
|
|
670
|
+
static int http_stream_write_single(
|
|
671
|
+
git_smart_subtransport_stream *stream,
|
|
672
|
+
const char *buffer,
|
|
673
|
+
size_t len)
|
|
365
674
|
{
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
char buffer[2048];
|
|
370
|
-
#ifdef GIT_WINHTTP
|
|
371
|
-
DWORD recvd;
|
|
372
|
-
#else
|
|
373
|
-
gitno_buffer inner;
|
|
374
|
-
int error;
|
|
375
|
-
#endif
|
|
376
|
-
|
|
377
|
-
if (t->transfer_finished)
|
|
378
|
-
return 0;
|
|
675
|
+
http_stream *s = (http_stream *)stream;
|
|
676
|
+
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
677
|
+
git_buf request = GIT_BUF_INIT;
|
|
379
678
|
|
|
380
|
-
|
|
381
|
-
gitno_buffer_setup(transport, &inner, buffer, sizeof(buffer));
|
|
679
|
+
assert(t->connected);
|
|
382
680
|
|
|
383
|
-
if (
|
|
681
|
+
if (s->sent_request) {
|
|
682
|
+
giterr_set(GITERR_NET, "Subtransport configured for only one write");
|
|
384
683
|
return -1;
|
|
385
|
-
|
|
386
|
-
old_len = buf->offset;
|
|
387
|
-
http_parser_execute(&t->parser, &t->settings, inner.data, inner.offset);
|
|
388
|
-
if (t->error < 0)
|
|
389
|
-
return t->error;
|
|
390
|
-
#else
|
|
391
|
-
old_len = buf->offset;
|
|
392
|
-
if (WinHttpReadData(t->request, buffer, sizeof(buffer), &recvd) == FALSE) {
|
|
393
|
-
giterr_set(GITERR_OS, "Failed to read data from the network");
|
|
394
|
-
return t->error = -1;
|
|
395
684
|
}
|
|
396
685
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
686
|
+
clear_parser_state(t);
|
|
687
|
+
|
|
688
|
+
if (gen_request(&request, s, len) < 0) {
|
|
689
|
+
giterr_set(GITERR_NET, "Failed to generate request");
|
|
690
|
+
return -1;
|
|
400
691
|
}
|
|
401
692
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
693
|
+
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0)
|
|
694
|
+
goto on_error;
|
|
695
|
+
|
|
696
|
+
if (len && gitno_send(&t->socket, buffer, len, 0) < 0)
|
|
697
|
+
goto on_error;
|
|
698
|
+
|
|
699
|
+
git_buf_free(&request);
|
|
700
|
+
s->sent_request = 1;
|
|
405
701
|
|
|
406
|
-
return
|
|
702
|
+
return 0;
|
|
703
|
+
|
|
704
|
+
on_error:
|
|
705
|
+
git_buf_free(&request);
|
|
706
|
+
return -1;
|
|
407
707
|
}
|
|
408
708
|
|
|
409
|
-
|
|
410
|
-
static void setup_gitno_buffer(git_transport *transport)
|
|
709
|
+
static void http_stream_free(git_smart_subtransport_stream *stream)
|
|
411
710
|
{
|
|
412
|
-
|
|
711
|
+
http_stream *s = (http_stream *)stream;
|
|
413
712
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
memset(&t->settings, 0x0, sizeof(http_parser_settings));
|
|
420
|
-
t->settings.on_header_field = on_header_field;
|
|
421
|
-
t->settings.on_header_value = on_header_value;
|
|
422
|
-
t->settings.on_headers_complete = on_headers_complete;
|
|
423
|
-
t->settings.on_body = on_body_fill_buffer;
|
|
424
|
-
t->settings.on_message_complete = on_message_complete;
|
|
425
|
-
#endif
|
|
713
|
+
if (s->chunk_buffer)
|
|
714
|
+
git__free(s->chunk_buffer);
|
|
715
|
+
|
|
716
|
+
if (s->redirect_url)
|
|
717
|
+
git__free(s->redirect_url);
|
|
426
718
|
|
|
427
|
-
|
|
719
|
+
git__free(s);
|
|
428
720
|
}
|
|
429
721
|
|
|
430
|
-
static int
|
|
722
|
+
static int http_stream_alloc(http_subtransport *t,
|
|
723
|
+
git_smart_subtransport_stream **stream)
|
|
431
724
|
{
|
|
432
|
-
|
|
433
|
-
int ret;
|
|
434
|
-
git_buf request = GIT_BUF_INIT;
|
|
435
|
-
const char *service = "upload-pack";
|
|
436
|
-
const char *url = t->parent.url, *prefix_http = "http://", *prefix_https = "https://";
|
|
437
|
-
const char *default_port;
|
|
438
|
-
git_pkt *pkt;
|
|
725
|
+
http_stream *s;
|
|
439
726
|
|
|
440
|
-
if (
|
|
441
|
-
giterr_set(GITERR_NET, "Pushing over HTTP is not implemented");
|
|
727
|
+
if (!stream)
|
|
442
728
|
return -1;
|
|
443
|
-
}
|
|
444
729
|
|
|
445
|
-
|
|
730
|
+
s = git__calloc(sizeof(http_stream), 1);
|
|
731
|
+
GITERR_CHECK_ALLOC(s);
|
|
446
732
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
733
|
+
s->parent.subtransport = &t->parent;
|
|
734
|
+
s->parent.read = http_stream_read;
|
|
735
|
+
s->parent.write = http_stream_write_single;
|
|
736
|
+
s->parent.free = http_stream_free;
|
|
451
737
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
738
|
+
*stream = (git_smart_subtransport_stream *)s;
|
|
739
|
+
return 0;
|
|
740
|
+
}
|
|
456
741
|
|
|
457
|
-
|
|
742
|
+
static int http_uploadpack_ls(
|
|
743
|
+
http_subtransport *t,
|
|
744
|
+
git_smart_subtransport_stream **stream)
|
|
745
|
+
{
|
|
746
|
+
http_stream *s;
|
|
458
747
|
|
|
459
|
-
if ((
|
|
460
|
-
|
|
748
|
+
if (http_stream_alloc(t, stream) < 0)
|
|
749
|
+
return -1;
|
|
461
750
|
|
|
462
|
-
|
|
463
|
-
GITERR_CHECK_ALLOC(t->service);
|
|
751
|
+
s = (http_stream *)*stream;
|
|
464
752
|
|
|
465
|
-
|
|
466
|
-
|
|
753
|
+
s->service = upload_pack_service;
|
|
754
|
+
s->service_url = upload_pack_ls_service_url;
|
|
755
|
+
s->verb = get_verb;
|
|
467
756
|
|
|
468
|
-
|
|
469
|
-
|
|
757
|
+
return 0;
|
|
758
|
+
}
|
|
470
759
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
760
|
+
static int http_uploadpack(
|
|
761
|
+
http_subtransport *t,
|
|
762
|
+
git_smart_subtransport_stream **stream)
|
|
763
|
+
{
|
|
764
|
+
http_stream *s;
|
|
474
765
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
giterr_set(GITERR_NET, "Invalid HTTP response");
|
|
478
|
-
return t->error = -1;
|
|
479
|
-
} else {
|
|
480
|
-
/* Remove the comment pkt from the list */
|
|
481
|
-
git_vector_remove(&transport->refs, 0);
|
|
482
|
-
git__free(pkt);
|
|
483
|
-
}
|
|
766
|
+
if (http_stream_alloc(t, stream) < 0)
|
|
767
|
+
return -1;
|
|
484
768
|
|
|
485
|
-
|
|
486
|
-
return t->error = -1;
|
|
769
|
+
s = (http_stream *)*stream;
|
|
487
770
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
771
|
+
s->service = upload_pack_service;
|
|
772
|
+
s->service_url = upload_pack_service_url;
|
|
773
|
+
s->verb = post_verb;
|
|
491
774
|
|
|
492
|
-
return
|
|
775
|
+
return 0;
|
|
493
776
|
}
|
|
494
777
|
|
|
495
|
-
static int
|
|
778
|
+
static int http_receivepack_ls(
|
|
779
|
+
http_subtransport *t,
|
|
780
|
+
git_smart_subtransport_stream **stream)
|
|
496
781
|
{
|
|
497
|
-
|
|
498
|
-
int ret;
|
|
782
|
+
http_stream *s;
|
|
499
783
|
|
|
500
|
-
|
|
501
|
-
if ((ret = do_connect(t)) < 0)
|
|
784
|
+
if (http_stream_alloc(t, stream) < 0)
|
|
502
785
|
return -1;
|
|
503
786
|
|
|
504
|
-
|
|
505
|
-
return -1;
|
|
787
|
+
s = (http_stream *)*stream;
|
|
506
788
|
|
|
507
|
-
|
|
508
|
-
|
|
789
|
+
s->service = receive_pack_service;
|
|
790
|
+
s->service_url = receive_pack_ls_service_url;
|
|
791
|
+
s->verb = get_verb;
|
|
509
792
|
|
|
510
793
|
return 0;
|
|
511
794
|
}
|
|
512
795
|
|
|
513
|
-
static int
|
|
796
|
+
static int http_receivepack(
|
|
797
|
+
http_subtransport *t,
|
|
798
|
+
git_smart_subtransport_stream **stream)
|
|
514
799
|
{
|
|
515
|
-
|
|
516
|
-
if (gitno_ssl_teardown(transport) < 0)
|
|
517
|
-
return -1;
|
|
800
|
+
http_stream *s;
|
|
518
801
|
|
|
519
|
-
if (
|
|
520
|
-
giterr_set(GITERR_OS, "Failed to close the socket: %s", strerror(errno));
|
|
802
|
+
if (http_stream_alloc(t, stream) < 0)
|
|
521
803
|
return -1;
|
|
522
|
-
}
|
|
523
|
-
#else
|
|
524
|
-
transport_http *t = (transport_http *) transport;
|
|
525
804
|
|
|
526
|
-
|
|
527
|
-
WinHttpCloseHandle(t->request);
|
|
528
|
-
if (t->connection)
|
|
529
|
-
WinHttpCloseHandle(t->connection);
|
|
530
|
-
if (t->session)
|
|
531
|
-
WinHttpCloseHandle(t->session);
|
|
532
|
-
#endif
|
|
805
|
+
s = (http_stream *)*stream;
|
|
533
806
|
|
|
534
|
-
|
|
807
|
+
/* Use Transfer-Encoding: chunked for this request */
|
|
808
|
+
s->chunked = 1;
|
|
809
|
+
s->parent.write = http_stream_write_chunked;
|
|
810
|
+
|
|
811
|
+
s->service = receive_pack_service;
|
|
812
|
+
s->service_url = receive_pack_service_url;
|
|
813
|
+
s->verb = post_verb;
|
|
535
814
|
|
|
536
815
|
return 0;
|
|
537
816
|
}
|
|
538
817
|
|
|
539
|
-
|
|
540
|
-
|
|
818
|
+
static int http_action(
|
|
819
|
+
git_smart_subtransport_stream **stream,
|
|
820
|
+
git_smart_subtransport *subtransport,
|
|
821
|
+
const char *url,
|
|
822
|
+
git_smart_service_t action)
|
|
541
823
|
{
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
824
|
+
http_subtransport *t = (http_subtransport *)subtransport;
|
|
825
|
+
const char *default_port = NULL;
|
|
826
|
+
int ret;
|
|
827
|
+
|
|
828
|
+
if (!stream)
|
|
829
|
+
return -1;
|
|
830
|
+
|
|
831
|
+
if (!t->host || !t->port || !t->path) {
|
|
832
|
+
if (!git__prefixcmp(url, prefix_http)) {
|
|
833
|
+
url = url + strlen(prefix_http);
|
|
834
|
+
default_port = "80";
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (!git__prefixcmp(url, prefix_https)) {
|
|
838
|
+
url += strlen(prefix_https);
|
|
839
|
+
default_port = "443";
|
|
840
|
+
t->use_ssl = 1;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (!default_port)
|
|
844
|
+
return -1;
|
|
845
|
+
|
|
846
|
+
if ((ret = gitno_extract_url_parts(&t->host, &t->port,
|
|
847
|
+
&t->user_from_url, &t->pass_from_url, url, default_port)) < 0)
|
|
848
|
+
return ret;
|
|
849
|
+
|
|
850
|
+
t->path = strchr(url, '/');
|
|
558
851
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
852
|
+
|
|
853
|
+
if (http_connect(t) < 0)
|
|
854
|
+
return -1;
|
|
855
|
+
|
|
856
|
+
switch (action)
|
|
857
|
+
{
|
|
858
|
+
case GIT_SERVICE_UPLOADPACK_LS:
|
|
859
|
+
return http_uploadpack_ls(t, stream);
|
|
860
|
+
|
|
861
|
+
case GIT_SERVICE_UPLOADPACK:
|
|
862
|
+
return http_uploadpack(t, stream);
|
|
863
|
+
|
|
864
|
+
case GIT_SERVICE_RECEIVEPACK_LS:
|
|
865
|
+
return http_receivepack_ls(t, stream);
|
|
866
|
+
|
|
867
|
+
case GIT_SERVICE_RECEIVEPACK:
|
|
868
|
+
return http_receivepack(t, stream);
|
|
562
869
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
git__free(t->host);
|
|
567
|
-
git__free(t->port);
|
|
568
|
-
git__free(t->service);
|
|
569
|
-
git__free(t->parent.url);
|
|
570
|
-
git__free(t);
|
|
870
|
+
|
|
871
|
+
*stream = NULL;
|
|
872
|
+
return -1;
|
|
571
873
|
}
|
|
572
874
|
|
|
573
|
-
int
|
|
875
|
+
static int http_close(git_smart_subtransport *subtransport)
|
|
574
876
|
{
|
|
575
|
-
|
|
877
|
+
http_subtransport *t = (http_subtransport *) subtransport;
|
|
576
878
|
|
|
577
|
-
t
|
|
578
|
-
GITERR_CHECK_ALLOC(t);
|
|
879
|
+
clear_parser_state(t);
|
|
579
880
|
|
|
580
|
-
|
|
881
|
+
if (t->socket.socket) {
|
|
882
|
+
gitno_close(&t->socket);
|
|
883
|
+
memset(&t->socket, 0x0, sizeof(gitno_socket));
|
|
884
|
+
}
|
|
581
885
|
|
|
582
|
-
t->
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
t->parent.rpc = 1;
|
|
886
|
+
if (t->cred) {
|
|
887
|
+
t->cred->free(t->cred);
|
|
888
|
+
t->cred = NULL;
|
|
889
|
+
}
|
|
587
890
|
|
|
588
|
-
if (
|
|
589
|
-
|
|
590
|
-
|
|
891
|
+
if (t->url_cred) {
|
|
892
|
+
t->url_cred->free(t->url_cred);
|
|
893
|
+
t->url_cred = NULL;
|
|
591
894
|
}
|
|
592
895
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
896
|
+
if (t->host) {
|
|
897
|
+
git__free(t->host);
|
|
898
|
+
t->host = NULL;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (t->port) {
|
|
902
|
+
git__free(t->port);
|
|
903
|
+
t->port = NULL;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
if (t->user_from_url) {
|
|
907
|
+
git__free(t->user_from_url);
|
|
908
|
+
t->user_from_url = NULL;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (t->pass_from_url) {
|
|
912
|
+
git__free(t->pass_from_url);
|
|
913
|
+
t->pass_from_url = NULL;
|
|
600
914
|
}
|
|
601
|
-
#endif
|
|
602
915
|
|
|
603
|
-
*out = (git_transport *) t;
|
|
604
916
|
return 0;
|
|
605
917
|
}
|
|
606
918
|
|
|
607
|
-
|
|
919
|
+
static void http_free(git_smart_subtransport *subtransport)
|
|
608
920
|
{
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
921
|
+
http_subtransport *t = (http_subtransport *) subtransport;
|
|
922
|
+
|
|
923
|
+
http_close(subtransport);
|
|
924
|
+
|
|
925
|
+
git__free(t);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner)
|
|
929
|
+
{
|
|
930
|
+
http_subtransport *t;
|
|
931
|
+
|
|
932
|
+
if (!out)
|
|
612
933
|
return -1;
|
|
613
934
|
|
|
614
|
-
t
|
|
615
|
-
t
|
|
616
|
-
*out = (git_transport *) t;
|
|
935
|
+
t = git__calloc(sizeof(http_subtransport), 1);
|
|
936
|
+
GITERR_CHECK_ALLOC(t);
|
|
617
937
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
938
|
+
t->owner = (transport_smart *)owner;
|
|
939
|
+
t->parent.action = http_action;
|
|
940
|
+
t->parent.close = http_close;
|
|
941
|
+
t->parent.free = http_free;
|
|
621
942
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
943
|
+
t->settings.on_header_field = on_header_field;
|
|
944
|
+
t->settings.on_header_value = on_header_value;
|
|
945
|
+
t->settings.on_headers_complete = on_headers_complete;
|
|
946
|
+
t->settings.on_body = on_body_fill_buffer;
|
|
947
|
+
t->settings.on_message_complete = on_message_complete;
|
|
948
|
+
|
|
949
|
+
*out = (git_smart_subtransport *) t;
|
|
950
|
+
return 0;
|
|
625
951
|
}
|
|
952
|
+
|
|
953
|
+
#endif /* !GIT_WINHTTP */
|