rugged 0.28.4.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (391) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/rugged/extconf.rb +3 -1
  4. data/ext/rugged/rugged.c +35 -31
  5. data/ext/rugged/rugged.h +13 -0
  6. data/ext/rugged/rugged_blob.c +11 -9
  7. data/ext/rugged/rugged_commit.c +17 -15
  8. data/ext/rugged/rugged_config.c +1 -1
  9. data/ext/rugged/rugged_diff.c +4 -26
  10. data/ext/rugged/rugged_index.c +4 -2
  11. data/ext/rugged/rugged_note.c +5 -3
  12. data/ext/rugged/rugged_object.c +57 -10
  13. data/ext/rugged/rugged_rebase.c +3 -1
  14. data/ext/rugged/rugged_remote.c +32 -8
  15. data/ext/rugged/rugged_repo.c +232 -17
  16. data/ext/rugged/rugged_tag.c +8 -6
  17. data/ext/rugged/rugged_tree.c +18 -16
  18. data/lib/rugged/commit.rb +1 -2
  19. data/lib/rugged/repository.rb +5 -6
  20. data/lib/rugged/submodule_collection.rb +4 -4
  21. data/lib/rugged/version.rb +1 -1
  22. data/vendor/libgit2/AUTHORS +1 -0
  23. data/vendor/libgit2/CMakeLists.txt +39 -19
  24. data/vendor/libgit2/COPYING +28 -0
  25. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +5 -1
  26. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +2 -2
  27. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +1 -1
  28. data/vendor/libgit2/cmake/Modules/FindGSSFramework.cmake +28 -0
  29. data/vendor/libgit2/cmake/Modules/FindPCRE.cmake +38 -0
  30. data/vendor/libgit2/cmake/Modules/FindPCRE2.cmake +37 -0
  31. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +2 -2
  32. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +6 -0
  33. data/vendor/libgit2/cmake/Modules/PkgBuildConfig.cmake +77 -0
  34. data/vendor/libgit2/cmake/Modules/SanitizeBool.cmake +20 -0
  35. data/vendor/libgit2/cmake/Modules/SelectGSSAPI.cmake +56 -0
  36. data/vendor/libgit2/cmake/Modules/SelectHTTPSBackend.cmake +127 -0
  37. data/vendor/libgit2/cmake/Modules/SelectHashes.cmake +69 -0
  38. data/vendor/libgit2/deps/http-parser/http_parser.c +11 -6
  39. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +23 -0
  40. data/vendor/libgit2/deps/ntlmclient/compat.h +55 -0
  41. data/vendor/libgit2/deps/ntlmclient/crypt.h +64 -0
  42. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +120 -0
  43. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +18 -0
  44. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +145 -0
  45. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +18 -0
  46. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +130 -0
  47. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +21 -0
  48. data/vendor/libgit2/deps/ntlmclient/ntlm.c +1422 -0
  49. data/vendor/libgit2/deps/ntlmclient/ntlm.h +174 -0
  50. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +320 -0
  51. data/vendor/libgit2/deps/ntlmclient/unicode.h +36 -0
  52. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +445 -0
  53. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +201 -0
  54. data/vendor/libgit2/deps/ntlmclient/utf8.h +1257 -0
  55. data/vendor/libgit2/deps/ntlmclient/util.c +21 -0
  56. data/vendor/libgit2/deps/ntlmclient/util.h +14 -0
  57. data/vendor/libgit2/deps/pcre/CMakeLists.txt +140 -0
  58. data/vendor/libgit2/deps/pcre/COPYING +5 -0
  59. data/vendor/libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  60. data/vendor/libgit2/deps/pcre/cmake/FindEditline.cmake +17 -0
  61. data/vendor/libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  62. data/vendor/libgit2/deps/pcre/cmake/FindReadline.cmake +29 -0
  63. data/vendor/libgit2/deps/pcre/config.h.in +57 -0
  64. data/vendor/libgit2/deps/pcre/pcre.h +641 -0
  65. data/vendor/libgit2/deps/pcre/pcre_byte_order.c +319 -0
  66. data/vendor/libgit2/deps/pcre/pcre_chartables.c +198 -0
  67. data/vendor/libgit2/deps/pcre/pcre_compile.c +9800 -0
  68. data/vendor/libgit2/deps/pcre/pcre_config.c +190 -0
  69. data/vendor/libgit2/deps/pcre/pcre_dfa_exec.c +3676 -0
  70. data/vendor/libgit2/deps/pcre/pcre_exec.c +7173 -0
  71. data/vendor/libgit2/deps/pcre/pcre_fullinfo.c +245 -0
  72. data/vendor/libgit2/deps/pcre/pcre_get.c +669 -0
  73. data/vendor/libgit2/deps/pcre/pcre_globals.c +86 -0
  74. data/vendor/libgit2/deps/pcre/pcre_internal.h +2787 -0
  75. data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +11913 -0
  76. data/vendor/libgit2/deps/pcre/pcre_maketables.c +156 -0
  77. data/vendor/libgit2/deps/pcre/pcre_newline.c +210 -0
  78. data/vendor/libgit2/deps/pcre/pcre_ord2utf8.c +94 -0
  79. data/vendor/libgit2/deps/pcre/pcre_printint.c +834 -0
  80. data/vendor/libgit2/deps/pcre/pcre_refcount.c +92 -0
  81. data/vendor/libgit2/deps/pcre/pcre_string_utils.c +211 -0
  82. data/vendor/libgit2/deps/pcre/pcre_study.c +1686 -0
  83. data/vendor/libgit2/deps/pcre/pcre_tables.c +727 -0
  84. data/vendor/libgit2/deps/pcre/pcre_ucd.c +3644 -0
  85. data/vendor/libgit2/deps/pcre/pcre_valid_utf8.c +301 -0
  86. data/vendor/libgit2/deps/pcre/pcre_version.c +98 -0
  87. data/vendor/libgit2/deps/pcre/pcre_xclass.c +268 -0
  88. data/vendor/libgit2/deps/pcre/pcreposix.c +421 -0
  89. data/vendor/libgit2/deps/pcre/pcreposix.h +117 -0
  90. data/vendor/libgit2/deps/pcre/ucp.h +224 -0
  91. data/vendor/libgit2/deps/zlib/adler32.c +0 -7
  92. data/vendor/libgit2/deps/zlib/crc32.c +0 -7
  93. data/vendor/libgit2/include/git2.h +2 -0
  94. data/vendor/libgit2/include/git2/apply.h +22 -2
  95. data/vendor/libgit2/include/git2/attr.h +23 -13
  96. data/vendor/libgit2/include/git2/blame.h +2 -2
  97. data/vendor/libgit2/include/git2/blob.h +44 -12
  98. data/vendor/libgit2/include/git2/branch.h +74 -57
  99. data/vendor/libgit2/include/git2/buffer.h +20 -14
  100. data/vendor/libgit2/include/git2/cert.h +135 -0
  101. data/vendor/libgit2/include/git2/checkout.h +46 -14
  102. data/vendor/libgit2/include/git2/cherrypick.h +3 -3
  103. data/vendor/libgit2/include/git2/clone.h +2 -2
  104. data/vendor/libgit2/include/git2/commit.h +23 -1
  105. data/vendor/libgit2/include/git2/common.h +15 -6
  106. data/vendor/libgit2/include/git2/config.h +12 -12
  107. data/vendor/libgit2/include/git2/cred_helpers.h +4 -42
  108. data/vendor/libgit2/include/git2/credential.h +314 -0
  109. data/vendor/libgit2/include/git2/credential_helpers.h +52 -0
  110. data/vendor/libgit2/include/git2/deprecated.h +321 -3
  111. data/vendor/libgit2/include/git2/describe.h +4 -4
  112. data/vendor/libgit2/include/git2/diff.h +16 -14
  113. data/vendor/libgit2/include/git2/errors.h +4 -2
  114. data/vendor/libgit2/include/git2/filter.h +8 -0
  115. data/vendor/libgit2/include/git2/index.h +2 -1
  116. data/vendor/libgit2/include/git2/indexer.h +48 -4
  117. data/vendor/libgit2/include/git2/merge.h +6 -10
  118. data/vendor/libgit2/include/git2/net.h +0 -5
  119. data/vendor/libgit2/include/git2/object.h +2 -14
  120. data/vendor/libgit2/include/git2/odb.h +3 -2
  121. data/vendor/libgit2/include/git2/odb_backend.h +5 -4
  122. data/vendor/libgit2/include/git2/oid.h +11 -6
  123. data/vendor/libgit2/include/git2/pack.h +12 -1
  124. data/vendor/libgit2/include/git2/proxy.h +6 -4
  125. data/vendor/libgit2/include/git2/rebase.h +46 -2
  126. data/vendor/libgit2/include/git2/refs.h +19 -0
  127. data/vendor/libgit2/include/git2/remote.h +40 -15
  128. data/vendor/libgit2/include/git2/repository.h +29 -6
  129. data/vendor/libgit2/include/git2/revert.h +1 -1
  130. data/vendor/libgit2/include/git2/revwalk.h +7 -3
  131. data/vendor/libgit2/include/git2/stash.h +4 -4
  132. data/vendor/libgit2/include/git2/status.h +25 -16
  133. data/vendor/libgit2/include/git2/submodule.h +20 -3
  134. data/vendor/libgit2/include/git2/sys/alloc.h +9 -9
  135. data/vendor/libgit2/include/git2/sys/cred.h +15 -0
  136. data/vendor/libgit2/include/git2/sys/credential.h +90 -0
  137. data/vendor/libgit2/include/git2/sys/index.h +4 -2
  138. data/vendor/libgit2/include/git2/sys/mempack.h +2 -1
  139. data/vendor/libgit2/include/git2/sys/merge.h +1 -1
  140. data/vendor/libgit2/include/git2/sys/odb_backend.h +48 -4
  141. data/vendor/libgit2/include/git2/sys/refdb_backend.h +164 -21
  142. data/vendor/libgit2/include/git2/sys/repository.h +17 -6
  143. data/vendor/libgit2/include/git2/sys/transport.h +4 -4
  144. data/vendor/libgit2/include/git2/tag.h +11 -2
  145. data/vendor/libgit2/include/git2/trace.h +2 -2
  146. data/vendor/libgit2/include/git2/transport.h +11 -340
  147. data/vendor/libgit2/include/git2/tree.h +5 -3
  148. data/vendor/libgit2/include/git2/types.h +4 -89
  149. data/vendor/libgit2/include/git2/version.h +5 -5
  150. data/vendor/libgit2/include/git2/worktree.h +5 -5
  151. data/vendor/libgit2/src/CMakeLists.txt +99 -236
  152. data/vendor/libgit2/src/alloc.c +2 -14
  153. data/vendor/libgit2/src/{stdalloc.c → allocators/stdalloc.c} +3 -4
  154. data/vendor/libgit2/src/{stdalloc.h → allocators/stdalloc.h} +4 -4
  155. data/vendor/libgit2/src/allocators/win32_crtdbg.c +118 -0
  156. data/vendor/libgit2/src/{transports/cred.h → allocators/win32_crtdbg.h} +5 -4
  157. data/vendor/libgit2/src/apply.c +60 -30
  158. data/vendor/libgit2/src/attr.c +70 -64
  159. data/vendor/libgit2/src/attr_file.c +189 -96
  160. data/vendor/libgit2/src/attr_file.h +9 -9
  161. data/vendor/libgit2/src/attrcache.c +48 -48
  162. data/vendor/libgit2/src/attrcache.h +2 -1
  163. data/vendor/libgit2/src/blame.c +17 -5
  164. data/vendor/libgit2/src/blame.h +1 -1
  165. data/vendor/libgit2/src/blame_git.c +21 -7
  166. data/vendor/libgit2/src/blob.c +81 -17
  167. data/vendor/libgit2/src/blob.h +2 -2
  168. data/vendor/libgit2/src/branch.c +60 -32
  169. data/vendor/libgit2/src/buffer.c +19 -7
  170. data/vendor/libgit2/src/buffer.h +1 -0
  171. data/vendor/libgit2/src/cache.c +33 -36
  172. data/vendor/libgit2/src/cache.h +1 -1
  173. data/vendor/libgit2/src/cc-compat.h +5 -0
  174. data/vendor/libgit2/src/checkout.c +26 -16
  175. data/vendor/libgit2/src/cherrypick.c +9 -3
  176. data/vendor/libgit2/src/clone.c +29 -7
  177. data/vendor/libgit2/src/clone.h +4 -0
  178. data/vendor/libgit2/src/commit.c +70 -22
  179. data/vendor/libgit2/src/commit.h +6 -0
  180. data/vendor/libgit2/src/commit_list.c +28 -76
  181. data/vendor/libgit2/src/commit_list.h +2 -2
  182. data/vendor/libgit2/src/common.h +3 -75
  183. data/vendor/libgit2/src/config.c +31 -40
  184. data/vendor/libgit2/src/config.h +7 -6
  185. data/vendor/libgit2/src/config_backend.h +12 -0
  186. data/vendor/libgit2/src/config_cache.c +39 -39
  187. data/vendor/libgit2/src/config_entries.c +69 -99
  188. data/vendor/libgit2/src/config_entries.h +1 -0
  189. data/vendor/libgit2/src/config_file.c +346 -380
  190. data/vendor/libgit2/src/config_mem.c +12 -16
  191. data/vendor/libgit2/src/config_parse.c +49 -29
  192. data/vendor/libgit2/src/config_parse.h +13 -12
  193. data/vendor/libgit2/src/config_snapshot.c +206 -0
  194. data/vendor/libgit2/src/crlf.c +14 -14
  195. data/vendor/libgit2/src/describe.c +21 -20
  196. data/vendor/libgit2/src/diff.c +43 -58
  197. data/vendor/libgit2/src/diff.h +4 -3
  198. data/vendor/libgit2/src/diff_driver.c +37 -38
  199. data/vendor/libgit2/src/diff_file.c +12 -10
  200. data/vendor/libgit2/src/diff_file.h +2 -2
  201. data/vendor/libgit2/src/diff_generate.c +148 -98
  202. data/vendor/libgit2/src/diff_generate.h +2 -2
  203. data/vendor/libgit2/src/diff_parse.c +1 -1
  204. data/vendor/libgit2/src/diff_print.c +25 -13
  205. data/vendor/libgit2/src/diff_stats.c +1 -1
  206. data/vendor/libgit2/src/diff_tform.c +11 -11
  207. data/vendor/libgit2/src/errors.c +21 -25
  208. data/vendor/libgit2/src/errors.h +81 -0
  209. data/vendor/libgit2/src/features.h.in +9 -2
  210. data/vendor/libgit2/src/fetch.c +7 -2
  211. data/vendor/libgit2/src/fetchhead.c +36 -4
  212. data/vendor/libgit2/src/filebuf.c +6 -10
  213. data/vendor/libgit2/src/filebuf.h +2 -2
  214. data/vendor/libgit2/src/filter.c +16 -8
  215. data/vendor/libgit2/src/{fileops.c → futils.c} +21 -17
  216. data/vendor/libgit2/src/{fileops.h → futils.h} +5 -5
  217. data/vendor/libgit2/src/global.c +12 -40
  218. data/vendor/libgit2/src/global.h +0 -2
  219. data/vendor/libgit2/src/hash.c +61 -0
  220. data/vendor/libgit2/src/hash.h +19 -21
  221. data/vendor/libgit2/src/hash/sha1.h +38 -0
  222. data/vendor/libgit2/src/hash/{hash_collisiondetect.h → sha1/collisiondetect.c} +14 -17
  223. data/vendor/libgit2/src/{sha1_lookup.h → hash/sha1/collisiondetect.h} +8 -8
  224. data/vendor/libgit2/src/hash/{hash_common_crypto.h → sha1/common_crypto.c} +15 -19
  225. data/vendor/libgit2/src/hash/sha1/common_crypto.h +19 -0
  226. data/vendor/libgit2/src/hash/{hash_generic.c → sha1/generic.c} +22 -10
  227. data/vendor/libgit2/src/hash/{hash_generic.h → sha1/generic.h} +4 -14
  228. data/vendor/libgit2/src/hash/{hash_mbedtls.c → sha1/mbedtls.c} +15 -7
  229. data/vendor/libgit2/src/hash/{hash_mbedtls.h → sha1/mbedtls.h} +6 -11
  230. data/vendor/libgit2/src/hash/{hash_openssl.h → sha1/openssl.c} +14 -18
  231. data/vendor/libgit2/src/hash/sha1/openssl.h +19 -0
  232. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.c +14 -3
  233. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.h +0 -0
  234. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.c +0 -0
  235. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.h +0 -0
  236. data/vendor/libgit2/src/hash/{hash_win32.c → sha1/win32.c} +34 -24
  237. data/vendor/libgit2/src/hash/{hash_win32.h → sha1/win32.h} +6 -19
  238. data/vendor/libgit2/src/hashsig.c +1 -1
  239. data/vendor/libgit2/src/idxmap.c +91 -65
  240. data/vendor/libgit2/src/idxmap.h +151 -15
  241. data/vendor/libgit2/src/ignore.c +32 -38
  242. data/vendor/libgit2/src/index.c +105 -83
  243. data/vendor/libgit2/src/index.h +1 -1
  244. data/vendor/libgit2/src/indexer.c +71 -72
  245. data/vendor/libgit2/src/integer.h +39 -4
  246. data/vendor/libgit2/src/iterator.c +40 -35
  247. data/vendor/libgit2/src/iterator.h +8 -8
  248. data/vendor/libgit2/src/map.h +1 -1
  249. data/vendor/libgit2/src/merge.c +78 -51
  250. data/vendor/libgit2/src/merge.h +2 -2
  251. data/vendor/libgit2/src/merge_driver.c +5 -5
  252. data/vendor/libgit2/src/merge_file.c +1 -1
  253. data/vendor/libgit2/src/mwindow.c +18 -23
  254. data/vendor/libgit2/src/mwindow.h +4 -4
  255. data/vendor/libgit2/src/net.c +411 -0
  256. data/vendor/libgit2/src/net.h +57 -0
  257. data/vendor/libgit2/src/netops.c +6 -193
  258. data/vendor/libgit2/src/netops.h +1 -34
  259. data/vendor/libgit2/src/notes.c +8 -5
  260. data/vendor/libgit2/src/object.c +3 -3
  261. data/vendor/libgit2/src/object.h +2 -0
  262. data/vendor/libgit2/src/odb.c +41 -23
  263. data/vendor/libgit2/src/odb.h +3 -2
  264. data/vendor/libgit2/src/odb_loose.c +17 -10
  265. data/vendor/libgit2/src/odb_mempack.c +13 -24
  266. data/vendor/libgit2/src/odb_pack.c +4 -5
  267. data/vendor/libgit2/src/offmap.c +43 -55
  268. data/vendor/libgit2/src/offmap.h +102 -24
  269. data/vendor/libgit2/src/oid.c +19 -8
  270. data/vendor/libgit2/src/oidmap.c +39 -57
  271. data/vendor/libgit2/src/oidmap.h +99 -19
  272. data/vendor/libgit2/src/pack-objects.c +28 -33
  273. data/vendor/libgit2/src/pack-objects.h +1 -1
  274. data/vendor/libgit2/src/pack.c +117 -129
  275. data/vendor/libgit2/src/pack.h +15 -18
  276. data/vendor/libgit2/src/parse.c +10 -0
  277. data/vendor/libgit2/src/parse.h +3 -3
  278. data/vendor/libgit2/src/patch.c +1 -1
  279. data/vendor/libgit2/src/patch_generate.c +2 -2
  280. data/vendor/libgit2/src/patch_parse.c +130 -33
  281. data/vendor/libgit2/src/path.c +43 -6
  282. data/vendor/libgit2/src/path.h +2 -0
  283. data/vendor/libgit2/src/pathspec.c +14 -14
  284. data/vendor/libgit2/src/pool.c +26 -22
  285. data/vendor/libgit2/src/pool.h +7 -7
  286. data/vendor/libgit2/src/posix.c +7 -7
  287. data/vendor/libgit2/src/posix.h +12 -1
  288. data/vendor/libgit2/src/proxy.c +7 -2
  289. data/vendor/libgit2/src/push.c +13 -7
  290. data/vendor/libgit2/src/reader.c +2 -2
  291. data/vendor/libgit2/src/rebase.c +87 -28
  292. data/vendor/libgit2/src/refdb.c +12 -0
  293. data/vendor/libgit2/src/refdb_fs.c +219 -167
  294. data/vendor/libgit2/src/reflog.c +11 -13
  295. data/vendor/libgit2/src/refs.c +39 -23
  296. data/vendor/libgit2/src/refs.h +8 -1
  297. data/vendor/libgit2/src/refspec.c +9 -16
  298. data/vendor/libgit2/src/regexp.c +221 -0
  299. data/vendor/libgit2/src/regexp.h +97 -0
  300. data/vendor/libgit2/src/remote.c +57 -55
  301. data/vendor/libgit2/src/remote.h +2 -2
  302. data/vendor/libgit2/src/repository.c +187 -154
  303. data/vendor/libgit2/src/repository.h +49 -40
  304. data/vendor/libgit2/src/revert.c +8 -3
  305. data/vendor/libgit2/src/revparse.c +18 -19
  306. data/vendor/libgit2/src/revwalk.c +72 -34
  307. data/vendor/libgit2/src/revwalk.h +20 -0
  308. data/vendor/libgit2/src/settings.c +13 -1
  309. data/vendor/libgit2/src/sortedcache.c +12 -26
  310. data/vendor/libgit2/src/sortedcache.h +1 -1
  311. data/vendor/libgit2/src/stash.c +47 -67
  312. data/vendor/libgit2/src/status.c +17 -11
  313. data/vendor/libgit2/src/streams/openssl.c +54 -2
  314. data/vendor/libgit2/src/streams/socket.c +2 -2
  315. data/vendor/libgit2/src/strmap.c +37 -84
  316. data/vendor/libgit2/src/strmap.h +105 -33
  317. data/vendor/libgit2/src/submodule.c +151 -126
  318. data/vendor/libgit2/src/submodule.h +1 -1
  319. data/vendor/libgit2/src/sysdir.c +11 -1
  320. data/vendor/libgit2/src/tag.c +10 -2
  321. data/vendor/libgit2/src/trace.c +1 -1
  322. data/vendor/libgit2/src/trace.h +3 -3
  323. data/vendor/libgit2/src/trailer.c +46 -32
  324. data/vendor/libgit2/src/transaction.c +10 -9
  325. data/vendor/libgit2/src/transports/auth.c +16 -15
  326. data/vendor/libgit2/src/transports/auth.h +18 -11
  327. data/vendor/libgit2/src/transports/auth_negotiate.c +64 -33
  328. data/vendor/libgit2/src/transports/auth_negotiate.h +2 -2
  329. data/vendor/libgit2/src/transports/auth_ntlm.c +223 -0
  330. data/vendor/libgit2/src/transports/auth_ntlm.h +38 -0
  331. data/vendor/libgit2/src/transports/credential.c +476 -0
  332. data/vendor/libgit2/src/transports/{cred_helpers.c → credential_helpers.c} +21 -8
  333. data/vendor/libgit2/src/transports/git.c +11 -16
  334. data/vendor/libgit2/src/transports/http.c +488 -1248
  335. data/vendor/libgit2/src/transports/http.h +4 -1
  336. data/vendor/libgit2/src/transports/httpclient.c +1549 -0
  337. data/vendor/libgit2/src/transports/httpclient.h +190 -0
  338. data/vendor/libgit2/src/transports/local.c +10 -10
  339. data/vendor/libgit2/src/transports/smart.c +19 -19
  340. data/vendor/libgit2/src/transports/smart.h +3 -3
  341. data/vendor/libgit2/src/transports/smart_pkt.c +1 -1
  342. data/vendor/libgit2/src/transports/smart_protocol.c +40 -64
  343. data/vendor/libgit2/src/transports/ssh.c +77 -59
  344. data/vendor/libgit2/src/transports/winhttp.c +272 -242
  345. data/vendor/libgit2/src/tree-cache.c +14 -7
  346. data/vendor/libgit2/src/tree.c +16 -26
  347. data/vendor/libgit2/src/unix/map.c +1 -1
  348. data/vendor/libgit2/src/unix/posix.h +2 -12
  349. data/vendor/libgit2/src/userdiff.h +3 -1
  350. data/vendor/libgit2/src/util.c +51 -53
  351. data/vendor/libgit2/src/util.h +16 -21
  352. data/vendor/libgit2/src/wildmatch.c +320 -0
  353. data/vendor/libgit2/src/wildmatch.h +23 -0
  354. data/vendor/libgit2/src/win32/map.c +3 -5
  355. data/vendor/libgit2/src/win32/path_w32.c +40 -3
  356. data/vendor/libgit2/src/win32/path_w32.h +15 -29
  357. data/vendor/libgit2/src/win32/posix.h +1 -4
  358. data/vendor/libgit2/src/win32/posix_w32.c +47 -5
  359. data/vendor/libgit2/src/win32/precompiled.h +0 -2
  360. data/vendor/libgit2/src/win32/thread.c +5 -10
  361. data/vendor/libgit2/src/win32/w32_buffer.c +7 -3
  362. data/vendor/libgit2/src/win32/w32_common.h +39 -0
  363. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +0 -93
  364. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -2
  365. data/vendor/libgit2/src/win32/w32_stack.c +4 -9
  366. data/vendor/libgit2/src/win32/w32_stack.h +3 -3
  367. data/vendor/libgit2/src/win32/w32_util.c +31 -0
  368. data/vendor/libgit2/src/win32/w32_util.h +6 -32
  369. data/vendor/libgit2/src/worktree.c +79 -49
  370. data/vendor/libgit2/src/xdiff/xdiffi.c +1 -1
  371. data/vendor/libgit2/src/xdiff/xmerge.c +12 -0
  372. data/vendor/libgit2/src/xdiff/xpatience.c +3 -0
  373. data/vendor/libgit2/src/zstream.c +5 -0
  374. data/vendor/libgit2/src/zstream.h +1 -0
  375. metadata +108 -41
  376. data/vendor/libgit2/deps/regex/CMakeLists.txt +0 -2
  377. data/vendor/libgit2/deps/regex/COPYING +0 -502
  378. data/vendor/libgit2/deps/regex/config.h +0 -7
  379. data/vendor/libgit2/deps/regex/regcomp.c +0 -3857
  380. data/vendor/libgit2/deps/regex/regex.c +0 -92
  381. data/vendor/libgit2/deps/regex/regex.h +0 -582
  382. data/vendor/libgit2/deps/regex/regex_internal.c +0 -1744
  383. data/vendor/libgit2/deps/regex/regex_internal.h +0 -819
  384. data/vendor/libgit2/deps/regex/regexec.c +0 -4369
  385. data/vendor/libgit2/include/git2/inttypes.h +0 -309
  386. data/vendor/libgit2/include/git2/sys/time.h +0 -31
  387. data/vendor/libgit2/libgit2.pc.in +0 -13
  388. data/vendor/libgit2/src/fnmatch.c +0 -248
  389. data/vendor/libgit2/src/fnmatch.h +0 -48
  390. data/vendor/libgit2/src/sha1_lookup.c +0 -35
  391. data/vendor/libgit2/src/transports/cred.c +0 -390
@@ -7,16 +7,16 @@
7
7
 
8
8
  #include "common.h"
9
9
 
10
- #include "git2/cred_helpers.h"
10
+ #include "git2/credential_helpers.h"
11
11
 
12
- int git_cred_userpass(
13
- git_cred **cred,
12
+ int git_credential_userpass(
13
+ git_credential **cred,
14
14
  const char *url,
15
15
  const char *user_from_url,
16
16
  unsigned int allowed_types,
17
17
  void *payload)
18
18
  {
19
- git_cred_userpass_payload *userpass = (git_cred_userpass_payload*)payload;
19
+ git_credential_userpass_payload *userpass = (git_credential_userpass_payload*)payload;
20
20
  const char *effective_username = NULL;
21
21
 
22
22
  GIT_UNUSED(url);
@@ -42,12 +42,25 @@ int git_cred_userpass(
42
42
  else
43
43
  return -1;
44
44
 
45
- if (GIT_CREDTYPE_USERNAME & allowed_types)
46
- return git_cred_username_new(cred, effective_username);
45
+ if (GIT_CREDENTIAL_USERNAME & allowed_types)
46
+ return git_credential_username_new(cred, effective_username);
47
47
 
48
- if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 ||
49
- git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
48
+ if ((GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) == 0 ||
49
+ git_credential_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
50
50
  return -1;
51
51
 
52
52
  return 0;
53
53
  }
54
+
55
+ /* Deprecated credential functions */
56
+
57
+ int git_cred_userpass(
58
+ git_credential **out,
59
+ const char *url,
60
+ const char *user_from_url,
61
+ unsigned int allowed_types,
62
+ void *payload)
63
+ {
64
+ return git_credential_userpass(out, url, user_from_url,
65
+ allowed_types, payload);
66
+ }
@@ -192,8 +192,9 @@ static int _git_uploadpack_ls(
192
192
  const char *url,
193
193
  git_smart_subtransport_stream **stream)
194
194
  {
195
- char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
195
+ git_net_url urldata = GIT_NET_URL_INIT;
196
196
  const char *stream_url = url;
197
+ const char *host, *port;
197
198
  git_proto_stream *s;
198
199
  int error;
199
200
 
@@ -202,17 +203,15 @@ static int _git_uploadpack_ls(
202
203
  if (!git__prefixcmp(url, prefix_git))
203
204
  stream_url += strlen(prefix_git);
204
205
 
205
- if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0)
206
+ if ((error = git_net_url_parse(&urldata, url)) < 0)
206
207
  return error;
207
208
 
208
- error = git_proto_stream_alloc(t, stream_url, cmd_uploadpack, host, port, stream);
209
+ host = urldata.host;
210
+ port = urldata.port ? urldata.port : GIT_DEFAULT_PORT;
209
211
 
210
- git__free(host);
211
- git__free(port);
212
- git__free(path);
213
- git__free(user);
214
- git__free(pass);
212
+ error = git_proto_stream_alloc(t, stream_url, cmd_uploadpack, host, port, stream);
215
213
 
214
+ git_net_url_dispose(&urldata);
216
215
 
217
216
  if (error < 0) {
218
217
  git_proto_stream_free(*stream);
@@ -251,7 +250,7 @@ static int _git_receivepack_ls(
251
250
  const char *url,
252
251
  git_smart_subtransport_stream **stream)
253
252
  {
254
- char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
253
+ git_net_url urldata = GIT_NET_URL_INIT;
255
254
  const char *stream_url = url;
256
255
  git_proto_stream *s;
257
256
  int error;
@@ -260,16 +259,12 @@ static int _git_receivepack_ls(
260
259
  if (!git__prefixcmp(url, prefix_git))
261
260
  stream_url += strlen(prefix_git);
262
261
 
263
- if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0)
262
+ if ((error = git_net_url_parse(&urldata, url)) < 0)
264
263
  return error;
265
264
 
266
- error = git_proto_stream_alloc(t, stream_url, cmd_receivepack, host, port, stream);
265
+ error = git_proto_stream_alloc(t, stream_url, cmd_receivepack, urldata.host, urldata.port, stream);
267
266
 
268
- git__free(host);
269
- git__free(port);
270
- git__free(path);
271
- git__free(user);
272
- git__free(pass);
267
+ git_net_url_dispose(&urldata);
273
268
 
274
269
  if (error < 0) {
275
270
  git_proto_stream_free(*stream);
@@ -12,1363 +12,635 @@
12
12
  #include "git2.h"
13
13
  #include "http_parser.h"
14
14
  #include "buffer.h"
15
+ #include "net.h"
15
16
  #include "netops.h"
16
17
  #include "global.h"
17
18
  #include "remote.h"
19
+ #include "git2/sys/credential.h"
18
20
  #include "smart.h"
19
21
  #include "auth.h"
20
22
  #include "http.h"
21
23
  #include "auth_negotiate.h"
24
+ #include "auth_ntlm.h"
25
+ #include "trace.h"
22
26
  #include "streams/tls.h"
23
27
  #include "streams/socket.h"
28
+ #include "httpclient.h"
24
29
 
25
- git_http_auth_scheme auth_schemes[] = {
26
- { GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
27
- { GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
28
- };
29
-
30
- static const char *upload_pack_service = "upload-pack";
31
- static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
32
- static const char *upload_pack_service_url = "/git-upload-pack";
33
- static const char *receive_pack_service = "receive-pack";
34
- static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive-pack";
35
- static const char *receive_pack_service_url = "/git-receive-pack";
36
- static const char *get_verb = "GET";
37
- static const char *post_verb = "POST";
38
-
39
- #define AUTH_HEADER_SERVER "Authorization"
40
- #define AUTH_HEADER_PROXY "Proxy-Authorization"
41
-
42
- #define SERVER_TYPE_REMOTE "remote"
43
- #define SERVER_TYPE_PROXY "proxy"
44
-
45
- #define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
30
+ bool git_http__expect_continue = false;
46
31
 
47
- #define PARSE_ERROR_GENERIC -1
48
- #define PARSE_ERROR_REPLAY -2
49
- /** Look at the user field */
50
- #define PARSE_ERROR_EXT -3
32
+ typedef enum {
33
+ HTTP_STATE_NONE = 0,
34
+ HTTP_STATE_SENDING_REQUEST,
35
+ HTTP_STATE_RECEIVING_RESPONSE,
36
+ HTTP_STATE_DONE
37
+ } http_state;
51
38
 
52
- #define CHUNK_SIZE 4096
53
-
54
- enum last_cb {
55
- NONE,
56
- FIELD,
57
- VALUE
58
- };
39
+ typedef struct {
40
+ git_http_method method;
41
+ const char *url;
42
+ const char *request_type;
43
+ const char *response_type;
44
+ unsigned chunked : 1;
45
+ } http_service;
59
46
 
60
47
  typedef struct {
61
48
  git_smart_subtransport_stream parent;
62
- const char *service;
63
- const char *service_url;
64
- char *redirect_url;
65
- const char *verb;
66
- char *chunk_buffer;
67
- unsigned chunk_buffer_len;
68
- unsigned sent_request : 1,
69
- received_response : 1,
70
- chunked : 1;
49
+ const http_service *service;
50
+ http_state state;
51
+ unsigned replay_count;
71
52
  } http_stream;
72
53
 
73
54
  typedef struct {
74
- gitno_connection_data url;
75
- git_stream *stream;
76
-
77
- git_cred *cred;
78
- git_cred *url_cred;
55
+ git_net_url url;
79
56
 
80
- git_vector auth_challenges;
81
- git_vector auth_contexts;
57
+ git_credential *cred;
58
+ unsigned auth_schemetypes;
59
+ unsigned url_cred_presented : 1;
82
60
  } http_server;
83
61
 
84
62
  typedef struct {
85
63
  git_smart_subtransport parent;
86
64
  transport_smart *owner;
87
- git_stream *gitserver_stream;
88
- bool connected;
89
65
 
90
66
  http_server server;
91
-
92
67
  http_server proxy;
93
- char *proxy_url;
94
- git_proxy_options proxy_opts;
95
-
96
- /* Parser structures */
97
- http_parser parser;
98
- http_parser_settings settings;
99
- gitno_buffer parse_buffer;
100
- git_buf parse_header_name;
101
- git_buf parse_header_value;
102
- char parse_buffer_data[NETIO_BUFSIZE];
103
- char *content_type;
104
- char *content_length;
105
- char *location;
106
- enum last_cb last_cb;
107
- int parse_error;
108
- int error;
109
- unsigned parse_finished : 1,
110
- replay_count : 3;
68
+
69
+ git_http_client *http_client;
111
70
  } http_subtransport;
112
71
 
113
- typedef struct {
114
- http_stream *s;
115
- http_subtransport *t;
72
+ static const http_service upload_pack_ls_service = {
73
+ GIT_HTTP_METHOD_GET, "/info/refs?service=git-upload-pack",
74
+ NULL,
75
+ "application/x-git-upload-pack-advertisement",
76
+ 0
77
+ };
78
+ static const http_service upload_pack_service = {
79
+ GIT_HTTP_METHOD_POST, "/git-upload-pack",
80
+ "application/x-git-upload-pack-request",
81
+ "application/x-git-upload-pack-result",
82
+ 0
83
+ };
84
+ static const http_service receive_pack_ls_service = {
85
+ GIT_HTTP_METHOD_GET, "/info/refs?service=git-receive-pack",
86
+ NULL,
87
+ "application/x-git-receive-pack-advertisement",
88
+ 0
89
+ };
90
+ static const http_service receive_pack_service = {
91
+ GIT_HTTP_METHOD_POST, "/git-receive-pack",
92
+ "application/x-git-receive-pack-request",
93
+ "application/x-git-receive-pack-result",
94
+ 1
95
+ };
96
+
97
+ #define SERVER_TYPE_REMOTE "remote"
98
+ #define SERVER_TYPE_PROXY "proxy"
116
99
 
117
- /* Target buffer details from read() */
118
- char *buffer;
119
- size_t buf_size;
120
- size_t *bytes_read;
121
- } parser_context;
100
+ #define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
122
101
 
123
- static bool credtype_match(git_http_auth_scheme *scheme, void *data)
102
+ static int apply_url_credentials(
103
+ git_credential **cred,
104
+ unsigned int allowed_types,
105
+ const char *username,
106
+ const char *password)
124
107
  {
125
- unsigned int credtype = *(unsigned int *)data;
108
+ if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT)
109
+ return git_credential_userpass_plaintext_new(cred, username, password);
110
+
111
+ if ((allowed_types & GIT_CREDENTIAL_DEFAULT) && *username == '\0' && *password == '\0')
112
+ return git_credential_default_new(cred);
126
113
 
127
- return !!(scheme->credtypes & credtype);
114
+ return GIT_PASSTHROUGH;
128
115
  }
129
116
 
130
- static bool challenge_match(git_http_auth_scheme *scheme, void *data)
117
+ GIT_INLINE(void) free_cred(git_credential **cred)
131
118
  {
132
- const char *scheme_name = scheme->name;
133
- const char *challenge = (const char *)data;
134
- size_t scheme_len;
135
-
136
- scheme_len = strlen(scheme_name);
137
- return (strncasecmp(challenge, scheme_name, scheme_len) == 0 &&
138
- (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
119
+ if (*cred) {
120
+ git_credential_free(*cred);
121
+ (*cred) = NULL;
122
+ }
139
123
  }
140
124
 
141
- static int auth_context_match(
142
- git_http_auth_context **out,
125
+ static int handle_auth(
143
126
  http_server *server,
144
- bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
145
- void *data)
127
+ const char *server_type,
128
+ const char *url,
129
+ unsigned int allowed_schemetypes,
130
+ unsigned int allowed_credtypes,
131
+ git_credential_acquire_cb callback,
132
+ void *callback_payload)
146
133
  {
147
- git_http_auth_scheme *scheme = NULL;
148
- git_http_auth_context *context = NULL, *c;
149
- size_t i;
134
+ int error = 1;
150
135
 
151
- *out = NULL;
136
+ if (server->cred)
137
+ free_cred(&server->cred);
152
138
 
153
- for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
154
- if (scheme_match(&auth_schemes[i], data)) {
155
- scheme = &auth_schemes[i];
156
- break;
157
- }
139
+ /* Start with URL-specified credentials, if there were any. */
140
+ if ((allowed_credtypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT) &&
141
+ !server->url_cred_presented &&
142
+ server->url.username &&
143
+ server->url.password) {
144
+ error = apply_url_credentials(&server->cred, allowed_credtypes, server->url.username, server->url.password);
145
+ server->url_cred_presented = 1;
146
+
147
+ /* treat GIT_PASSTHROUGH as if callback isn't set */
148
+ if (error == GIT_PASSTHROUGH)
149
+ error = 1;
158
150
  }
159
151
 
160
- if (!scheme)
161
- return 0;
152
+ if (error > 0 && callback) {
153
+ error = callback(&server->cred, url, server->url.username, allowed_credtypes, callback_payload);
162
154
 
163
- /* See if authentication has already started for this scheme */
164
- git_vector_foreach(&server->auth_contexts, i, c) {
165
- if (c->type == scheme->type) {
166
- context = c;
167
- break;
168
- }
155
+ /* treat GIT_PASSTHROUGH as if callback isn't set */
156
+ if (error == GIT_PASSTHROUGH)
157
+ error = 1;
169
158
  }
170
159
 
171
- if (!context) {
172
- if (scheme->init_context(&context, &server->url) < 0)
173
- return -1;
174
- else if (!context)
175
- return 0;
176
- else if (git_vector_insert(&server->auth_contexts, context) < 0)
177
- return -1;
160
+ if (error > 0) {
161
+ git_error_set(GIT_ERROR_HTTP, "%s authentication required but no callback set", server_type);
162
+ error = -1;
178
163
  }
179
164
 
180
- *out = context;
165
+ if (!error)
166
+ server->auth_schemetypes = allowed_schemetypes;
181
167
 
182
- return 0;
168
+ return error;
183
169
  }
184
170
 
185
- static int apply_credentials(
186
- git_buf *buf,
187
- http_server *server,
188
- const char *header_name)
171
+ GIT_INLINE(int) handle_remote_auth(
172
+ http_stream *stream,
173
+ git_http_response *response)
189
174
  {
190
- git_cred *cred = server->cred;
191
- git_http_auth_context *context;
192
-
193
- /* Apply the credentials given to us in the URL */
194
- if (!cred && server->url.user && server->url.pass) {
195
- if (!server->url_cred &&
196
- git_cred_userpass_plaintext_new(&server->url_cred,
197
- server->url.user, server->url.pass) < 0)
198
- return -1;
199
-
200
- cred = server->url_cred;
201
- }
175
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
202
176
 
203
- if (!cred)
204
- return 0;
205
-
206
- /* Get or create a context for the best scheme for this cred type */
207
- if (auth_context_match(&context, server,
208
- credtype_match, &cred->credtype) < 0)
177
+ if (response->server_auth_credtypes == 0) {
178
+ git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
209
179
  return -1;
210
-
211
- if (!context)
212
- return 0;
213
-
214
- return context->next_token(buf, context, header_name, cred);
215
- }
216
-
217
- static int gen_request(
218
- git_buf *buf,
219
- http_stream *s,
220
- size_t content_length)
221
- {
222
- http_subtransport *t = OWNING_SUBTRANSPORT(s);
223
- const char *path = t->server.url.path ? t->server.url.path : "/";
224
- size_t i;
225
-
226
- if (t->proxy_opts.type == GIT_PROXY_SPECIFIED)
227
- git_buf_printf(buf, "%s %s://%s:%s%s%s HTTP/1.1\r\n",
228
- s->verb,
229
- t->server.url.use_ssl ? "https" : "http",
230
- t->server.url.host,
231
- t->server.url.port,
232
- path, s->service_url);
233
- else
234
- git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n",
235
- s->verb, path, s->service_url);
236
-
237
- git_buf_puts(buf, "User-Agent: ");
238
- git_http__user_agent(buf);
239
- git_buf_puts(buf, "\r\n");
240
- git_buf_printf(buf, "Host: %s", t->server.url.host);
241
- if (strcmp(t->server.url.port, gitno__default_port(&t->server.url)) != 0) {
242
- git_buf_printf(buf, ":%s", t->server.url.port);
243
180
  }
244
- git_buf_puts(buf, "\r\n");
245
-
246
- if (s->chunked || content_length > 0) {
247
- git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service);
248
- git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", s->service);
249
-
250
- if (s->chunked)
251
- git_buf_puts(buf, "Transfer-Encoding: chunked\r\n");
252
- else
253
- git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length);
254
- } else
255
- git_buf_puts(buf, "Accept: */*\r\n");
256
-
257
- for (i = 0; i < t->owner->custom_headers.count; i++) {
258
- if (t->owner->custom_headers.strings[i])
259
- git_buf_printf(buf, "%s\r\n", t->owner->custom_headers.strings[i]);
260
- }
261
-
262
- /* Apply proxy and server credentials to the request */
263
- if (t->proxy_opts.type != GIT_PROXY_NONE &&
264
- apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0)
265
- return -1;
266
181
 
267
- if (apply_credentials(buf, &t->server, AUTH_HEADER_SERVER) < 0)
268
- return -1;
269
-
270
- git_buf_puts(buf, "\r\n");
271
-
272
- if (git_buf_oom(buf))
273
- return -1;
274
-
275
- return 0;
182
+ /* Otherwise, prompt for credentials. */
183
+ return handle_auth(
184
+ &transport->server,
185
+ SERVER_TYPE_REMOTE,
186
+ transport->owner->url,
187
+ response->server_auth_schemetypes,
188
+ response->server_auth_credtypes,
189
+ transport->owner->cred_acquire_cb,
190
+ transport->owner->cred_acquire_payload);
276
191
  }
277
192
 
278
- static int parse_authenticate_response(
279
- http_server *server,
280
- int *allowed_types)
193
+ GIT_INLINE(int) handle_proxy_auth(
194
+ http_stream *stream,
195
+ git_http_response *response)
281
196
  {
282
- git_http_auth_context *context;
283
- char *challenge;
284
- size_t i;
197
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
285
198
 
286
- git_vector_foreach(&server->auth_challenges, i, challenge) {
287
- if (auth_context_match(&context, server,
288
- challenge_match, challenge) < 0)
289
- return -1;
290
- else if (!context)
291
- continue;
292
-
293
- if (context->set_challenge &&
294
- context->set_challenge(context, challenge) < 0)
295
- return -1;
296
-
297
- *allowed_types |= context->credtypes;
199
+ if (response->proxy_auth_credtypes == 0) {
200
+ git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
201
+ return -1;
298
202
  }
299
203
 
300
- return 0;
204
+ /* Otherwise, prompt for credentials. */
205
+ return handle_auth(
206
+ &transport->proxy,
207
+ SERVER_TYPE_PROXY,
208
+ transport->owner->proxy.url,
209
+ response->server_auth_schemetypes,
210
+ response->proxy_auth_credtypes,
211
+ transport->owner->proxy.credentials,
212
+ transport->owner->proxy.payload);
301
213
  }
302
214
 
303
- static int on_header_ready(http_subtransport *t)
215
+
216
+ static int handle_response(
217
+ bool *complete,
218
+ http_stream *stream,
219
+ git_http_response *response,
220
+ bool allow_replay)
304
221
  {
305
- git_buf *name = &t->parse_header_name;
306
- git_buf *value = &t->parse_header_value;
222
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
223
+ int error;
307
224
 
308
- if (!strcasecmp("Content-Type", git_buf_cstr(name))) {
309
- if (t->content_type) {
310
- git_error_set(GIT_ERROR_NET, "multiple Content-Type headers");
311
- return -1;
312
- }
225
+ *complete = false;
313
226
 
314
- t->content_type = git__strdup(git_buf_cstr(value));
315
- GIT_ERROR_CHECK_ALLOC(t->content_type);
316
- }
317
- else if (!strcasecmp("Content-Length", git_buf_cstr(name))) {
318
- if (t->content_length) {
319
- git_error_set(GIT_ERROR_NET, "multiple Content-Length headers");
227
+ if (allow_replay && git_http_response_is_redirect(response)) {
228
+ if (!response->location) {
229
+ git_error_set(GIT_ERROR_HTTP, "redirect without location");
320
230
  return -1;
321
231
  }
322
232
 
323
- t->content_length = git__strdup(git_buf_cstr(value));
324
- GIT_ERROR_CHECK_ALLOC(t->content_length);
325
- }
326
- else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) {
327
- char *dup = git__strdup(git_buf_cstr(value));
328
- GIT_ERROR_CHECK_ALLOC(dup);
329
-
330
- if (git_vector_insert(&t->proxy.auth_challenges, dup) < 0)
331
- return -1;
332
- }
333
- else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) {
334
- char *dup = git__strdup(git_buf_cstr(value));
335
- GIT_ERROR_CHECK_ALLOC(dup);
336
-
337
- if (git_vector_insert(&t->server.auth_challenges, dup) < 0)
338
- return -1;
339
- }
340
- else if (!strcasecmp("Location", git_buf_cstr(name))) {
341
- if (t->location) {
342
- git_error_set(GIT_ERROR_NET, "multiple Location headers");
233
+ if (git_net_url_apply_redirect(&transport->server.url, response->location, stream->service->url) < 0) {
343
234
  return -1;
344
235
  }
345
236
 
346
- t->location = git__strdup(git_buf_cstr(value));
347
- GIT_ERROR_CHECK_ALLOC(t->location);
348
- }
349
-
350
- return 0;
351
- }
352
-
353
- static int on_header_field(http_parser *parser, const char *str, size_t len)
354
- {
355
- parser_context *ctx = (parser_context *) parser->data;
356
- http_subtransport *t = ctx->t;
357
-
358
- /* Both parse_header_name and parse_header_value are populated
359
- * and ready for consumption */
360
- if (VALUE == t->last_cb)
361
- if (on_header_ready(t) < 0)
362
- return t->parse_error = PARSE_ERROR_GENERIC;
363
-
364
- if (NONE == t->last_cb || VALUE == t->last_cb)
365
- git_buf_clear(&t->parse_header_name);
366
-
367
- if (git_buf_put(&t->parse_header_name, str, len) < 0)
368
- return t->parse_error = PARSE_ERROR_GENERIC;
369
-
370
- t->last_cb = FIELD;
371
- return 0;
372
- }
373
-
374
- static int on_header_value(http_parser *parser, const char *str, size_t len)
375
- {
376
- parser_context *ctx = (parser_context *) parser->data;
377
- http_subtransport *t = ctx->t;
378
-
379
- assert(NONE != t->last_cb);
380
-
381
- if (FIELD == t->last_cb)
382
- git_buf_clear(&t->parse_header_value);
383
-
384
- if (git_buf_put(&t->parse_header_value, str, len) < 0)
385
- return t->parse_error = PARSE_ERROR_GENERIC;
386
-
387
- t->last_cb = VALUE;
388
- return 0;
389
- }
390
-
391
- GIT_INLINE(void) free_cred(git_cred **cred)
392
- {
393
- if (*cred) {
394
- git_cred_free(*cred);
395
- (*cred) = NULL;
396
- }
397
- }
398
-
399
- static int on_auth_required(
400
- git_cred **creds,
401
- http_parser *parser,
402
- const char *url,
403
- const char *type,
404
- git_cred_acquire_cb callback,
405
- void *callback_payload,
406
- const char *username,
407
- int allowed_types)
408
- {
409
- parser_context *ctx = (parser_context *) parser->data;
410
- http_subtransport *t = ctx->t;
411
- int ret;
412
-
413
- if (!allowed_types) {
414
- git_error_set(GIT_ERROR_NET, "%s requested authentication but did not negotiate mechanisms", type);
415
- t->parse_error = PARSE_ERROR_GENERIC;
416
- return t->parse_error;
417
- }
418
-
419
- if (callback) {
420
- free_cred(creds);
421
- ret = callback(creds, url, username, allowed_types, callback_payload);
422
-
423
- if (ret == GIT_PASSTHROUGH) {
424
- /* treat GIT_PASSTHROUGH as if callback isn't set */
425
- } else if (ret < 0) {
426
- t->error = ret;
427
- t->parse_error = PARSE_ERROR_EXT;
428
- return t->parse_error;
429
- } else {
430
- assert(*creds);
431
-
432
- if (!((*creds)->credtype & allowed_types)) {
433
- git_error_set(GIT_ERROR_NET, "%s credential provider returned an invalid cred type", type);
434
- t->parse_error = PARSE_ERROR_GENERIC;
435
- return t->parse_error;
436
- }
437
-
438
- /* Successfully acquired a credential. */
439
- t->parse_error = PARSE_ERROR_REPLAY;
440
- return 0;
441
- }
237
+ return 0;
238
+ } else if (git_http_response_is_redirect(response)) {
239
+ git_error_set(GIT_ERROR_HTTP, "unexpected redirect");
240
+ return -1;
442
241
  }
443
242
 
444
- git_error_set(GIT_ERROR_NET, "%s authentication required but no callback set",
445
- type);
446
- t->parse_error = PARSE_ERROR_GENERIC;
447
- return t->parse_error;
448
- }
449
-
450
- static int on_headers_complete(http_parser *parser)
451
- {
452
- parser_context *ctx = (parser_context *) parser->data;
453
- http_subtransport *t = ctx->t;
454
- http_stream *s = ctx->s;
455
- git_buf buf = GIT_BUF_INIT;
456
- int proxy_auth_types = 0, server_auth_types = 0;
457
-
458
- /* Enforce a reasonable cap on the number of replays */
459
- if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) {
460
- git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
461
- return t->parse_error = PARSE_ERROR_GENERIC;
462
- }
243
+ /* If we're in the middle of challenge/response auth, continue. */
244
+ if (allow_replay && response->resend_credentials) {
245
+ return 0;
246
+ } else if (allow_replay && response->status == GIT_HTTP_STATUS_UNAUTHORIZED) {
247
+ if ((error = handle_remote_auth(stream, response)) < 0)
248
+ return error;
463
249
 
464
- /* Both parse_header_name and parse_header_value are populated
465
- * and ready for consumption. */
466
- if (VALUE == t->last_cb)
467
- if (on_header_ready(t) < 0)
468
- return t->parse_error = PARSE_ERROR_GENERIC;
250
+ return git_http_client_skip_body(transport->http_client);
251
+ } else if (allow_replay && response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
252
+ if ((error = handle_proxy_auth(stream, response)) < 0)
253
+ return error;
469
254
 
470
- /*
471
- * Capture authentication headers for the proxy or final endpoint,
472
- * these may be 407/401 (authentication is not complete) or a 200
473
- * (informing us that auth has completed).
474
- */
475
- if (parse_authenticate_response(&t->proxy, &proxy_auth_types) < 0 ||
476
- parse_authenticate_response(&t->server, &server_auth_types) < 0)
477
- return t->parse_error = PARSE_ERROR_GENERIC;
478
-
479
- /* Check for a proxy authentication failure. */
480
- if (parser->status_code == 407 && get_verb == s->verb)
481
- return on_auth_required(&t->proxy.cred,
482
- parser,
483
- t->proxy_opts.url,
484
- SERVER_TYPE_PROXY,
485
- t->proxy_opts.credentials,
486
- t->proxy_opts.payload,
487
- t->proxy.url.user,
488
- proxy_auth_types);
489
-
490
- /* Check for an authentication failure. */
491
- if (parser->status_code == 401 && get_verb == s->verb)
492
- return on_auth_required(&t->server.cred,
493
- parser,
494
- t->owner->url,
495
- SERVER_TYPE_REMOTE,
496
- t->owner->cred_acquire_cb,
497
- t->owner->cred_acquire_payload,
498
- t->server.url.user,
499
- server_auth_types);
500
-
501
- /* Check for a redirect.
502
- * Right now we only permit a redirect to the same hostname. */
503
- if ((parser->status_code == 301 ||
504
- parser->status_code == 302 ||
505
- (parser->status_code == 303 && get_verb == s->verb) ||
506
- parser->status_code == 307 ||
507
- parser->status_code == 308) &&
508
- t->location) {
509
-
510
- if (gitno_connection_data_from_url(&t->server.url, t->location, s->service_url) < 0)
511
- return t->parse_error = PARSE_ERROR_GENERIC;
512
-
513
- /* Set the redirect URL on the stream. This is a transfer of
514
- * ownership of the memory. */
515
- if (s->redirect_url)
516
- git__free(s->redirect_url);
517
-
518
- s->redirect_url = t->location;
519
- t->location = NULL;
520
-
521
- t->connected = 0;
522
- t->parse_error = PARSE_ERROR_REPLAY;
523
- return 0;
255
+ return git_http_client_skip_body(transport->http_client);
256
+ } else if (response->status == GIT_HTTP_STATUS_UNAUTHORIZED ||
257
+ response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
258
+ git_error_set(GIT_ERROR_HTTP, "unexpected authentication failure");
259
+ return -1;
524
260
  }
525
261
 
526
- /* Check for a 200 HTTP status code. */
527
- if (parser->status_code != 200) {
528
- git_error_set(GIT_ERROR_NET,
529
- "unexpected HTTP status code: %d",
530
- parser->status_code);
531
- return t->parse_error = PARSE_ERROR_GENERIC;
262
+ if (response->status != GIT_HTTP_STATUS_OK) {
263
+ git_error_set(GIT_ERROR_HTTP, "unexpected http status code: %d", response->status);
264
+ return -1;
532
265
  }
533
266
 
534
267
  /* The response must contain a Content-Type header. */
535
- if (!t->content_type) {
536
- git_error_set(GIT_ERROR_NET, "no Content-Type header in response");
537
- return t->parse_error = PARSE_ERROR_GENERIC;
268
+ if (!response->content_type) {
269
+ git_error_set(GIT_ERROR_HTTP, "no content-type header in response");
270
+ return -1;
538
271
  }
539
272
 
540
273
  /* The Content-Type header must match our expectation. */
541
- if (get_verb == s->verb)
542
- git_buf_printf(&buf,
543
- "application/x-git-%s-advertisement",
544
- ctx->s->service);
545
- else
546
- git_buf_printf(&buf,
547
- "application/x-git-%s-result",
548
- ctx->s->service);
549
-
550
- if (git_buf_oom(&buf))
551
- return t->parse_error = PARSE_ERROR_GENERIC;
552
-
553
- if (strcmp(t->content_type, git_buf_cstr(&buf))) {
554
- git_buf_dispose(&buf);
555
- git_error_set(GIT_ERROR_NET,
556
- "invalid Content-Type: %s",
557
- t->content_type);
558
- return t->parse_error = PARSE_ERROR_GENERIC;
274
+ if (strcmp(response->content_type, stream->service->response_type) != 0) {
275
+ git_error_set(GIT_ERROR_HTTP, "invalid content-type: '%s'", response->content_type);
276
+ return -1;
559
277
  }
560
278
 
561
- git_buf_dispose(&buf);
562
-
279
+ *complete = true;
280
+ stream->state = HTTP_STATE_RECEIVING_RESPONSE;
563
281
  return 0;
564
282
  }
565
283
 
566
- static int on_message_complete(http_parser *parser)
284
+ static int lookup_proxy(
285
+ bool *out_use,
286
+ http_subtransport *transport)
567
287
  {
568
- parser_context *ctx = (parser_context *) parser->data;
569
- http_subtransport *t = ctx->t;
288
+ const char *proxy;
289
+ git_remote *remote;
290
+ bool use_ssl;
291
+ char *config = NULL;
292
+ int error = 0;
570
293
 
571
- t->parse_finished = 1;
294
+ *out_use = false;
295
+ git_net_url_dispose(&transport->proxy.url);
572
296
 
573
- return 0;
574
- }
575
-
576
- static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
577
- {
578
- parser_context *ctx = (parser_context *) parser->data;
579
- http_subtransport *t = ctx->t;
580
-
581
- /* If our goal is to replay the request (either an auth failure or
582
- * a redirect) then don't bother buffering since we're ignoring the
583
- * content anyway.
584
- */
585
- if (t->parse_error == PARSE_ERROR_REPLAY)
586
- return 0;
587
-
588
- /* If there's no buffer set, we're explicitly ignoring the body. */
589
- if (ctx->buffer) {
590
- if (ctx->buf_size < len) {
591
- git_error_set(GIT_ERROR_NET, "can't fit data in the buffer");
592
- return t->parse_error = PARSE_ERROR_GENERIC;
593
- }
594
-
595
- memcpy(ctx->buffer, str, len);
596
- ctx->buffer += len;
597
- ctx->buf_size -= len;
598
- }
599
-
600
- *(ctx->bytes_read) += len;
601
-
602
- return 0;
603
- }
297
+ switch (transport->owner->proxy.type) {
298
+ case GIT_PROXY_SPECIFIED:
299
+ proxy = transport->owner->proxy.url;
300
+ break;
604
301
 
605
- static void clear_parser_state(http_subtransport *t)
606
- {
607
- http_parser_init(&t->parser, HTTP_RESPONSE);
608
- gitno_buffer_setup_fromstream(t->server.stream,
609
- &t->parse_buffer,
610
- t->parse_buffer_data,
611
- sizeof(t->parse_buffer_data));
302
+ case GIT_PROXY_AUTO:
303
+ remote = transport->owner->owner;
304
+ use_ssl = !strcmp(transport->server.url.scheme, "https");
612
305
 
613
- t->last_cb = NONE;
614
- t->parse_error = 0;
615
- t->parse_finished = 0;
306
+ error = git_remote__get_http_proxy(remote, use_ssl, &config);
616
307
 
617
- git_buf_dispose(&t->parse_header_name);
618
- git_buf_init(&t->parse_header_name, 0);
308
+ if (error || !config)
309
+ goto done;
619
310
 
620
- git_buf_dispose(&t->parse_header_value);
621
- git_buf_init(&t->parse_header_value, 0);
311
+ proxy = config;
312
+ break;
622
313
 
623
- git__free(t->content_type);
624
- t->content_type = NULL;
314
+ default:
315
+ return 0;
316
+ }
625
317
 
626
- git__free(t->content_length);
627
- t->content_length = NULL;
318
+ if (!proxy ||
319
+ (error = git_net_url_parse(&transport->proxy.url, proxy)) < 0)
320
+ goto done;
628
321
 
629
- git__free(t->location);
630
- t->location = NULL;
322
+ *out_use = true;
631
323
 
632
- git_vector_free_deep(&t->proxy.auth_challenges);
633
- git_vector_free_deep(&t->server.auth_challenges);
324
+ done:
325
+ git__free(config);
326
+ return error;
634
327
  }
635
328
 
636
- static int write_chunk(git_stream *io, const char *buffer, size_t len)
329
+ static int generate_request(
330
+ git_net_url *url,
331
+ git_http_request *request,
332
+ http_stream *stream,
333
+ size_t len)
637
334
  {
638
- git_buf buf = GIT_BUF_INIT;
335
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
336
+ bool use_proxy = false;
337
+ int error;
639
338
 
640
- /* Chunk header */
641
- git_buf_printf(&buf, "%" PRIxZ "\r\n", len);
339
+ if ((error = git_net_url_joinpath(url,
340
+ &transport->server.url, stream->service->url)) < 0 ||
341
+ (error = lookup_proxy(&use_proxy, transport)) < 0)
342
+ return error;
642
343
 
643
- if (git_buf_oom(&buf))
644
- return -1;
344
+ request->method = stream->service->method;
345
+ request->url = url;
346
+ request->credentials = transport->server.cred;
347
+ request->proxy = use_proxy ? &transport->proxy.url : NULL;
348
+ request->proxy_credentials = transport->proxy.cred;
349
+ request->custom_headers = &transport->owner->custom_headers;
645
350
 
646
- if (git_stream__write_full(io, buf.ptr, buf.size, 0) < 0) {
647
- git_buf_dispose(&buf);
648
- return -1;
351
+ if (stream->service->method == GIT_HTTP_METHOD_POST) {
352
+ request->chunked = stream->service->chunked;
353
+ request->content_length = stream->service->chunked ? 0 : len;
354
+ request->content_type = stream->service->request_type;
355
+ request->accept = stream->service->response_type;
356
+ request->expect_continue = git_http__expect_continue;
649
357
  }
650
358
 
651
- git_buf_dispose(&buf);
652
-
653
- /* Chunk body */
654
- if (len > 0 && git_stream__write_full(io, buffer, len, 0) < 0)
655
- return -1;
656
-
657
- /* Chunk footer */
658
- if (git_stream__write_full(io, "\r\n", 2, 0) < 0)
659
- return -1;
660
-
661
359
  return 0;
662
360
  }
663
361
 
664
- static int load_proxy_config(http_subtransport *t)
665
- {
362
+ /*
363
+ * Read from an HTTP transport - for the first invocation of this function
364
+ * (ie, when stream->state == HTTP_STATE_NONE), we'll send a GET request
365
+ * to the remote host. We will stream that data back on all subsequent
366
+ * calls.
367
+ */
368
+ static int http_stream_read(
369
+ git_smart_subtransport_stream *s,
370
+ char *buffer,
371
+ size_t buffer_size,
372
+ size_t *out_len)
373
+ {
374
+ http_stream *stream = (http_stream *)s;
375
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
376
+ git_net_url url = GIT_NET_URL_INIT;
377
+ git_net_url proxy_url = GIT_NET_URL_INIT;
378
+ git_http_request request = {0};
379
+ git_http_response response = {0};
380
+ bool complete;
666
381
  int error;
667
382
 
668
- switch (t->owner->proxy.type) {
669
- case GIT_PROXY_NONE:
670
- return 0;
671
-
672
- case GIT_PROXY_AUTO:
673
- git__free(t->proxy_url);
674
- t->proxy_url = NULL;
675
-
676
- git_proxy_init_options(&t->proxy_opts, GIT_PROXY_OPTIONS_VERSION);
383
+ *out_len = 0;
677
384
 
678
- if ((error = git_remote__get_http_proxy(t->owner->owner,
679
- !!t->server.url.use_ssl, &t->proxy_url)) < 0)
680
- return error;
681
-
682
- if (!t->proxy_url)
683
- return 0;
385
+ if (stream->state == HTTP_STATE_NONE) {
386
+ stream->state = HTTP_STATE_SENDING_REQUEST;
387
+ stream->replay_count = 0;
388
+ }
684
389
 
685
- t->proxy_opts.type = GIT_PROXY_SPECIFIED;
686
- t->proxy_opts.url = t->proxy_url;
687
- t->proxy_opts.credentials = t->owner->proxy.credentials;
688
- t->proxy_opts.certificate_check = t->owner->proxy.certificate_check;
689
- t->proxy_opts.payload = t->owner->proxy.payload;
690
- break;
390
+ /*
391
+ * Formulate the URL, send the request and read the response
392
+ * headers. Some of the request body may also be read.
393
+ */
394
+ while (stream->state == HTTP_STATE_SENDING_REQUEST &&
395
+ stream->replay_count < GIT_HTTP_REPLAY_MAX) {
396
+ git_net_url_dispose(&url);
397
+ git_net_url_dispose(&proxy_url);
398
+ git_http_response_dispose(&response);
399
+
400
+ if ((error = generate_request(&url, &request, stream, 0)) < 0 ||
401
+ (error = git_http_client_send_request(
402
+ transport->http_client, &request)) < 0 ||
403
+ (error = git_http_client_read_response(
404
+ &response, transport->http_client)) < 0 ||
405
+ (error = handle_response(&complete, stream, &response, true)) < 0)
406
+ goto done;
691
407
 
692
- case GIT_PROXY_SPECIFIED:
693
- memcpy(&t->proxy_opts, &t->owner->proxy, sizeof(git_proxy_options));
694
- break;
408
+ if (complete)
409
+ break;
695
410
 
696
- default:
697
- assert(0);
698
- return -1;
411
+ stream->replay_count++;
699
412
  }
700
413
 
701
- if ((error = gitno_connection_data_from_url(&t->proxy.url, t->proxy_opts.url, NULL)) < 0)
702
- return error;
703
-
704
- if (t->proxy.url.use_ssl) {
705
- git_error_set(GIT_ERROR_NET, "SSL connections to proxy are not supported");
706
- return -1;
414
+ if (stream->state == HTTP_STATE_SENDING_REQUEST) {
415
+ git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays");
416
+ error = -1;
417
+ goto done;
707
418
  }
708
419
 
709
- return error;
710
- }
711
-
712
- static int check_certificate(
713
- git_stream *stream,
714
- gitno_connection_data *url,
715
- int is_valid,
716
- git_transport_certificate_check_cb cert_cb,
717
- void *cert_cb_payload)
718
- {
719
- git_cert *cert;
720
- git_error_state last_error = {0};
721
- int error;
722
-
723
- if ((error = git_stream_certificate(&cert, stream)) < 0)
724
- return error;
725
-
726
- git_error_state_capture(&last_error, GIT_ECERTIFICATE);
420
+ assert (stream->state == HTTP_STATE_RECEIVING_RESPONSE);
727
421
 
728
- error = cert_cb(cert, is_valid, url->host, cert_cb_payload);
422
+ error = git_http_client_read_body(transport->http_client, buffer, buffer_size);
729
423
 
730
- if (error == GIT_PASSTHROUGH && !is_valid)
731
- return git_error_state_restore(&last_error);
732
- else if (error == GIT_PASSTHROUGH)
424
+ if (error > 0) {
425
+ *out_len = error;
733
426
  error = 0;
734
- else if (error && !git_error_last())
735
- git_error_set(GIT_ERROR_NET, "user rejected certificate for %s", url->host);
736
-
737
- git_error_state_free(&last_error);
738
- return error;
739
- }
740
-
741
- static int stream_connect(
742
- git_stream *stream,
743
- gitno_connection_data *url,
744
- git_transport_certificate_check_cb cert_cb,
745
- void *cb_payload)
746
- {
747
- int error;
748
-
749
- GIT_ERROR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
750
-
751
- error = git_stream_connect(stream);
752
-
753
- if (error && error != GIT_ECERTIFICATE)
754
- return error;
427
+ }
755
428
 
756
- if (git_stream_is_encrypted(stream) && cert_cb != NULL)
757
- error = check_certificate(stream, url, !error, cert_cb, cb_payload);
429
+ done:
430
+ git_net_url_dispose(&url);
431
+ git_net_url_dispose(&proxy_url);
432
+ git_http_response_dispose(&response);
758
433
 
759
434
  return error;
760
435
  }
761
436
 
762
- static int gen_connect_req(git_buf *buf, http_subtransport *t)
437
+ static bool needs_probe(http_stream *stream)
763
438
  {
764
- git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n",
765
- t->server.url.host, t->server.url.port);
766
-
767
- git_buf_puts(buf, "User-Agent: ");
768
- git_http__user_agent(buf);
769
- git_buf_puts(buf, "\r\n");
770
-
771
- git_buf_printf(buf, "Host: %s\r\n", t->proxy.url.host);
439
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
772
440
 
773
- if (apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0)
774
- return -1;
775
-
776
- git_buf_puts(buf, "\r\n");
777
-
778
- return git_buf_oom(buf) ? -1 : 0;
441
+ return (transport->server.auth_schemetypes == GIT_HTTP_AUTH_NTLM ||
442
+ transport->server.auth_schemetypes == GIT_HTTP_AUTH_NEGOTIATE);
779
443
  }
780
444
 
781
- static int proxy_headers_complete(http_parser *parser)
445
+ static int send_probe(http_stream *stream)
782
446
  {
783
- parser_context *ctx = (parser_context *) parser->data;
784
- http_subtransport *t = ctx->t;
785
- int proxy_auth_types = 0;
786
-
787
- /* Enforce a reasonable cap on the number of replays */
788
- if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) {
789
- git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
790
- return t->parse_error = PARSE_ERROR_GENERIC;
791
- }
447
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
448
+ git_http_client *client = transport->http_client;
449
+ const char *probe = "0000";
450
+ size_t len = 4;
451
+ git_net_url url = GIT_NET_URL_INIT;
452
+ git_http_request request = {0};
453
+ git_http_response response = {0};
454
+ bool complete = false;
455
+ size_t step, steps = 1;
456
+ int error;
792
457
 
793
- /* Both parse_header_name and parse_header_value are populated
794
- * and ready for consumption. */
795
- if (VALUE == t->last_cb)
796
- if (on_header_ready(t) < 0)
797
- return t->parse_error = PARSE_ERROR_GENERIC;
458
+ /* NTLM requires a full challenge/response */
459
+ if (transport->server.auth_schemetypes == GIT_HTTP_AUTH_NTLM)
460
+ steps = GIT_AUTH_STEPS_NTLM;
798
461
 
799
462
  /*
800
- * Capture authentication headers for the proxy or final endpoint,
801
- * these may be 407/401 (authentication is not complete) or a 200
802
- * (informing us that auth has completed).
463
+ * Send at most two requests: one without any authentication to see
464
+ * if we get prompted to authenticate. If we do, send a second one
465
+ * with the first authentication message. The final authentication
466
+ * message with the response will occur with the *actual* POST data.
803
467
  */
804
- if (parse_authenticate_response(&t->proxy, &proxy_auth_types) < 0)
805
- return t->parse_error = PARSE_ERROR_GENERIC;
806
-
807
- /* Check for a proxy authentication failure. */
808
- if (parser->status_code == 407)
809
- return on_auth_required(&t->proxy.cred,
810
- parser,
811
- t->proxy_opts.url,
812
- SERVER_TYPE_PROXY,
813
- t->proxy_opts.credentials,
814
- t->proxy_opts.payload,
815
- t->proxy.url.user,
816
- proxy_auth_types);
817
-
818
- if (parser->status_code != 200) {
819
- git_error_set(GIT_ERROR_NET, "unexpected status code from proxy: %d",
820
- parser->status_code);
821
- return t->parse_error = PARSE_ERROR_GENERIC;
468
+ for (step = 0; step < steps && !complete; step++) {
469
+ git_net_url_dispose(&url);
470
+ git_http_response_dispose(&response);
471
+
472
+ if ((error = generate_request(&url, &request, stream, len)) < 0 ||
473
+ (error = git_http_client_send_request(client, &request)) < 0 ||
474
+ (error = git_http_client_send_body(client, probe, len)) < 0 ||
475
+ (error = git_http_client_read_response(&response, client)) < 0 ||
476
+ (error = git_http_client_skip_body(client)) < 0 ||
477
+ (error = handle_response(&complete, stream, &response, true)) < 0)
478
+ goto done;
822
479
  }
823
480
 
824
- if (!t->content_length || strcmp(t->content_length, "0") == 0)
825
- t->parse_finished = 1;
826
-
827
- return 0;
481
+ done:
482
+ git_http_response_dispose(&response);
483
+ git_net_url_dispose(&url);
484
+ return error;
828
485
  }
829
486
 
830
- static int proxy_connect(
831
- git_stream **out, git_stream *proxy_stream, http_subtransport *t)
487
+ /*
488
+ * Write to an HTTP transport - for the first invocation of this function
489
+ * (ie, when stream->state == HTTP_STATE_NONE), we'll send a POST request
490
+ * to the remote host. If we're sending chunked data, then subsequent calls
491
+ * will write the additional data given in the buffer. If we're not chunking,
492
+ * then the caller should have given us all the data in the original call.
493
+ * The caller should call http_stream_read_response to get the result.
494
+ */
495
+ static int http_stream_write(
496
+ git_smart_subtransport_stream *s,
497
+ const char *buffer,
498
+ size_t len)
832
499
  {
833
- git_buf request = GIT_BUF_INIT;
834
- static http_parser_settings proxy_parser_settings = {0};
835
- size_t bytes_read = 0, bytes_parsed;
836
- parser_context ctx;
500
+ http_stream *stream = GIT_CONTAINER_OF(s, http_stream, parent);
501
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
502
+ git_net_url url = GIT_NET_URL_INIT;
503
+ git_http_request request = {0};
504
+ git_http_response response = {0};
837
505
  int error;
838
506
 
839
- /* Use the parser settings only to parser headers. */
840
- proxy_parser_settings.on_header_field = on_header_field;
841
- proxy_parser_settings.on_header_value = on_header_value;
842
- proxy_parser_settings.on_headers_complete = proxy_headers_complete;
843
- proxy_parser_settings.on_message_complete = on_message_complete;
844
-
845
- replay:
846
- clear_parser_state(t);
847
-
848
- gitno_buffer_setup_fromstream(proxy_stream,
849
- &t->parse_buffer,
850
- t->parse_buffer_data,
851
- sizeof(t->parse_buffer_data));
507
+ while (stream->state == HTTP_STATE_NONE &&
508
+ stream->replay_count < GIT_HTTP_REPLAY_MAX) {
852
509
 
853
- if ((error = gen_connect_req(&request, t)) < 0)
854
- goto done;
855
-
856
- if ((error = git_stream__write_full(proxy_stream, request.ptr,
857
- request.size, 0)) < 0)
858
- goto done;
859
-
860
- git_buf_dispose(&request);
861
-
862
- while (!bytes_read && !t->parse_finished) {
863
- t->parse_buffer.offset = 0;
864
-
865
- if ((error = gitno_recv(&t->parse_buffer)) < 0)
866
- goto done;
510
+ git_net_url_dispose(&url);
511
+ git_http_response_dispose(&response);
867
512
 
868
513
  /*
869
- * This call to http_parser_execute will invoke the on_*
870
- * callbacks. Since we don't care about the body of the response,
871
- * we can set our buffer to NULL.
514
+ * If we're authenticating with a connection-based mechanism
515
+ * (NTLM, Kerberos), send a "probe" packet. Servers SHOULD
516
+ * authenticate an entire keep-alive connection, so ideally
517
+ * we should not need to authenticate but some servers do
518
+ * not support this. By sending a probe packet, we'll be
519
+ * able to follow up with a second POST using the actual
520
+ * data (and, in the degenerate case, the authentication
521
+ * header as well).
872
522
  */
873
- ctx.t = t;
874
- ctx.s = NULL;
875
- ctx.buffer = NULL;
876
- ctx.buf_size = 0;
877
- ctx.bytes_read = &bytes_read;
878
-
879
- /* Set the context, call the parser, then unset the context. */
880
- t->parser.data = &ctx;
881
-
882
- bytes_parsed = http_parser_execute(&t->parser,
883
- &proxy_parser_settings, t->parse_buffer.data, t->parse_buffer.offset);
884
-
885
- t->parser.data = NULL;
886
-
887
- /* Ensure that we didn't get a redirect; unsupported. */
888
- if (t->location) {
889
- git_error_set(GIT_ERROR_NET, "proxy server sent unsupported redirect during CONNECT");
890
- error = -1;
523
+ if (needs_probe(stream) && (error = send_probe(stream)) < 0)
891
524
  goto done;
892
- }
893
-
894
- /* Replay the request with authentication headers. */
895
- if (PARSE_ERROR_REPLAY == t->parse_error)
896
- goto replay;
897
525
 
898
- if (t->parse_error < 0) {
899
- error = t->parse_error == PARSE_ERROR_EXT ? PARSE_ERROR_EXT : -1;
526
+ /* Send the regular POST request. */
527
+ if ((error = generate_request(&url, &request, stream, len)) < 0 ||
528
+ (error = git_http_client_send_request(
529
+ transport->http_client, &request)) < 0)
900
530
  goto done;
901
- }
902
531
 
903
- if (bytes_parsed != t->parse_buffer.offset) {
904
- git_error_set(GIT_ERROR_NET,
905
- "HTTP parser error: %s",
906
- http_errno_description((enum http_errno)t->parser.http_errno));
907
- error = -1;
908
- goto done;
532
+ if (request.expect_continue &&
533
+ git_http_client_has_response(transport->http_client)) {
534
+ bool complete;
535
+
536
+ /*
537
+ * If we got a response to an expect/continue, then
538
+ * it's something other than a 100 and we should
539
+ * deal with the response somehow.
540
+ */
541
+ if ((error = git_http_client_read_response(&response, transport->http_client)) < 0 ||
542
+ (error = handle_response(&complete, stream, &response, true)) < 0)
543
+ goto done;
544
+ } else {
545
+ stream->state = HTTP_STATE_SENDING_REQUEST;
909
546
  }
910
- }
911
-
912
- if ((error = git_tls_stream_wrap(out, proxy_stream, t->server.url.host)) == 0)
913
- error = stream_connect(*out, &t->server.url,
914
- t->owner->certificate_check_cb,
915
- t->owner->message_cb_payload);
916
-
917
- /*
918
- * Since we've connected via a HTTPS proxy tunnel, we don't behave
919
- * as if we have an HTTP proxy.
920
- */
921
- t->proxy_opts.type = GIT_PROXY_NONE;
922
- t->replay_count = 0;
923
547
 
924
- done:
925
- return error;
926
- }
927
-
928
- static int http_connect(http_subtransport *t)
929
- {
930
- gitno_connection_data *url;
931
- git_stream *proxy_stream = NULL, *stream = NULL;
932
- git_transport_certificate_check_cb cert_cb;
933
- void *cb_payload;
934
- int error;
935
-
936
- if (t->connected &&
937
- http_should_keep_alive(&t->parser) &&
938
- t->parse_finished)
939
- return 0;
940
-
941
- if ((error = load_proxy_config(t)) < 0)
942
- return error;
943
-
944
- if (t->server.stream) {
945
- git_stream_close(t->server.stream);
946
- git_stream_free(t->server.stream);
947
- t->server.stream = NULL;
948
- }
949
-
950
- if (t->proxy.stream) {
951
- git_stream_close(t->proxy.stream);
952
- git_stream_free(t->proxy.stream);
953
- t->proxy.stream = NULL;
954
- }
955
-
956
- t->connected = 0;
957
-
958
- if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) {
959
- url = &t->proxy.url;
960
- cert_cb = t->proxy_opts.certificate_check;
961
- cb_payload = t->proxy_opts.payload;
962
- } else {
963
- url = &t->server.url;
964
- cert_cb = t->owner->certificate_check_cb;
965
- cb_payload = t->owner->message_cb_payload;
548
+ stream->replay_count++;
966
549
  }
967
550
 
968
- if (url->use_ssl)
969
- error = git_tls_stream_new(&stream, url->host, url->port);
970
- else
971
- error = git_socket_stream_new(&stream, url->host, url->port);
972
-
973
- if (error < 0)
974
- goto on_error;
975
-
976
- if ((error = stream_connect(stream, url, cert_cb, cb_payload)) < 0)
977
- goto on_error;
978
-
979
- /*
980
- * At this point we have a connection to the remote server or to
981
- * a proxy. If it's a proxy and the remote server is actually
982
- * an HTTPS connection, then we need to build a CONNECT tunnel.
983
- */
984
- if (t->proxy_opts.type == GIT_PROXY_SPECIFIED &&
985
- t->server.url.use_ssl) {
986
- proxy_stream = stream;
987
- stream = NULL;
988
-
989
- if ((error = proxy_connect(&stream, proxy_stream, t)) < 0)
990
- goto on_error;
551
+ if (stream->state == HTTP_STATE_NONE) {
552
+ git_error_set(GIT_ERROR_HTTP,
553
+ "too many redirects or authentication replays");
554
+ error = -1;
555
+ goto done;
991
556
  }
992
557
 
993
- t->proxy.stream = proxy_stream;
994
- t->server.stream = stream;
995
- t->connected = 1;
996
- t->replay_count = 0;
997
- return 0;
558
+ assert(stream->state == HTTP_STATE_SENDING_REQUEST);
998
559
 
999
- on_error:
1000
- if (stream) {
1001
- git_stream_close(stream);
1002
- git_stream_free(stream);
1003
- }
1004
-
1005
- if (proxy_stream) {
1006
- git_stream_close(proxy_stream);
1007
- git_stream_free(proxy_stream);
1008
- }
560
+ error = git_http_client_send_body(transport->http_client, buffer, len);
1009
561
 
562
+ done:
563
+ git_http_response_dispose(&response);
564
+ git_net_url_dispose(&url);
1010
565
  return error;
1011
566
  }
1012
567
 
1013
- static int http_stream_read(
1014
- git_smart_subtransport_stream *stream,
568
+ /*
569
+ * Read from an HTTP transport after it has been written to. This is the
570
+ * response from a POST request made by http_stream_write.
571
+ */
572
+ static int http_stream_read_response(
573
+ git_smart_subtransport_stream *s,
1015
574
  char *buffer,
1016
- size_t buf_size,
1017
- size_t *bytes_read)
1018
- {
1019
- http_stream *s = (http_stream *)stream;
1020
- http_subtransport *t = OWNING_SUBTRANSPORT(s);
1021
- parser_context ctx;
1022
- size_t bytes_parsed;
1023
-
1024
- replay:
1025
- *bytes_read = 0;
1026
-
1027
- assert(t->connected);
1028
-
1029
- if (!s->sent_request) {
1030
- git_buf request = GIT_BUF_INIT;
1031
-
1032
- clear_parser_state(t);
1033
-
1034
- if (gen_request(&request, s, 0) < 0)
1035
- return -1;
1036
-
1037
- if (git_stream__write_full(t->server.stream, request.ptr,
1038
- request.size, 0) < 0) {
1039
- git_buf_dispose(&request);
1040
- return -1;
1041
- }
1042
-
1043
- git_buf_dispose(&request);
1044
-
1045
- s->sent_request = 1;
1046
- }
1047
-
1048
- if (!s->received_response) {
1049
- if (s->chunked) {
1050
- assert(s->verb == post_verb);
1051
-
1052
- /* Flush, if necessary */
1053
- if (s->chunk_buffer_len > 0 &&
1054
- write_chunk(t->server.stream,
1055
- s->chunk_buffer, s->chunk_buffer_len) < 0)
1056
- return -1;
1057
-
1058
- s->chunk_buffer_len = 0;
1059
-
1060
- /* Write the final chunk. */
1061
- if (git_stream__write_full(t->server.stream,
1062
- "0\r\n\r\n", 5, 0) < 0)
1063
- return -1;
1064
- }
1065
-
1066
- s->received_response = 1;
1067
- }
1068
-
1069
- while (!*bytes_read && !t->parse_finished) {
1070
- size_t data_offset;
1071
- int error;
1072
-
1073
- /*
1074
- * Make the parse_buffer think it's as full of data as
1075
- * the buffer, so it won't try to recv more data than
1076
- * we can put into it.
1077
- *
1078
- * data_offset is the actual data offset from which we
1079
- * should tell the parser to start reading.
1080
- */
1081
- if (buf_size >= t->parse_buffer.len) {
1082
- t->parse_buffer.offset = 0;
1083
- } else {
1084
- t->parse_buffer.offset = t->parse_buffer.len - buf_size;
1085
- }
1086
-
1087
- data_offset = t->parse_buffer.offset;
1088
-
1089
- if (gitno_recv(&t->parse_buffer) < 0)
1090
- return -1;
1091
-
1092
- /* This call to http_parser_execute will result in invocations of the
1093
- * on_* family of callbacks. The most interesting of these is
1094
- * on_body_fill_buffer, which is called when data is ready to be copied
1095
- * into the target buffer. We need to marshal the buffer, buf_size, and
1096
- * bytes_read parameters to this callback. */
1097
- ctx.t = t;
1098
- ctx.s = s;
1099
- ctx.buffer = buffer;
1100
- ctx.buf_size = buf_size;
1101
- ctx.bytes_read = bytes_read;
1102
-
1103
- /* Set the context, call the parser, then unset the context. */
1104
- t->parser.data = &ctx;
1105
-
1106
- bytes_parsed = http_parser_execute(&t->parser,
1107
- &t->settings,
1108
- t->parse_buffer.data + data_offset,
1109
- t->parse_buffer.offset - data_offset);
1110
-
1111
- t->parser.data = NULL;
1112
-
1113
- /* If there was a handled authentication failure, then parse_error
1114
- * will have signaled us that we should replay the request. */
1115
- if (PARSE_ERROR_REPLAY == t->parse_error) {
1116
- s->sent_request = 0;
1117
-
1118
- if ((error = http_connect(t)) < 0)
1119
- return error;
1120
-
1121
- goto replay;
1122
- }
1123
-
1124
- if (t->parse_error == PARSE_ERROR_EXT) {
1125
- return t->error;
1126
- }
1127
-
1128
- if (t->parse_error < 0)
1129
- return -1;
1130
-
1131
- if (bytes_parsed != t->parse_buffer.offset - data_offset) {
1132
- git_error_set(GIT_ERROR_NET,
1133
- "HTTP parser error: %s",
1134
- http_errno_description((enum http_errno)t->parser.http_errno));
1135
- return -1;
1136
- }
1137
- }
1138
-
1139
- return 0;
1140
- }
1141
-
1142
- static int http_stream_write_chunked(
1143
- git_smart_subtransport_stream *stream,
1144
- const char *buffer,
1145
- size_t len)
1146
- {
1147
- http_stream *s = (http_stream *)stream;
1148
- http_subtransport *t = OWNING_SUBTRANSPORT(s);
1149
-
1150
- assert(t->connected);
1151
-
1152
- /* Send the request, if necessary */
1153
- if (!s->sent_request) {
1154
- git_buf request = GIT_BUF_INIT;
1155
-
1156
- clear_parser_state(t);
1157
-
1158
- if (gen_request(&request, s, 0) < 0)
1159
- return -1;
575
+ size_t buffer_size,
576
+ size_t *out_len)
577
+ {
578
+ http_stream *stream = (http_stream *)s;
579
+ http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
580
+ git_http_client *client = transport->http_client;
581
+ git_http_response response = {0};
582
+ bool complete;
583
+ int error;
1160
584
 
1161
- if (git_stream__write_full(t->server.stream, request.ptr,
1162
- request.size, 0) < 0) {
1163
- git_buf_dispose(&request);
1164
- return -1;
1165
- }
585
+ *out_len = 0;
1166
586
 
1167
- git_buf_dispose(&request);
587
+ if (stream->state == HTTP_STATE_SENDING_REQUEST) {
588
+ if ((error = git_http_client_read_response(&response, client)) < 0 ||
589
+ (error = handle_response(&complete, stream, &response, false)) < 0)
590
+ goto done;
1168
591
 
1169
- s->sent_request = 1;
592
+ assert(complete);
593
+ stream->state = HTTP_STATE_RECEIVING_RESPONSE;
1170
594
  }
1171
595
 
1172
- if (len > CHUNK_SIZE) {
1173
- /* Flush, if necessary */
1174
- if (s->chunk_buffer_len > 0) {
1175
- if (write_chunk(t->server.stream,
1176
- s->chunk_buffer, s->chunk_buffer_len) < 0)
1177
- return -1;
1178
-
1179
- s->chunk_buffer_len = 0;
1180
- }
596
+ error = git_http_client_read_body(client, buffer, buffer_size);
1181
597
 
1182
- /* Write chunk directly */
1183
- if (write_chunk(t->server.stream, buffer, len) < 0)
1184
- return -1;
1185
- }
1186
- else {
1187
- /* Append as much to the buffer as we can */
1188
- int count = min(CHUNK_SIZE - s->chunk_buffer_len, len);
1189
-
1190
- if (!s->chunk_buffer)
1191
- s->chunk_buffer = git__malloc(CHUNK_SIZE);
1192
-
1193
- memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count);
1194
- s->chunk_buffer_len += count;
1195
- buffer += count;
1196
- len -= count;
1197
-
1198
- /* Is the buffer full? If so, then flush */
1199
- if (CHUNK_SIZE == s->chunk_buffer_len) {
1200
- if (write_chunk(t->server.stream,
1201
- s->chunk_buffer, s->chunk_buffer_len) < 0)
1202
- return -1;
1203
-
1204
- s->chunk_buffer_len = 0;
1205
-
1206
- if (len > 0) {
1207
- memcpy(s->chunk_buffer, buffer, len);
1208
- s->chunk_buffer_len = len;
1209
- }
1210
- }
1211
- }
1212
-
1213
- return 0;
1214
- }
1215
-
1216
- static int http_stream_write_single(
1217
- git_smart_subtransport_stream *stream,
1218
- const char *buffer,
1219
- size_t len)
1220
- {
1221
- http_stream *s = (http_stream *)stream;
1222
- http_subtransport *t = OWNING_SUBTRANSPORT(s);
1223
- git_buf request = GIT_BUF_INIT;
1224
-
1225
- assert(t->connected);
1226
-
1227
- if (s->sent_request) {
1228
- git_error_set(GIT_ERROR_NET, "subtransport configured for only one write");
1229
- return -1;
598
+ if (error > 0) {
599
+ *out_len = error;
600
+ error = 0;
1230
601
  }
1231
602
 
1232
- clear_parser_state(t);
1233
-
1234
- if (gen_request(&request, s, len) < 0)
1235
- return -1;
1236
-
1237
- if (git_stream__write_full(t->server.stream, request.ptr, request.size, 0) < 0)
1238
- goto on_error;
1239
-
1240
- if (len && git_stream__write_full(t->server.stream, buffer, len, 0) < 0)
1241
- goto on_error;
1242
-
1243
- git_buf_dispose(&request);
1244
- s->sent_request = 1;
1245
-
1246
- return 0;
1247
-
1248
- on_error:
1249
- git_buf_dispose(&request);
1250
- return -1;
603
+ done:
604
+ git_http_response_dispose(&response);
605
+ return error;
1251
606
  }
1252
607
 
1253
608
  static void http_stream_free(git_smart_subtransport_stream *stream)
1254
609
  {
1255
- http_stream *s = (http_stream *)stream;
1256
-
1257
- if (s->chunk_buffer)
1258
- git__free(s->chunk_buffer);
1259
-
1260
- if (s->redirect_url)
1261
- git__free(s->redirect_url);
1262
-
610
+ http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
1263
611
  git__free(s);
1264
612
  }
1265
613
 
1266
- static int http_stream_alloc(http_subtransport *t,
1267
- git_smart_subtransport_stream **stream)
1268
- {
1269
- http_stream *s;
1270
-
1271
- if (!stream)
1272
- return -1;
1273
-
1274
- s = git__calloc(sizeof(http_stream), 1);
1275
- GIT_ERROR_CHECK_ALLOC(s);
1276
-
1277
- s->parent.subtransport = &t->parent;
1278
- s->parent.read = http_stream_read;
1279
- s->parent.write = http_stream_write_single;
1280
- s->parent.free = http_stream_free;
1281
-
1282
- *stream = (git_smart_subtransport_stream *)s;
1283
- return 0;
1284
- }
1285
-
1286
- static int http_uploadpack_ls(
1287
- http_subtransport *t,
1288
- git_smart_subtransport_stream **stream)
1289
- {
1290
- http_stream *s;
1291
-
1292
- if (http_stream_alloc(t, stream) < 0)
1293
- return -1;
1294
-
1295
- s = (http_stream *)*stream;
1296
-
1297
- s->service = upload_pack_service;
1298
- s->service_url = upload_pack_ls_service_url;
1299
- s->verb = get_verb;
1300
-
1301
- return 0;
1302
- }
1303
-
1304
- static int http_uploadpack(
1305
- http_subtransport *t,
1306
- git_smart_subtransport_stream **stream)
614
+ static const http_service *select_service(git_smart_service_t action)
1307
615
  {
1308
- http_stream *s;
1309
-
1310
- if (http_stream_alloc(t, stream) < 0)
1311
- return -1;
1312
-
1313
- s = (http_stream *)*stream;
1314
-
1315
- s->service = upload_pack_service;
1316
- s->service_url = upload_pack_service_url;
1317
- s->verb = post_verb;
1318
-
1319
- return 0;
1320
- }
1321
-
1322
- static int http_receivepack_ls(
1323
- http_subtransport *t,
1324
- git_smart_subtransport_stream **stream)
1325
- {
1326
- http_stream *s;
1327
-
1328
- if (http_stream_alloc(t, stream) < 0)
1329
- return -1;
1330
-
1331
- s = (http_stream *)*stream;
1332
-
1333
- s->service = receive_pack_service;
1334
- s->service_url = receive_pack_ls_service_url;
1335
- s->verb = get_verb;
1336
-
1337
- return 0;
1338
- }
1339
-
1340
- static int http_receivepack(
1341
- http_subtransport *t,
1342
- git_smart_subtransport_stream **stream)
1343
- {
1344
- http_stream *s;
1345
-
1346
- if (http_stream_alloc(t, stream) < 0)
1347
- return -1;
1348
-
1349
- s = (http_stream *)*stream;
1350
-
1351
- /* Use Transfer-Encoding: chunked for this request */
1352
- s->chunked = 1;
1353
- s->parent.write = http_stream_write_chunked;
1354
-
1355
- s->service = receive_pack_service;
1356
- s->service_url = receive_pack_service_url;
1357
- s->verb = post_verb;
616
+ switch (action) {
617
+ case GIT_SERVICE_UPLOADPACK_LS:
618
+ return &upload_pack_ls_service;
619
+ case GIT_SERVICE_UPLOADPACK:
620
+ return &upload_pack_service;
621
+ case GIT_SERVICE_RECEIVEPACK_LS:
622
+ return &receive_pack_ls_service;
623
+ case GIT_SERVICE_RECEIVEPACK:
624
+ return &receive_pack_service;
625
+ }
1358
626
 
1359
- return 0;
627
+ return NULL;
1360
628
  }
1361
629
 
1362
630
  static int http_action(
1363
- git_smart_subtransport_stream **stream,
1364
- git_smart_subtransport *subtransport,
631
+ git_smart_subtransport_stream **out,
632
+ git_smart_subtransport *t,
1365
633
  const char *url,
1366
634
  git_smart_service_t action)
1367
635
  {
1368
- http_subtransport *t = (http_subtransport *)subtransport;
1369
- int ret;
636
+ http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent);
637
+ http_stream *stream;
638
+ const http_service *service;
639
+ int error;
1370
640
 
1371
- assert(stream);
641
+ assert(out && t);
642
+
643
+ *out = NULL;
1372
644
 
1373
645
  /*
1374
646
  * If we've seen a redirect then preserve the location that we've
@@ -1377,121 +649,89 @@ static int http_action(
1377
649
  * have redirected us from HTTP->HTTPS and is using an auth mechanism
1378
650
  * that would be insecure in plaintext (eg, HTTP Basic).
1379
651
  */
1380
- if ((!t->server.url.host || !t->server.url.port || !t->server.url.path) &&
1381
- (ret = gitno_connection_data_from_url(&t->server.url, url, NULL)) < 0)
1382
- return ret;
1383
-
1384
- assert(t->server.url.host && t->server.url.port && t->server.url.path);
652
+ if (!git_net_url_valid(&transport->server.url) &&
653
+ (error = git_net_url_parse(&transport->server.url, url)) < 0)
654
+ return error;
1385
655
 
1386
- if ((ret = http_connect(t)) < 0)
1387
- return ret;
656
+ if ((service = select_service(action)) == NULL) {
657
+ git_error_set(GIT_ERROR_HTTP, "invalid action");
658
+ return -1;
659
+ }
1388
660
 
1389
- switch (action) {
1390
- case GIT_SERVICE_UPLOADPACK_LS:
1391
- return http_uploadpack_ls(t, stream);
661
+ stream = git__calloc(sizeof(http_stream), 1);
662
+ GIT_ERROR_CHECK_ALLOC(stream);
1392
663
 
1393
- case GIT_SERVICE_UPLOADPACK:
1394
- return http_uploadpack(t, stream);
664
+ if (!transport->http_client) {
665
+ git_http_client_options opts = {0};
1395
666
 
1396
- case GIT_SERVICE_RECEIVEPACK_LS:
1397
- return http_receivepack_ls(t, stream);
667
+ opts.server_certificate_check_cb = transport->owner->certificate_check_cb;
668
+ opts.server_certificate_check_payload = transport->owner->message_cb_payload;
669
+ opts.proxy_certificate_check_cb = transport->owner->proxy.certificate_check;
670
+ opts.proxy_certificate_check_payload = transport->owner->proxy.payload;
1398
671
 
1399
- case GIT_SERVICE_RECEIVEPACK:
1400
- return http_receivepack(t, stream);
672
+ if (git_http_client_new(&transport->http_client, &opts) < 0)
673
+ return -1;
1401
674
  }
1402
675
 
1403
- *stream = NULL;
1404
- return -1;
1405
- }
1406
-
1407
- static void free_auth_contexts(git_vector *contexts)
1408
- {
1409
- git_http_auth_context *context;
1410
- size_t i;
676
+ stream->service = service;
677
+ stream->parent.subtransport = &transport->parent;
1411
678
 
1412
- git_vector_foreach(contexts, i, context) {
1413
- if (context->free)
1414
- context->free(context);
679
+ if (service->method == GIT_HTTP_METHOD_GET) {
680
+ stream->parent.read = http_stream_read;
681
+ } else {
682
+ stream->parent.write = http_stream_write;
683
+ stream->parent.read = http_stream_read_response;
1415
684
  }
1416
685
 
1417
- git_vector_clear(contexts);
686
+ stream->parent.free = http_stream_free;
687
+
688
+ *out = (git_smart_subtransport_stream *)stream;
689
+ return 0;
1418
690
  }
1419
691
 
1420
- static int http_close(git_smart_subtransport *subtransport)
692
+ static int http_close(git_smart_subtransport *t)
1421
693
  {
1422
- http_subtransport *t = (http_subtransport *) subtransport;
1423
-
1424
- clear_parser_state(t);
1425
-
1426
- t->connected = 0;
1427
-
1428
- if (t->server.stream) {
1429
- git_stream_close(t->server.stream);
1430
- git_stream_free(t->server.stream);
1431
- t->server.stream = NULL;
1432
- }
1433
-
1434
- if (t->proxy.stream) {
1435
- git_stream_close(t->proxy.stream);
1436
- git_stream_free(t->proxy.stream);
1437
- t->proxy.stream = NULL;
1438
- }
1439
-
1440
- free_cred(&t->server.cred);
1441
- free_cred(&t->server.url_cred);
1442
- free_cred(&t->proxy.cred);
1443
- free_cred(&t->proxy.url_cred);
694
+ http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent);
1444
695
 
1445
- free_auth_contexts(&t->server.auth_contexts);
1446
- free_auth_contexts(&t->proxy.auth_contexts);
696
+ free_cred(&transport->server.cred);
697
+ free_cred(&transport->proxy.cred);
1447
698
 
1448
- gitno_connection_data_free_ptrs(&t->server.url);
1449
- memset(&t->server.url, 0x0, sizeof(gitno_connection_data));
699
+ transport->server.url_cred_presented = false;
700
+ transport->proxy.url_cred_presented = false;
1450
701
 
1451
- gitno_connection_data_free_ptrs(&t->proxy.url);
1452
- memset(&t->proxy.url, 0x0, sizeof(gitno_connection_data));
1453
-
1454
- git__free(t->proxy_url);
1455
- t->proxy_url = NULL;
702
+ git_net_url_dispose(&transport->server.url);
703
+ git_net_url_dispose(&transport->proxy.url);
1456
704
 
1457
705
  return 0;
1458
706
  }
1459
707
 
1460
- static void http_free(git_smart_subtransport *subtransport)
708
+ static void http_free(git_smart_subtransport *t)
1461
709
  {
1462
- http_subtransport *t = (http_subtransport *) subtransport;
710
+ http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent);
1463
711
 
1464
- http_close(subtransport);
712
+ git_http_client_free(transport->http_client);
1465
713
 
1466
- git_vector_free(&t->server.auth_contexts);
1467
- git_vector_free(&t->proxy.auth_contexts);
1468
- git__free(t);
714
+ http_close(t);
715
+ git__free(transport);
1469
716
  }
1470
717
 
1471
718
  int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner, void *param)
1472
719
  {
1473
- http_subtransport *t;
720
+ http_subtransport *transport;
1474
721
 
1475
722
  GIT_UNUSED(param);
1476
723
 
1477
- if (!out)
1478
- return -1;
1479
-
1480
- t = git__calloc(sizeof(http_subtransport), 1);
1481
- GIT_ERROR_CHECK_ALLOC(t);
724
+ assert(out);
1482
725
 
1483
- t->owner = (transport_smart *)owner;
1484
- t->parent.action = http_action;
1485
- t->parent.close = http_close;
1486
- t->parent.free = http_free;
726
+ transport = git__calloc(sizeof(http_subtransport), 1);
727
+ GIT_ERROR_CHECK_ALLOC(transport);
1487
728
 
1488
- t->settings.on_header_field = on_header_field;
1489
- t->settings.on_header_value = on_header_value;
1490
- t->settings.on_headers_complete = on_headers_complete;
1491
- t->settings.on_body = on_body_fill_buffer;
1492
- t->settings.on_message_complete = on_message_complete;
729
+ transport->owner = (transport_smart *)owner;
730
+ transport->parent.action = http_action;
731
+ transport->parent.close = http_close;
732
+ transport->parent.free = http_free;
1493
733
 
1494
- *out = (git_smart_subtransport *) t;
734
+ *out = (git_smart_subtransport *) transport;
1495
735
  return 0;
1496
736
  }
1497
737