rubygems-update 3.3.18 → 3.6.2

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.
Files changed (832) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2182 -1067
  3. data/CODE_OF_CONDUCT.md +79 -28
  4. data/Manifest.txt +184 -290
  5. data/README.md +35 -19
  6. data/bundler/CHANGELOG.md +1003 -3
  7. data/bundler/README.md +3 -7
  8. data/bundler/bundler.gemspec +11 -11
  9. data/bundler/exe/bundle +5 -25
  10. data/bundler/lib/bundler/build_metadata.rb +3 -3
  11. data/bundler/lib/bundler/capistrano.rb +1 -1
  12. data/bundler/lib/bundler/checksum.rb +254 -0
  13. data/bundler/lib/bundler/ci_detector.rb +75 -0
  14. data/bundler/lib/bundler/cli/add.rb +7 -5
  15. data/bundler/lib/bundler/cli/binstubs.rb +10 -6
  16. data/bundler/lib/bundler/cli/cache.rb +1 -1
  17. data/bundler/lib/bundler/cli/check.rb +4 -4
  18. data/bundler/lib/bundler/cli/common.rb +11 -1
  19. data/bundler/lib/bundler/cli/config.rb +8 -7
  20. data/bundler/lib/bundler/cli/console.rb +2 -5
  21. data/bundler/lib/bundler/cli/doctor.rb +10 -12
  22. data/bundler/lib/bundler/cli/exec.rb +2 -1
  23. data/bundler/lib/bundler/cli/fund.rb +1 -1
  24. data/bundler/lib/bundler/cli/gem.rb +77 -53
  25. data/bundler/lib/bundler/cli/info.rb +4 -15
  26. data/bundler/lib/bundler/cli/init.rb +6 -2
  27. data/bundler/lib/bundler/cli/inject.rb +1 -1
  28. data/bundler/lib/bundler/cli/install.rb +27 -15
  29. data/bundler/lib/bundler/cli/issue.rb +1 -1
  30. data/bundler/lib/bundler/cli/lock.rb +54 -28
  31. data/bundler/lib/bundler/cli/open.rb +9 -9
  32. data/bundler/lib/bundler/cli/outdated.rb +34 -29
  33. data/bundler/lib/bundler/cli/platform.rb +7 -5
  34. data/bundler/lib/bundler/cli/plugin.rb +9 -15
  35. data/bundler/lib/bundler/cli/pristine.rb +38 -30
  36. data/bundler/lib/bundler/cli/show.rb +4 -4
  37. data/bundler/lib/bundler/cli/update.rb +6 -5
  38. data/bundler/lib/bundler/cli/viz.rb +1 -1
  39. data/bundler/lib/bundler/cli.rb +258 -307
  40. data/bundler/lib/bundler/compact_index_client/cache.rb +55 -60
  41. data/bundler/lib/bundler/compact_index_client/cache_file.rb +148 -0
  42. data/bundler/lib/bundler/compact_index_client/gem_parser.rb +7 -3
  43. data/bundler/lib/bundler/compact_index_client/parser.rb +84 -0
  44. data/bundler/lib/bundler/compact_index_client/updater.rb +71 -83
  45. data/bundler/lib/bundler/compact_index_client.rb +58 -80
  46. data/bundler/lib/bundler/constants.rb +9 -2
  47. data/bundler/lib/bundler/current_ruby.rb +11 -16
  48. data/bundler/lib/bundler/definition.rb +547 -228
  49. data/bundler/lib/bundler/dependency.rb +30 -87
  50. data/bundler/lib/bundler/digest.rb +3 -3
  51. data/bundler/lib/bundler/dsl.rb +115 -65
  52. data/bundler/lib/bundler/endpoint_specification.rb +27 -14
  53. data/bundler/lib/bundler/env.rb +5 -7
  54. data/bundler/lib/bundler/environment_preserver.rb +8 -25
  55. data/bundler/lib/bundler/errors.rb +85 -11
  56. data/bundler/lib/bundler/feature_flag.rb +1 -2
  57. data/bundler/lib/bundler/fetcher/base.rb +5 -3
  58. data/bundler/lib/bundler/fetcher/compact_index.rb +28 -43
  59. data/bundler/lib/bundler/fetcher/dependency.rb +3 -7
  60. data/bundler/lib/bundler/fetcher/downloader.rb +17 -16
  61. data/bundler/lib/bundler/fetcher/gem_remote_fetcher.rb +16 -0
  62. data/bundler/lib/bundler/fetcher/index.rb +2 -3
  63. data/bundler/lib/bundler/fetcher.rb +91 -74
  64. data/bundler/lib/bundler/force_platform.rb +16 -0
  65. data/bundler/lib/bundler/friendly_errors.rb +6 -9
  66. data/bundler/lib/bundler/gem_helper.rb +5 -6
  67. data/bundler/lib/bundler/gem_helpers.rb +45 -7
  68. data/bundler/lib/bundler/gem_version_promoter.rb +68 -109
  69. data/bundler/lib/bundler/graph.rb +9 -9
  70. data/bundler/lib/bundler/index.rb +69 -73
  71. data/bundler/lib/bundler/injector.rb +12 -13
  72. data/bundler/lib/bundler/inline.rb +40 -17
  73. data/bundler/lib/bundler/installer/gem_installer.rb +13 -12
  74. data/bundler/lib/bundler/installer/parallel_installer.rb +19 -66
  75. data/bundler/lib/bundler/installer/standalone.rb +29 -15
  76. data/bundler/lib/bundler/installer.rb +27 -77
  77. data/bundler/lib/bundler/lazy_specification.rb +134 -71
  78. data/bundler/lib/bundler/lockfile_generator.rb +13 -4
  79. data/bundler/lib/bundler/lockfile_parser.rb +134 -61
  80. data/bundler/lib/bundler/man/bundle-add.1 +46 -48
  81. data/bundler/lib/bundler/man/bundle-add.1.ronn +54 -22
  82. data/bundler/lib/bundler/man/bundle-binstubs.1 +10 -19
  83. data/bundler/lib/bundler/man/bundle-binstubs.1.ronn +6 -3
  84. data/bundler/lib/bundler/man/bundle-cache.1 +38 -25
  85. data/bundler/lib/bundler/man/bundle-cache.1.ronn +40 -4
  86. data/bundler/lib/bundler/man/bundle-check.1 +7 -14
  87. data/bundler/lib/bundler/man/bundle-check.1.ronn +7 -2
  88. data/bundler/lib/bundler/man/bundle-clean.1 +4 -11
  89. data/bundler/lib/bundler/man/bundle-clean.1.ronn +1 -1
  90. data/bundler/lib/bundler/man/bundle-config.1 +41 -220
  91. data/bundler/lib/bundler/man/bundle-config.1.ronn +27 -22
  92. data/bundler/lib/bundler/man/bundle-console.1 +33 -0
  93. data/bundler/lib/bundler/man/bundle-console.1.ronn +39 -0
  94. data/bundler/lib/bundler/man/bundle-doctor.1 +5 -19
  95. data/bundler/lib/bundler/man/bundle-doctor.1.ronn +1 -1
  96. data/bundler/lib/bundler/man/bundle-env.1 +9 -0
  97. data/bundler/lib/bundler/man/bundle-env.1.ronn +10 -0
  98. data/bundler/lib/bundler/man/bundle-exec.1 +20 -78
  99. data/bundler/lib/bundler/man/bundle-exec.1.ronn +12 -10
  100. data/bundler/lib/bundler/man/bundle-fund.1 +22 -0
  101. data/bundler/lib/bundler/man/bundle-fund.1.ronn +25 -0
  102. data/bundler/lib/bundler/man/bundle-gem.1 +53 -81
  103. data/bundler/lib/bundler/man/bundle-gem.1.ronn +41 -9
  104. data/bundler/lib/bundler/man/bundle-help.1 +9 -0
  105. data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
  106. data/bundler/lib/bundler/man/bundle-info.1 +8 -11
  107. data/bundler/lib/bundler/man/bundle-info.1.ronn +9 -5
  108. data/bundler/lib/bundler/man/bundle-init.1 +7 -12
  109. data/bundler/lib/bundler/man/bundle-init.1.ronn +4 -1
  110. data/bundler/lib/bundler/man/bundle-inject.1 +17 -19
  111. data/bundler/lib/bundler/man/bundle-inject.1.ronn +12 -2
  112. data/bundler/lib/bundler/man/bundle-install.1 +42 -162
  113. data/bundler/lib/bundler/man/bundle-install.1.ronn +31 -49
  114. data/bundler/lib/bundler/man/bundle-issue.1 +45 -0
  115. data/bundler/lib/bundler/man/bundle-issue.1.ronn +37 -0
  116. data/bundler/lib/bundler/man/bundle-licenses.1 +9 -0
  117. data/bundler/lib/bundler/man/bundle-licenses.1.ronn +10 -0
  118. data/bundler/lib/bundler/man/bundle-list.1 +4 -19
  119. data/bundler/lib/bundler/man/bundle-list.1.ronn +4 -1
  120. data/bundler/lib/bundler/man/bundle-lock.1 +25 -34
  121. data/bundler/lib/bundler/man/bundle-lock.1.ronn +25 -4
  122. data/bundler/lib/bundler/man/bundle-open.1 +18 -18
  123. data/bundler/lib/bundler/man/bundle-open.1.ronn +10 -1
  124. data/bundler/lib/bundler/man/bundle-outdated.1 +22 -67
  125. data/bundler/lib/bundler/man/bundle-outdated.1.ronn +20 -12
  126. data/bundler/lib/bundler/man/bundle-platform.1 +16 -28
  127. data/bundler/lib/bundler/man/bundle-platform.1.ronn +14 -7
  128. data/bundler/lib/bundler/man/bundle-plugin.1 +58 -0
  129. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +63 -0
  130. data/bundler/lib/bundler/man/bundle-pristine.1 +5 -16
  131. data/bundler/lib/bundler/man/bundle-pristine.1.ronn +1 -1
  132. data/bundler/lib/bundler/man/bundle-remove.1 +4 -14
  133. data/bundler/lib/bundler/man/bundle-remove.1.ronn +1 -1
  134. data/bundler/lib/bundler/man/bundle-show.1 +7 -11
  135. data/bundler/lib/bundler/man/bundle-show.1.ronn +4 -0
  136. data/bundler/lib/bundler/man/bundle-update.1 +30 -143
  137. data/bundler/lib/bundler/man/bundle-update.1.ronn +14 -6
  138. data/bundler/lib/bundler/man/bundle-version.1 +22 -0
  139. data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
  140. data/bundler/lib/bundler/man/bundle-viz.1 +9 -18
  141. data/bundler/lib/bundler/man/bundle-viz.1.ronn +9 -3
  142. data/bundler/lib/bundler/man/bundle.1 +17 -51
  143. data/bundler/lib/bundler/man/bundle.1.ronn +12 -7
  144. data/bundler/lib/bundler/man/gemfile.5 +77 -341
  145. data/bundler/lib/bundler/man/gemfile.5.ronn +73 -54
  146. data/bundler/lib/bundler/man/index.txt +8 -0
  147. data/bundler/lib/bundler/match_metadata.rb +17 -0
  148. data/bundler/lib/bundler/match_platform.rb +1 -1
  149. data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
  150. data/bundler/lib/bundler/materialization.rb +59 -0
  151. data/bundler/lib/bundler/mirror.rb +8 -10
  152. data/bundler/lib/bundler/plugin/api/source.rb +7 -5
  153. data/bundler/lib/bundler/plugin/events.rb +24 -0
  154. data/bundler/lib/bundler/plugin/index.rb +13 -5
  155. data/bundler/lib/bundler/plugin/installer/path.rb +18 -0
  156. data/bundler/lib/bundler/plugin/installer/rubygems.rb +0 -4
  157. data/bundler/lib/bundler/plugin/installer.rb +42 -19
  158. data/bundler/lib/bundler/plugin/source_list.rb +4 -4
  159. data/bundler/lib/bundler/plugin.rb +35 -7
  160. data/bundler/lib/bundler/process_lock.rb +10 -14
  161. data/bundler/lib/bundler/remote_specification.rb +17 -13
  162. data/bundler/lib/bundler/resolver/base.rb +117 -0
  163. data/bundler/lib/bundler/resolver/candidate.rb +82 -0
  164. data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
  165. data/bundler/lib/bundler/resolver/package.rb +90 -0
  166. data/bundler/lib/bundler/resolver/root.rb +25 -0
  167. data/bundler/lib/bundler/resolver/spec_group.rb +54 -67
  168. data/bundler/lib/bundler/resolver.rb +432 -329
  169. data/bundler/lib/bundler/retry.rb +2 -2
  170. data/bundler/lib/bundler/ruby_dsl.rb +42 -7
  171. data/bundler/lib/bundler/ruby_version.rb +23 -10
  172. data/bundler/lib/bundler/rubygems_ext.rb +286 -81
  173. data/bundler/lib/bundler/rubygems_gem_installer.rb +77 -68
  174. data/bundler/lib/bundler/rubygems_integration.rb +57 -155
  175. data/bundler/lib/bundler/runtime.rb +28 -17
  176. data/bundler/lib/bundler/safe_marshal.rb +31 -0
  177. data/bundler/lib/bundler/self_manager.rb +50 -12
  178. data/bundler/lib/bundler/settings.rb +144 -58
  179. data/bundler/lib/bundler/setup.rb +13 -1
  180. data/bundler/lib/bundler/shared_helpers.rb +87 -36
  181. data/bundler/lib/bundler/source/git/git_proxy.rb +278 -80
  182. data/bundler/lib/bundler/source/git.rb +161 -68
  183. data/bundler/lib/bundler/source/metadata.rb +16 -16
  184. data/bundler/lib/bundler/source/path/installer.rb +1 -22
  185. data/bundler/lib/bundler/source/path.rb +16 -26
  186. data/bundler/lib/bundler/source/rubygems/remote.rb +1 -1
  187. data/bundler/lib/bundler/source/rubygems.rb +94 -154
  188. data/bundler/lib/bundler/source.rb +3 -1
  189. data/bundler/lib/bundler/source_list.rb +34 -4
  190. data/bundler/lib/bundler/spec_set.rb +195 -65
  191. data/bundler/lib/bundler/stub_specification.rb +34 -4
  192. data/bundler/lib/bundler/templates/Executable +1 -1
  193. data/bundler/lib/bundler/templates/Executable.bundler +6 -11
  194. data/bundler/lib/bundler/templates/Executable.standalone +2 -0
  195. data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +77 -29
  196. data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  197. data/bundler/lib/bundler/templates/newgem/README.md.tt +11 -5
  198. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +19 -8
  199. data/bundler/lib/bundler/templates/newgem/bin/console.tt +0 -4
  200. data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  201. data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  202. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
  203. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  204. data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +1 -1
  205. data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  206. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +18 -8
  207. data/bundler/lib/bundler/templates/newgem/gitignore.tt +3 -0
  208. data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +13 -4
  209. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -4
  210. data/bundler/lib/bundler/templates/newgem/rubocop.yml.tt +0 -5
  211. data/bundler/lib/bundler/templates/newgem/standard.yml.tt +1 -1
  212. data/bundler/lib/bundler/ui/rg_proxy.rb +1 -1
  213. data/bundler/lib/bundler/ui/shell.rb +60 -15
  214. data/bundler/lib/bundler/ui/silent.rb +33 -6
  215. data/bundler/lib/bundler/uri_credentials_filter.rb +3 -3
  216. data/bundler/lib/bundler/uri_normalizer.rb +23 -0
  217. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
  218. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  219. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
  220. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +56 -7
  221. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1350 -418
  222. data/bundler/lib/bundler/vendor/net-http-persistent/.document +1 -0
  223. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  224. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +4 -3
  225. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +23 -11
  226. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +1 -1
  227. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +102 -64
  228. data/bundler/lib/bundler/vendor/pub_grub/.document +1 -0
  229. data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  230. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  231. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  232. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  233. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
  234. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  235. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  236. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  237. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  238. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +61 -0
  239. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  240. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  241. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
  242. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
  243. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +248 -0
  244. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  245. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  246. data/bundler/lib/bundler/vendor/securerandom/.document +1 -0
  247. data/bundler/lib/bundler/vendor/securerandom/COPYING +56 -0
  248. data/bundler/lib/bundler/vendor/securerandom/lib/securerandom.rb +102 -0
  249. data/bundler/lib/bundler/vendor/thor/.document +1 -0
  250. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +3 -2
  251. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +1 -1
  252. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +1 -1
  253. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +11 -15
  254. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -4
  255. data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +15 -15
  256. data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +140 -14
  257. data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +13 -4
  258. data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +4 -0
  259. data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +16 -25
  260. data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +12 -1
  261. data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +1 -1
  262. data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +2 -2
  263. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +17 -1
  264. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +33 -17
  265. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +28 -9
  266. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +46 -7
  267. data/bundler/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +2 -2
  268. data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +40 -30
  269. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +35 -159
  270. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +1 -46
  271. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
  272. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +1 -46
  273. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +118 -0
  274. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
  275. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
  276. data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  277. data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
  278. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  279. data/bundler/lib/bundler/vendor/thor/lib/thor.rb +166 -8
  280. data/bundler/lib/bundler/vendor/tsort/.document +1 -0
  281. data/bundler/lib/bundler/vendor/tsort/lib/tsort.rb +3 -0
  282. data/bundler/lib/bundler/vendor/uri/.document +1 -0
  283. data/bundler/lib/bundler/vendor/uri/COPYING +56 -0
  284. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +343 -148
  285. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +10 -4
  286. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +3 -2
  287. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +44 -33
  288. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
  289. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
  290. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  291. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  292. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
  293. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +25 -12
  294. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +130 -38
  295. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  296. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
  297. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
  298. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +12 -11
  299. data/bundler/lib/bundler/vendored_net_http.rb +23 -0
  300. data/bundler/lib/bundler/vendored_persistent.rb +0 -36
  301. data/bundler/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
  302. data/bundler/lib/bundler/vendored_securerandom.rb +12 -0
  303. data/bundler/lib/bundler/vendored_timeout.rb +12 -0
  304. data/bundler/lib/bundler/vendored_uri.rb +18 -1
  305. data/bundler/lib/bundler/version.rb +5 -1
  306. data/bundler/lib/bundler/vlad.rb +1 -1
  307. data/bundler/lib/bundler/worker.rb +5 -7
  308. data/bundler/lib/bundler/yaml_serializer.rb +22 -13
  309. data/bundler/lib/bundler.rb +155 -148
  310. data/{bundler → doc/bundler}/UPGRADING.md +11 -4
  311. data/{CONTRIBUTING.md → doc/rubygems/CONTRIBUTING.md} +40 -17
  312. data/doc/rubygems/POLICIES.md +204 -0
  313. data/{test/rubygems/fake_certlib/openssl.rb → exe/gem} +5 -1
  314. data/{bin → exe}/update_rubygems +12 -10
  315. data/lib/rubygems/available_set.rb +8 -7
  316. data/lib/rubygems/basic_specification.rb +90 -52
  317. data/lib/rubygems/bundler_version_finder.rb +6 -6
  318. data/lib/rubygems/ci_detector.rb +75 -0
  319. data/lib/rubygems/command.rb +68 -64
  320. data/lib/rubygems/command_manager.rb +39 -24
  321. data/lib/rubygems/commands/build_command.rb +14 -19
  322. data/lib/rubygems/commands/cert_command.rb +39 -39
  323. data/lib/rubygems/commands/check_command.rb +30 -25
  324. data/lib/rubygems/commands/cleanup_command.rb +32 -43
  325. data/lib/rubygems/commands/contents_command.rb +33 -25
  326. data/lib/rubygems/commands/dependency_command.rb +22 -23
  327. data/lib/rubygems/commands/environment_command.rb +8 -9
  328. data/lib/rubygems/commands/exec_command.rb +247 -0
  329. data/lib/rubygems/commands/fetch_command.rb +25 -10
  330. data/lib/rubygems/commands/generate_index_command.rb +40 -74
  331. data/lib/rubygems/commands/help_command.rb +15 -14
  332. data/lib/rubygems/commands/info_command.rb +5 -5
  333. data/lib/rubygems/commands/install_command.rb +31 -38
  334. data/lib/rubygems/commands/list_command.rb +6 -5
  335. data/lib/rubygems/commands/lock_command.rb +6 -5
  336. data/lib/rubygems/commands/mirror_command.rb +4 -3
  337. data/lib/rubygems/commands/open_command.rb +11 -12
  338. data/lib/rubygems/commands/outdated_command.rb +6 -5
  339. data/lib/rubygems/commands/owner_command.rb +23 -22
  340. data/lib/rubygems/commands/pristine_command.rb +83 -62
  341. data/lib/rubygems/commands/push_command.rb +38 -13
  342. data/lib/rubygems/commands/query_command.rb +11 -11
  343. data/lib/rubygems/commands/rdoc_command.rb +23 -28
  344. data/lib/rubygems/commands/rebuild_command.rb +262 -0
  345. data/lib/rubygems/commands/search_command.rb +6 -5
  346. data/lib/rubygems/commands/server_command.rb +4 -3
  347. data/lib/rubygems/commands/setup_command.rb +137 -154
  348. data/lib/rubygems/commands/signin_command.rb +10 -9
  349. data/lib/rubygems/commands/signout_command.rb +8 -7
  350. data/lib/rubygems/commands/sources_command.rb +34 -33
  351. data/lib/rubygems/commands/specification_command.rb +25 -20
  352. data/lib/rubygems/commands/stale_command.rb +5 -4
  353. data/lib/rubygems/commands/uninstall_command.rb +66 -59
  354. data/lib/rubygems/commands/unpack_command.rb +23 -30
  355. data/lib/rubygems/commands/update_command.rb +62 -94
  356. data/lib/rubygems/commands/which_command.rb +9 -8
  357. data/lib/rubygems/commands/yank_command.rb +14 -13
  358. data/lib/rubygems/compatibility.rb +5 -6
  359. data/lib/rubygems/config_file.rb +160 -50
  360. data/lib/rubygems/core_ext/kernel_gem.rb +3 -10
  361. data/lib/rubygems/core_ext/kernel_require.rb +88 -114
  362. data/lib/rubygems/core_ext/kernel_warn.rb +30 -39
  363. data/lib/rubygems/core_ext/tcpsocket_init.rb +4 -2
  364. data/lib/rubygems/defaults.rb +53 -22
  365. data/lib/rubygems/dependency.rb +34 -36
  366. data/lib/rubygems/dependency_installer.rb +52 -56
  367. data/lib/rubygems/dependency_list.rb +8 -7
  368. data/lib/rubygems/deprecate.rb +80 -75
  369. data/lib/rubygems/doctor.rb +23 -22
  370. data/lib/rubygems/errors.rb +6 -8
  371. data/lib/rubygems/exceptions.rb +20 -18
  372. data/lib/rubygems/ext/build_error.rb +2 -1
  373. data/lib/rubygems/ext/builder.rb +56 -32
  374. data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +9 -5
  375. data/lib/rubygems/ext/cargo_builder.rb +158 -131
  376. data/lib/rubygems/ext/cmake_builder.rb +9 -4
  377. data/lib/rubygems/ext/configure_builder.rb +9 -3
  378. data/lib/rubygems/ext/ext_conf_builder.rb +19 -15
  379. data/lib/rubygems/ext/rake_builder.rb +14 -7
  380. data/lib/rubygems/ext.rb +8 -7
  381. data/lib/rubygems/gem_runner.rb +23 -9
  382. data/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb +163 -0
  383. data/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +105 -0
  384. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +80 -0
  385. data/lib/rubygems/gemcutter_utilities.rb +141 -63
  386. data/lib/rubygems/gemspec_helpers.rb +19 -0
  387. data/lib/rubygems/install_default_message.rb +3 -2
  388. data/lib/rubygems/install_message.rb +3 -2
  389. data/lib/rubygems/install_update_options.rb +72 -67
  390. data/lib/rubygems/installer.rb +148 -130
  391. data/lib/rubygems/installer_uninstaller_utils.rb +2 -4
  392. data/lib/rubygems/local_remote_options.rb +24 -28
  393. data/lib/rubygems/name_tuple.rb +10 -11
  394. data/lib/rubygems/package/digest_io.rb +2 -1
  395. data/lib/rubygems/package/file_source.rb +3 -2
  396. data/lib/rubygems/package/io_source.rb +1 -0
  397. data/lib/rubygems/package/old.rb +11 -10
  398. data/lib/rubygems/package/source.rb +1 -0
  399. data/lib/rubygems/package/tar_header.rb +125 -91
  400. data/lib/rubygems/package/tar_reader/entry.rb +106 -29
  401. data/lib/rubygems/package/tar_reader.rb +16 -39
  402. data/lib/rubygems/package/tar_writer.rb +29 -26
  403. data/lib/rubygems/package.rb +122 -84
  404. data/lib/rubygems/package_task.rb +7 -6
  405. data/lib/rubygems/path_support.rb +11 -11
  406. data/lib/rubygems/platform.rb +119 -70
  407. data/lib/rubygems/psych_tree.rb +6 -1
  408. data/lib/rubygems/query_utils.rb +46 -48
  409. data/lib/rubygems/rdoc.rb +13 -3
  410. data/lib/rubygems/remote_fetcher.rb +47 -39
  411. data/lib/rubygems/request/connection_pools.rb +6 -6
  412. data/lib/rubygems/request/http_pool.rb +2 -1
  413. data/lib/rubygems/request/https_pool.rb +1 -0
  414. data/lib/rubygems/request.rb +48 -44
  415. data/lib/rubygems/request_set/gem_dependency_api.rb +141 -144
  416. data/lib/rubygems/request_set/lockfile/parser.rb +31 -30
  417. data/lib/rubygems/request_set/lockfile/tokenizer.rb +24 -14
  418. data/lib/rubygems/request_set/lockfile.rb +11 -15
  419. data/lib/rubygems/request_set.rb +25 -23
  420. data/lib/rubygems/requirement.rb +30 -27
  421. data/lib/rubygems/resolver/activation_request.rb +7 -10
  422. data/lib/rubygems/resolver/api_set/gem_parser.rb +7 -3
  423. data/lib/rubygems/resolver/api_set.rb +20 -13
  424. data/lib/rubygems/resolver/api_specification.rb +8 -7
  425. data/lib/rubygems/resolver/best_set.rb +5 -32
  426. data/lib/rubygems/resolver/composed_set.rb +4 -3
  427. data/lib/rubygems/resolver/conflict.rb +14 -21
  428. data/lib/rubygems/resolver/current_set.rb +1 -0
  429. data/lib/rubygems/resolver/dependency_request.rb +3 -2
  430. data/lib/rubygems/resolver/git_set.rb +2 -2
  431. data/lib/rubygems/resolver/git_specification.rb +7 -6
  432. data/lib/rubygems/resolver/index_set.rb +10 -9
  433. data/lib/rubygems/resolver/index_specification.rb +8 -6
  434. data/lib/rubygems/resolver/installed_specification.rb +6 -5
  435. data/lib/rubygems/resolver/installer_set.rb +19 -22
  436. data/lib/rubygems/resolver/local_specification.rb +4 -3
  437. data/lib/rubygems/resolver/lock_set.rb +6 -5
  438. data/lib/rubygems/resolver/lock_specification.rb +5 -4
  439. data/lib/rubygems/resolver/requirement_list.rb +1 -0
  440. data/lib/rubygems/resolver/set.rb +1 -0
  441. data/lib/rubygems/resolver/source_set.rb +2 -0
  442. data/lib/rubygems/resolver/spec_specification.rb +8 -0
  443. data/lib/rubygems/resolver/specification.rb +2 -1
  444. data/lib/rubygems/resolver/stats.rb +2 -1
  445. data/lib/rubygems/resolver/vendor_set.rb +2 -1
  446. data/lib/rubygems/resolver/vendor_specification.rb +4 -3
  447. data/lib/rubygems/resolver.rb +51 -57
  448. data/lib/rubygems/s3_uri_signer.rb +18 -16
  449. data/lib/rubygems/safe_marshal/elements.rb +146 -0
  450. data/lib/rubygems/safe_marshal/reader.rb +325 -0
  451. data/lib/rubygems/safe_marshal/visitors/stream_printer.rb +31 -0
  452. data/lib/rubygems/safe_marshal/visitors/to_ruby.rb +428 -0
  453. data/lib/rubygems/safe_marshal/visitors/visitor.rb +74 -0
  454. data/lib/rubygems/safe_marshal.rb +74 -0
  455. data/lib/rubygems/safe_yaml.rb +14 -26
  456. data/lib/rubygems/security/policies.rb +48 -49
  457. data/lib/rubygems/security/policy.rb +25 -28
  458. data/lib/rubygems/security/signer.rb +16 -7
  459. data/lib/rubygems/security/trust_dir.rb +12 -13
  460. data/lib/rubygems/security.rb +40 -66
  461. data/lib/rubygems/security_option.rb +7 -6
  462. data/lib/rubygems/shellwords.rb +3 -0
  463. data/lib/rubygems/source/git.rb +34 -31
  464. data/lib/rubygems/source/installed.rb +4 -3
  465. data/lib/rubygems/source/local.rb +49 -49
  466. data/lib/rubygems/source/lock.rb +2 -3
  467. data/lib/rubygems/source/specific_file.rb +6 -4
  468. data/lib/rubygems/source/vendor.rb +1 -2
  469. data/lib/rubygems/source.rb +37 -31
  470. data/lib/rubygems/source_list.rb +8 -8
  471. data/lib/rubygems/spec_fetcher.rb +95 -66
  472. data/lib/rubygems/specification.rb +342 -404
  473. data/lib/rubygems/specification_policy.rb +147 -75
  474. data/lib/rubygems/specification_record.rb +212 -0
  475. data/lib/rubygems/stub_specification.rb +56 -30
  476. data/lib/rubygems/target_rbconfig.rb +50 -0
  477. data/lib/rubygems/text.rb +3 -4
  478. data/lib/rubygems/uninstaller.rb +67 -48
  479. data/lib/rubygems/update_suggestion.rb +56 -0
  480. data/lib/rubygems/uri.rb +10 -10
  481. data/lib/rubygems/uri_formatter.rb +2 -2
  482. data/lib/rubygems/user_interaction.rb +50 -40
  483. data/lib/rubygems/util/licenses.rb +310 -39
  484. data/lib/rubygems/util/list.rb +4 -1
  485. data/lib/rubygems/util.rb +19 -20
  486. data/lib/rubygems/validator.rb +15 -14
  487. data/lib/rubygems/vendor/molinillo/.document +1 -0
  488. data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  489. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +11 -11
  490. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -1
  491. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -1
  492. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -1
  493. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -1
  494. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  495. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -1
  496. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -1
  497. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -1
  498. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +1 -1
  499. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -3
  500. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/errors.rb +1 -1
  501. data/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
  502. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +2 -2
  503. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/modules/ui.rb +1 -1
  504. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/resolution.rb +4 -4
  505. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/resolver.rb +1 -1
  506. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo/state.rb +1 -1
  507. data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/lib/molinillo.rb +2 -2
  508. data/lib/rubygems/vendor/net-http/.document +1 -0
  509. data/lib/rubygems/vendor/net-http/COPYING +56 -0
  510. data/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb +34 -0
  511. data/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb +414 -0
  512. data/lib/rubygems/vendor/net-http/lib/net/http/header.rb +981 -0
  513. data/lib/rubygems/vendor/net-http/lib/net/http/proxy_delta.rb +17 -0
  514. data/lib/rubygems/vendor/net-http/lib/net/http/request.rb +88 -0
  515. data/lib/rubygems/vendor/net-http/lib/net/http/requests.rb +430 -0
  516. data/lib/rubygems/vendor/net-http/lib/net/http/response.rb +738 -0
  517. data/lib/rubygems/vendor/net-http/lib/net/http/responses.rb +1174 -0
  518. data/lib/rubygems/vendor/net-http/lib/net/http/status.rb +84 -0
  519. data/lib/rubygems/vendor/net-http/lib/net/http.rb +2580 -0
  520. data/lib/rubygems/vendor/net-http/lib/net/https.rb +23 -0
  521. data/lib/rubygems/vendor/net-protocol/.document +1 -0
  522. data/lib/rubygems/vendor/net-protocol/lib/net/protocol.rb +544 -0
  523. data/lib/rubygems/vendor/optparse/.document +1 -0
  524. data/lib/rubygems/vendor/optparse/COPYING +56 -0
  525. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/ac.rb +16 -0
  526. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/kwargs.rb +8 -3
  527. data/lib/rubygems/vendor/optparse/lib/optparse/uri.rb +7 -0
  528. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/version.rb +9 -0
  529. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse.rb +206 -83
  530. data/lib/rubygems/vendor/resolv/.document +1 -0
  531. data/lib/rubygems/vendor/resolv/COPYING +56 -0
  532. data/lib/rubygems/vendor/resolv/lib/resolv.rb +3455 -0
  533. data/lib/rubygems/vendor/securerandom/.document +1 -0
  534. data/lib/rubygems/vendor/securerandom/COPYING +56 -0
  535. data/lib/rubygems/vendor/securerandom/lib/securerandom.rb +102 -0
  536. data/lib/rubygems/vendor/timeout/.document +1 -0
  537. data/lib/rubygems/vendor/timeout/COPYING +56 -0
  538. data/lib/rubygems/vendor/timeout/lib/timeout.rb +198 -0
  539. data/lib/rubygems/vendor/tsort/.document +1 -0
  540. data/lib/rubygems/vendor/tsort/lib/tsort.rb +455 -0
  541. data/lib/rubygems/vendor/uri/.document +1 -0
  542. data/lib/rubygems/vendor/uri/COPYING +56 -0
  543. data/lib/rubygems/vendor/uri/lib/uri/common.rb +876 -0
  544. data/lib/rubygems/vendor/uri/lib/uri/file.rb +100 -0
  545. data/lib/rubygems/vendor/uri/lib/uri/ftp.rb +267 -0
  546. data/lib/rubygems/vendor/uri/lib/uri/generic.rb +1578 -0
  547. data/lib/rubygems/vendor/uri/lib/uri/http.rb +125 -0
  548. data/lib/rubygems/vendor/uri/lib/uri/https.rb +23 -0
  549. data/lib/rubygems/vendor/uri/lib/uri/ldap.rb +261 -0
  550. data/lib/rubygems/vendor/uri/lib/uri/ldaps.rb +22 -0
  551. data/lib/rubygems/vendor/uri/lib/uri/mailto.rb +293 -0
  552. data/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb +546 -0
  553. data/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb +206 -0
  554. data/lib/rubygems/vendor/uri/lib/uri/version.rb +6 -0
  555. data/lib/rubygems/vendor/uri/lib/uri/ws.rb +83 -0
  556. data/lib/rubygems/vendor/uri/lib/uri/wss.rb +23 -0
  557. data/lib/rubygems/vendor/uri/lib/uri.rb +104 -0
  558. data/{bundler/lib/bundler → lib/rubygems}/vendored_molinillo.rb +0 -1
  559. data/lib/rubygems/vendored_net_http.rb +5 -0
  560. data/lib/rubygems/vendored_optparse.rb +3 -0
  561. data/lib/rubygems/vendored_securerandom.rb +3 -0
  562. data/lib/rubygems/vendored_timeout.rb +5 -0
  563. data/lib/rubygems/vendored_tsort.rb +3 -0
  564. data/lib/rubygems/version.rb +57 -45
  565. data/lib/rubygems/version_option.rb +6 -8
  566. data/lib/rubygems/yaml_serializer.rb +98 -0
  567. data/lib/rubygems.rb +191 -133
  568. data/rubygems-update.gemspec +16 -9
  569. data/setup.rb +12 -9
  570. metadata +233 -307
  571. data/POLICIES.md +0 -100
  572. data/bin/gem +0 -13
  573. data/bundler/lib/bundler/dep_proxy.rb +0 -55
  574. data/bundler/lib/bundler/templates/gems.rb +0 -5
  575. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -5
  576. data/bundler/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  577. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  578. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  579. data/bundler/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  580. data/bundler/lib/bundler/version_ranges.rb +0 -122
  581. data/lib/rubygems/indexer.rb +0 -427
  582. data/lib/rubygems/mock_gem_ui.rb +0 -85
  583. data/lib/rubygems/optparse/lib/optparse/uri.rb +0 -7
  584. data/lib/rubygems/optparse.rb +0 -3
  585. data/lib/rubygems/resolver/molinillo/LICENSE +0 -9
  586. data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  587. data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  588. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  589. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  590. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  591. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  592. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  593. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  594. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  595. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  596. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  597. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  598. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +0 -143
  599. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  600. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  601. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +0 -67
  602. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +0 -839
  603. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +0 -46
  604. data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +0 -58
  605. data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +0 -11
  606. data/lib/rubygems/resolver/molinillo.rb +0 -2
  607. data/lib/rubygems/tsort/LICENSE.txt +0 -22
  608. data/lib/rubygems/tsort/lib/tsort.rb +0 -454
  609. data/lib/rubygems/tsort.rb +0 -3
  610. data/test/rubygems/alternate_cert.pem +0 -19
  611. data/test/rubygems/alternate_cert_32.pem +0 -19
  612. data/test/rubygems/alternate_key.pem +0 -27
  613. data/test/rubygems/bad_rake.rb +0 -2
  614. data/test/rubygems/ca_cert.pem +0 -77
  615. data/test/rubygems/child_cert.pem +0 -20
  616. data/test/rubygems/child_cert_32.pem +0 -20
  617. data/test/rubygems/child_key.pem +0 -27
  618. data/test/rubygems/client.pem +0 -107
  619. data/test/rubygems/data/excon-0.7.7.gemspec.rz +0 -0
  620. data/test/rubygems/data/gem-private_key.pem +0 -27
  621. data/test/rubygems/data/gem-public_cert.pem +0 -20
  622. data/test/rubygems/data/null-required-ruby-version.gemspec.rz +0 -0
  623. data/test/rubygems/data/null-required-rubygems-version.gemspec.rz +0 -0
  624. data/test/rubygems/data/pry-0.4.7.gemspec.rz +0 -0
  625. data/test/rubygems/encrypted_private_key.pem +0 -30
  626. data/test/rubygems/expired_cert.pem +0 -19
  627. data/test/rubygems/foo/discover.rb +0 -1
  628. data/test/rubygems/future_cert.pem +0 -19
  629. data/test/rubygems/future_cert_32.pem +0 -19
  630. data/test/rubygems/good_rake.rb +0 -2
  631. data/test/rubygems/grandchild_cert.pem +0 -20
  632. data/test/rubygems/grandchild_cert_32.pem +0 -20
  633. data/test/rubygems/grandchild_key.pem +0 -27
  634. data/test/rubygems/helper.rb +0 -1622
  635. data/test/rubygems/installer_test_case.rb +0 -247
  636. data/test/rubygems/invalid_client.pem +0 -49
  637. data/test/rubygems/invalid_issuer_cert.pem +0 -20
  638. data/test/rubygems/invalid_issuer_cert_32.pem +0 -20
  639. data/test/rubygems/invalid_key.pem +0 -27
  640. data/test/rubygems/invalid_signer_cert.pem +0 -19
  641. data/test/rubygems/invalid_signer_cert_32.pem +0 -19
  642. data/test/rubygems/invalidchild_cert.pem +0 -20
  643. data/test/rubygems/invalidchild_cert_32.pem +0 -20
  644. data/test/rubygems/invalidchild_key.pem +0 -27
  645. data/test/rubygems/package/tar_test_case.rb +0 -139
  646. data/test/rubygems/packages/ascii_binder-0.1.10.1.gem +0 -0
  647. data/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem +0 -0
  648. data/test/rubygems/plugin/exception/rubygems_plugin.rb +0 -3
  649. data/test/rubygems/plugin/load/rubygems_plugin.rb +0 -4
  650. data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +0 -3
  651. data/test/rubygems/private3072_key.pem +0 -40
  652. data/test/rubygems/private_ec_key.pem +0 -9
  653. data/test/rubygems/private_key.pem +0 -27
  654. data/test/rubygems/public3072_cert.pem +0 -25
  655. data/test/rubygems/public_cert.pem +0 -20
  656. data/test/rubygems/public_cert_32.pem +0 -19
  657. data/test/rubygems/public_key.pem +0 -9
  658. data/test/rubygems/rubygems/commands/crash_command.rb +0 -4
  659. data/test/rubygems/rubygems_plugin.rb +0 -23
  660. data/test/rubygems/sff/discover.rb +0 -1
  661. data/test/rubygems/simple_gem.rb +0 -67
  662. data/test/rubygems/specifications/bar-0.0.2.gemspec +0 -7
  663. data/test/rubygems/specifications/foo-0.0.1-x86-mswin32.gemspec +0 -0
  664. data/test/rubygems/specifications/rubyforge-0.0.1.gemspec +0 -12
  665. data/test/rubygems/ssl_cert.pem +0 -80
  666. data/test/rubygems/ssl_key.pem +0 -27
  667. data/test/rubygems/test_bundled_ca.rb +0 -60
  668. data/test/rubygems/test_config.rb +0 -27
  669. data/test/rubygems/test_deprecate.rb +0 -157
  670. data/test/rubygems/test_exit.rb +0 -11
  671. data/test/rubygems/test_gem.rb +0 -2112
  672. data/test/rubygems/test_gem_available_set.rb +0 -129
  673. data/test/rubygems/test_gem_bundler_version_finder.rb +0 -125
  674. data/test/rubygems/test_gem_command.rb +0 -400
  675. data/test/rubygems/test_gem_command_manager.rb +0 -334
  676. data/test/rubygems/test_gem_commands_build_command.rb +0 -727
  677. data/test/rubygems/test_gem_commands_cert_command.rb +0 -867
  678. data/test/rubygems/test_gem_commands_check_command.rb +0 -67
  679. data/test/rubygems/test_gem_commands_cleanup_command.rb +0 -291
  680. data/test/rubygems/test_gem_commands_contents_command.rb +0 -270
  681. data/test/rubygems/test_gem_commands_dependency_command.rb +0 -227
  682. data/test/rubygems/test_gem_commands_environment_command.rb +0 -167
  683. data/test/rubygems/test_gem_commands_fetch_command.rb +0 -257
  684. data/test/rubygems/test_gem_commands_generate_index_command.rb +0 -80
  685. data/test/rubygems/test_gem_commands_help_command.rb +0 -93
  686. data/test/rubygems/test_gem_commands_info_command.rb +0 -43
  687. data/test/rubygems/test_gem_commands_install_command.rb +0 -1553
  688. data/test/rubygems/test_gem_commands_list_command.rb +0 -32
  689. data/test/rubygems/test_gem_commands_lock_command.rb +0 -66
  690. data/test/rubygems/test_gem_commands_mirror.rb +0 -19
  691. data/test/rubygems/test_gem_commands_open_command.rb +0 -97
  692. data/test/rubygems/test_gem_commands_outdated_command.rb +0 -49
  693. data/test/rubygems/test_gem_commands_owner_command.rb +0 -326
  694. data/test/rubygems/test_gem_commands_pristine_command.rb +0 -659
  695. data/test/rubygems/test_gem_commands_push_command.rb +0 -477
  696. data/test/rubygems/test_gem_commands_query_command.rb +0 -857
  697. data/test/rubygems/test_gem_commands_search_command.rb +0 -15
  698. data/test/rubygems/test_gem_commands_server_command.rb +0 -19
  699. data/test/rubygems/test_gem_commands_setup_command.rb +0 -447
  700. data/test/rubygems/test_gem_commands_signin_command.rb +0 -219
  701. data/test/rubygems/test_gem_commands_signout_command.rb +0 -30
  702. data/test/rubygems/test_gem_commands_sources_command.rb +0 -534
  703. data/test/rubygems/test_gem_commands_specification_command.rb +0 -276
  704. data/test/rubygems/test_gem_commands_stale_command.rb +0 -42
  705. data/test/rubygems/test_gem_commands_uninstall_command.rb +0 -504
  706. data/test/rubygems/test_gem_commands_unpack_command.rb +0 -223
  707. data/test/rubygems/test_gem_commands_update_command.rb +0 -835
  708. data/test/rubygems/test_gem_commands_which_command.rb +0 -84
  709. data/test/rubygems/test_gem_commands_yank_command.rb +0 -180
  710. data/test/rubygems/test_gem_config_file.rb +0 -504
  711. data/test/rubygems/test_gem_dependency.rb +0 -395
  712. data/test/rubygems/test_gem_dependency_installer.rb +0 -1155
  713. data/test/rubygems/test_gem_dependency_list.rb +0 -264
  714. data/test/rubygems/test_gem_dependency_resolution_error.rb +0 -26
  715. data/test/rubygems/test_gem_doctor.rb +0 -194
  716. data/test/rubygems/test_gem_ext_builder.rb +0 -338
  717. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore +0 -1
  718. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +0 -243
  719. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +0 -10
  720. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +0 -21
  721. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +0 -10
  722. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/src/lib.rs +0 -27
  723. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore +0 -1
  724. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +0 -243
  725. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +0 -10
  726. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +0 -21
  727. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec +0 -8
  728. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +0 -39
  729. data/test/rubygems/test_gem_ext_cargo_builder.rb +0 -178
  730. data/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +0 -33
  731. data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +0 -75
  732. data/test/rubygems/test_gem_ext_cmake_builder.rb +0 -83
  733. data/test/rubygems/test_gem_ext_configure_builder.rb +0 -79
  734. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +0 -230
  735. data/test/rubygems/test_gem_ext_rake_builder.rb +0 -112
  736. data/test/rubygems/test_gem_gem_runner.rb +0 -113
  737. data/test/rubygems/test_gem_gemcutter_utilities.rb +0 -272
  738. data/test/rubygems/test_gem_impossible_dependencies_error.rb +0 -59
  739. data/test/rubygems/test_gem_indexer.rb +0 -361
  740. data/test/rubygems/test_gem_install_update_options.rb +0 -207
  741. data/test/rubygems/test_gem_installer.rb +0 -2394
  742. data/test/rubygems/test_gem_local_remote_options.rb +0 -132
  743. data/test/rubygems/test_gem_name_tuple.rb +0 -42
  744. data/test/rubygems/test_gem_package.rb +0 -1178
  745. data/test/rubygems/test_gem_package_old.rb +0 -90
  746. data/test/rubygems/test_gem_package_tar_header.rb +0 -225
  747. data/test/rubygems/test_gem_package_tar_reader.rb +0 -87
  748. data/test/rubygems/test_gem_package_tar_reader_entry.rb +0 -152
  749. data/test/rubygems/test_gem_package_tar_writer.rb +0 -330
  750. data/test/rubygems/test_gem_package_task.rb +0 -117
  751. data/test/rubygems/test_gem_path_support.rb +0 -138
  752. data/test/rubygems/test_gem_platform.rb +0 -391
  753. data/test/rubygems/test_gem_rdoc.rb +0 -136
  754. data/test/rubygems/test_gem_remote_fetcher.rb +0 -1226
  755. data/test/rubygems/test_gem_request.rb +0 -541
  756. data/test/rubygems/test_gem_request_connection_pools.rb +0 -150
  757. data/test/rubygems/test_gem_request_set.rb +0 -671
  758. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +0 -847
  759. data/test/rubygems/test_gem_request_set_lockfile.rb +0 -468
  760. data/test/rubygems/test_gem_request_set_lockfile_parser.rb +0 -543
  761. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +0 -306
  762. data/test/rubygems/test_gem_requirement.rb +0 -498
  763. data/test/rubygems/test_gem_resolver.rb +0 -791
  764. data/test/rubygems/test_gem_resolver_activation_request.rb +0 -42
  765. data/test/rubygems/test_gem_resolver_api_set.rb +0 -209
  766. data/test/rubygems/test_gem_resolver_api_specification.rb +0 -166
  767. data/test/rubygems/test_gem_resolver_best_set.rb +0 -158
  768. data/test/rubygems/test_gem_resolver_composed_set.rb +0 -43
  769. data/test/rubygems/test_gem_resolver_conflict.rb +0 -81
  770. data/test/rubygems/test_gem_resolver_dependency_request.rb +0 -82
  771. data/test/rubygems/test_gem_resolver_git_set.rb +0 -187
  772. data/test/rubygems/test_gem_resolver_git_specification.rb +0 -113
  773. data/test/rubygems/test_gem_resolver_index_set.rb +0 -87
  774. data/test/rubygems/test_gem_resolver_index_specification.rb +0 -92
  775. data/test/rubygems/test_gem_resolver_installed_specification.rb +0 -46
  776. data/test/rubygems/test_gem_resolver_installer_set.rb +0 -275
  777. data/test/rubygems/test_gem_resolver_local_specification.rb +0 -43
  778. data/test/rubygems/test_gem_resolver_lock_set.rb +0 -61
  779. data/test/rubygems/test_gem_resolver_lock_specification.rb +0 -97
  780. data/test/rubygems/test_gem_resolver_requirement_list.rb +0 -18
  781. data/test/rubygems/test_gem_resolver_specification.rb +0 -62
  782. data/test/rubygems/test_gem_resolver_vendor_set.rb +0 -81
  783. data/test/rubygems/test_gem_resolver_vendor_specification.rb +0 -81
  784. data/test/rubygems/test_gem_security.rb +0 -340
  785. data/test/rubygems/test_gem_security_policy.rb +0 -535
  786. data/test/rubygems/test_gem_security_signer.rb +0 -217
  787. data/test/rubygems/test_gem_security_trust_dir.rb +0 -98
  788. data/test/rubygems/test_gem_silent_ui.rb +0 -116
  789. data/test/rubygems/test_gem_source.rb +0 -253
  790. data/test/rubygems/test_gem_source_fetch_problem.rb +0 -36
  791. data/test/rubygems/test_gem_source_git.rb +0 -303
  792. data/test/rubygems/test_gem_source_installed.rb +0 -34
  793. data/test/rubygems/test_gem_source_list.rb +0 -118
  794. data/test/rubygems/test_gem_source_local.rb +0 -106
  795. data/test/rubygems/test_gem_source_lock.rb +0 -112
  796. data/test/rubygems/test_gem_source_specific_file.rb +0 -75
  797. data/test/rubygems/test_gem_source_subpath_problem.rb +0 -49
  798. data/test/rubygems/test_gem_source_vendor.rb +0 -29
  799. data/test/rubygems/test_gem_spec_fetcher.rb +0 -337
  800. data/test/rubygems/test_gem_specification.rb +0 -3756
  801. data/test/rubygems/test_gem_stream_ui.rb +0 -224
  802. data/test/rubygems/test_gem_stub_specification.rb +0 -277
  803. data/test/rubygems/test_gem_text.rb +0 -102
  804. data/test/rubygems/test_gem_uninstaller.rb +0 -674
  805. data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +0 -30
  806. data/test/rubygems/test_gem_uri.rb +0 -39
  807. data/test/rubygems/test_gem_uri_formatter.rb +0 -26
  808. data/test/rubygems/test_gem_util.rb +0 -90
  809. data/test/rubygems/test_gem_validator.rb +0 -42
  810. data/test/rubygems/test_gem_version.rb +0 -295
  811. data/test/rubygems/test_gem_version_option.rb +0 -164
  812. data/test/rubygems/test_kernel.rb +0 -129
  813. data/test/rubygems/test_project_sanity.rb +0 -20
  814. data/test/rubygems/test_remote_fetch_error.rb +0 -19
  815. data/test/rubygems/test_require.rb +0 -719
  816. data/test/rubygems/test_rubygems.rb +0 -74
  817. data/test/rubygems/utilities.rb +0 -371
  818. data/test/rubygems/wrong_key_cert.pem +0 -19
  819. data/test/rubygems/wrong_key_cert_32.pem +0 -19
  820. data/test/test_changelog_generator.rb +0 -17
  821. /data/{lib/rubygems/optparse → bundler/lib/bundler/vendor/connection_pool}/.document +0 -0
  822. /data/{lib/rubygems/tsort → bundler/lib/bundler/vendor/fileutils}/.document +0 -0
  823. /data/{lib/rubygems/optparse → bundler/lib/bundler/vendor/fileutils}/COPYING +0 -0
  824. /data/{MAINTAINERS.txt → doc/MAINTAINERS.txt} +0 -0
  825. /data/{UPGRADING.md → doc/rubygems/UPGRADING.md} +0 -0
  826. /data/{bundler/lib/bundler → lib/rubygems}/vendor/molinillo/LICENSE +0 -0
  827. /data/{bundler/lib/bundler/vendor/fileutils → lib/rubygems/vendor/net-protocol}/LICENSE.txt +0 -0
  828. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optionparser.rb +0 -0
  829. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/date.rb +0 -0
  830. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/shellwords.rb +0 -0
  831. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/time.rb +0 -0
  832. /data/{bundler/lib/bundler/vendor/uri → lib/rubygems/vendor/tsort}/LICENSE.txt +0 -0
@@ -0,0 +1,3455 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+ require_relative '../../timeout/lib/timeout'
5
+ require 'io/wait'
6
+ require_relative '../../../vendored_securerandom'
7
+
8
+ # Gem::Resolv is a thread-aware DNS resolver library written in Ruby. Gem::Resolv can
9
+ # handle multiple DNS requests concurrently without blocking the entire Ruby
10
+ # interpreter.
11
+ #
12
+ # See also resolv-replace.rb to replace the libc resolver with Gem::Resolv.
13
+ #
14
+ # Gem::Resolv can look up various DNS resources using the DNS module directly.
15
+ #
16
+ # Examples:
17
+ #
18
+ # p Gem::Resolv.getaddress "www.ruby-lang.org"
19
+ # p Gem::Resolv.getname "210.251.121.214"
20
+ #
21
+ # Gem::Resolv::DNS.open do |dns|
22
+ # ress = dns.getresources "www.ruby-lang.org", Gem::Resolv::DNS::Resource::IN::A
23
+ # p ress.map(&:address)
24
+ # ress = dns.getresources "ruby-lang.org", Gem::Resolv::DNS::Resource::IN::MX
25
+ # p ress.map { |r| [r.exchange.to_s, r.preference] }
26
+ # end
27
+ #
28
+ #
29
+ # == Bugs
30
+ #
31
+ # * NIS is not supported.
32
+ # * /etc/nsswitch.conf is not supported.
33
+
34
+ class Gem::Resolv
35
+
36
+ VERSION = "0.6.0"
37
+
38
+ ##
39
+ # Looks up the first IP address for +name+.
40
+
41
+ def self.getaddress(name)
42
+ DefaultResolver.getaddress(name)
43
+ end
44
+
45
+ ##
46
+ # Looks up all IP address for +name+.
47
+
48
+ def self.getaddresses(name)
49
+ DefaultResolver.getaddresses(name)
50
+ end
51
+
52
+ ##
53
+ # Iterates over all IP addresses for +name+.
54
+
55
+ def self.each_address(name, &block)
56
+ DefaultResolver.each_address(name, &block)
57
+ end
58
+
59
+ ##
60
+ # Looks up the hostname of +address+.
61
+
62
+ def self.getname(address)
63
+ DefaultResolver.getname(address)
64
+ end
65
+
66
+ ##
67
+ # Looks up all hostnames for +address+.
68
+
69
+ def self.getnames(address)
70
+ DefaultResolver.getnames(address)
71
+ end
72
+
73
+ ##
74
+ # Iterates over all hostnames for +address+.
75
+
76
+ def self.each_name(address, &proc)
77
+ DefaultResolver.each_name(address, &proc)
78
+ end
79
+
80
+ ##
81
+ # Creates a new Gem::Resolv using +resolvers+.
82
+ #
83
+ # If +resolvers+ is not given, a hash, or +nil+, uses a Hosts resolver and
84
+ # and a DNS resolver. If +resolvers+ is a hash, uses the hash as
85
+ # configuration for the DNS resolver.
86
+
87
+ def initialize(resolvers=(arg_not_set = true; nil), use_ipv6: (keyword_not_set = true; nil))
88
+ if !keyword_not_set && !arg_not_set
89
+ warn "Support for separate use_ipv6 keyword is deprecated, as it is ignored if an argument is provided. Do not provide a positional argument if using the use_ipv6 keyword argument.", uplevel: 1
90
+ end
91
+
92
+ @resolvers = case resolvers
93
+ when Hash, nil
94
+ [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(resolvers || {}))]
95
+ else
96
+ resolvers
97
+ end
98
+ end
99
+
100
+ ##
101
+ # Looks up the first IP address for +name+.
102
+
103
+ def getaddress(name)
104
+ each_address(name) {|address| return address}
105
+ raise ResolvError.new("no address for #{name}")
106
+ end
107
+
108
+ ##
109
+ # Looks up all IP address for +name+.
110
+
111
+ def getaddresses(name)
112
+ ret = []
113
+ each_address(name) {|address| ret << address}
114
+ return ret
115
+ end
116
+
117
+ ##
118
+ # Iterates over all IP addresses for +name+.
119
+
120
+ def each_address(name)
121
+ if AddressRegex =~ name
122
+ yield name
123
+ return
124
+ end
125
+ yielded = false
126
+ @resolvers.each {|r|
127
+ r.each_address(name) {|address|
128
+ yield address.to_s
129
+ yielded = true
130
+ }
131
+ return if yielded
132
+ }
133
+ end
134
+
135
+ ##
136
+ # Looks up the hostname of +address+.
137
+
138
+ def getname(address)
139
+ each_name(address) {|name| return name}
140
+ raise ResolvError.new("no name for #{address}")
141
+ end
142
+
143
+ ##
144
+ # Looks up all hostnames for +address+.
145
+
146
+ def getnames(address)
147
+ ret = []
148
+ each_name(address) {|name| ret << name}
149
+ return ret
150
+ end
151
+
152
+ ##
153
+ # Iterates over all hostnames for +address+.
154
+
155
+ def each_name(address)
156
+ yielded = false
157
+ @resolvers.each {|r|
158
+ r.each_name(address) {|name|
159
+ yield name.to_s
160
+ yielded = true
161
+ }
162
+ return if yielded
163
+ }
164
+ end
165
+
166
+ ##
167
+ # Indicates a failure to resolve a name or address.
168
+
169
+ class ResolvError < StandardError; end
170
+
171
+ ##
172
+ # Indicates a timeout resolving a name or address.
173
+
174
+ class ResolvTimeout < Gem::Timeout::Error; end
175
+
176
+ ##
177
+ # Gem::Resolv::Hosts is a hostname resolver that uses the system hosts file.
178
+
179
+ class Hosts
180
+ if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and
181
+ begin
182
+ require 'win32/resolv'
183
+ DefaultFileName = Win32::Resolv.get_hosts_path || IO::NULL
184
+ rescue LoadError
185
+ end
186
+ end
187
+ DefaultFileName ||= '/etc/hosts'
188
+
189
+ ##
190
+ # Creates a new Gem::Resolv::Hosts, using +filename+ for its data source.
191
+
192
+ def initialize(filename = DefaultFileName)
193
+ @filename = filename
194
+ @mutex = Thread::Mutex.new
195
+ @initialized = nil
196
+ end
197
+
198
+ def lazy_initialize # :nodoc:
199
+ @mutex.synchronize {
200
+ unless @initialized
201
+ @name2addr = {}
202
+ @addr2name = {}
203
+ File.open(@filename, 'rb') {|f|
204
+ f.each {|line|
205
+ line.sub!(/#.*/, '')
206
+ addr, *hostnames = line.split(/\s+/)
207
+ next unless addr
208
+ (@addr2name[addr] ||= []).concat(hostnames)
209
+ hostnames.each {|hostname| (@name2addr[hostname] ||= []) << addr}
210
+ }
211
+ }
212
+ @name2addr.each {|name, arr| arr.reverse!}
213
+ @initialized = true
214
+ end
215
+ }
216
+ self
217
+ end
218
+
219
+ ##
220
+ # Gets the IP address of +name+ from the hosts file.
221
+
222
+ def getaddress(name)
223
+ each_address(name) {|address| return address}
224
+ raise ResolvError.new("#{@filename} has no name: #{name}")
225
+ end
226
+
227
+ ##
228
+ # Gets all IP addresses for +name+ from the hosts file.
229
+
230
+ def getaddresses(name)
231
+ ret = []
232
+ each_address(name) {|address| ret << address}
233
+ return ret
234
+ end
235
+
236
+ ##
237
+ # Iterates over all IP addresses for +name+ retrieved from the hosts file.
238
+
239
+ def each_address(name, &proc)
240
+ lazy_initialize
241
+ @name2addr[name]&.each(&proc)
242
+ end
243
+
244
+ ##
245
+ # Gets the hostname of +address+ from the hosts file.
246
+
247
+ def getname(address)
248
+ each_name(address) {|name| return name}
249
+ raise ResolvError.new("#{@filename} has no address: #{address}")
250
+ end
251
+
252
+ ##
253
+ # Gets all hostnames for +address+ from the hosts file.
254
+
255
+ def getnames(address)
256
+ ret = []
257
+ each_name(address) {|name| ret << name}
258
+ return ret
259
+ end
260
+
261
+ ##
262
+ # Iterates over all hostnames for +address+ retrieved from the hosts file.
263
+
264
+ def each_name(address, &proc)
265
+ lazy_initialize
266
+ @addr2name[address]&.each(&proc)
267
+ end
268
+ end
269
+
270
+ ##
271
+ # Gem::Resolv::DNS is a DNS stub resolver.
272
+ #
273
+ # Information taken from the following places:
274
+ #
275
+ # * STD0013
276
+ # * RFC 1035
277
+ # * ftp://ftp.isi.edu/in-notes/iana/assignments/dns-parameters
278
+ # * etc.
279
+
280
+ class DNS
281
+
282
+ ##
283
+ # Default DNS Port
284
+
285
+ Port = 53
286
+
287
+ ##
288
+ # Default DNS UDP packet size
289
+
290
+ UDPSize = 512
291
+
292
+ ##
293
+ # Creates a new DNS resolver. See Gem::Resolv::DNS.new for argument details.
294
+ #
295
+ # Yields the created DNS resolver to the block, if given, otherwise
296
+ # returns it.
297
+
298
+ def self.open(*args)
299
+ dns = new(*args)
300
+ return dns unless block_given?
301
+ begin
302
+ yield dns
303
+ ensure
304
+ dns.close
305
+ end
306
+ end
307
+
308
+ ##
309
+ # Creates a new DNS resolver.
310
+ #
311
+ # +config_info+ can be:
312
+ #
313
+ # nil:: Uses /etc/resolv.conf.
314
+ # String:: Path to a file using /etc/resolv.conf's format.
315
+ # Hash:: Must contain :nameserver, :search and :ndots keys.
316
+ # :nameserver_port can be used to specify port number of nameserver address.
317
+ # :raise_timeout_errors can be used to raise timeout errors
318
+ # as exceptions instead of treating the same as an NXDOMAIN response.
319
+ #
320
+ # The value of :nameserver should be an address string or
321
+ # an array of address strings.
322
+ # - :nameserver => '8.8.8.8'
323
+ # - :nameserver => ['8.8.8.8', '8.8.4.4']
324
+ #
325
+ # The value of :nameserver_port should be an array of
326
+ # pair of nameserver address and port number.
327
+ # - :nameserver_port => [['8.8.8.8', 53], ['8.8.4.4', 53]]
328
+ #
329
+ # Example:
330
+ #
331
+ # Gem::Resolv::DNS.new(:nameserver => ['210.251.121.21'],
332
+ # :search => ['ruby-lang.org'],
333
+ # :ndots => 1)
334
+
335
+ def initialize(config_info=nil)
336
+ @mutex = Thread::Mutex.new
337
+ @config = Config.new(config_info)
338
+ @initialized = nil
339
+ end
340
+
341
+ # Sets the resolver timeouts. This may be a single positive number
342
+ # or an array of positive numbers representing timeouts in seconds.
343
+ # If an array is specified, a DNS request will retry and wait for
344
+ # each successive interval in the array until a successful response
345
+ # is received. Specifying +nil+ reverts to the default timeouts:
346
+ # [ 5, second = 5 * 2 / nameserver_count, 2 * second, 4 * second ]
347
+ #
348
+ # Example:
349
+ #
350
+ # dns.timeouts = 3
351
+ #
352
+ def timeouts=(values)
353
+ @config.timeouts = values
354
+ end
355
+
356
+ def lazy_initialize # :nodoc:
357
+ @mutex.synchronize {
358
+ unless @initialized
359
+ @config.lazy_initialize
360
+ @initialized = true
361
+ end
362
+ }
363
+ self
364
+ end
365
+
366
+ ##
367
+ # Closes the DNS resolver.
368
+
369
+ def close
370
+ @mutex.synchronize {
371
+ if @initialized
372
+ @initialized = false
373
+ end
374
+ }
375
+ end
376
+
377
+ ##
378
+ # Gets the IP address of +name+ from the DNS resolver.
379
+ #
380
+ # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved address will
381
+ # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
382
+
383
+ def getaddress(name)
384
+ each_address(name) {|address| return address}
385
+ raise ResolvError.new("DNS result has no information for #{name}")
386
+ end
387
+
388
+ ##
389
+ # Gets all IP addresses for +name+ from the DNS resolver.
390
+ #
391
+ # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved addresses will
392
+ # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
393
+
394
+ def getaddresses(name)
395
+ ret = []
396
+ each_address(name) {|address| ret << address}
397
+ return ret
398
+ end
399
+
400
+ ##
401
+ # Iterates over all IP addresses for +name+ retrieved from the DNS
402
+ # resolver.
403
+ #
404
+ # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved addresses will
405
+ # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
406
+
407
+ def each_address(name)
408
+ if use_ipv6?
409
+ each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
410
+ end
411
+ each_resource(name, Resource::IN::A) {|resource| yield resource.address}
412
+ end
413
+
414
+ def use_ipv6? # :nodoc:
415
+ @config.lazy_initialize unless @config.instance_variable_get(:@initialized)
416
+
417
+ use_ipv6 = @config.use_ipv6?
418
+ unless use_ipv6.nil?
419
+ return use_ipv6
420
+ end
421
+
422
+ begin
423
+ list = Socket.ip_address_list
424
+ rescue NotImplementedError
425
+ return true
426
+ end
427
+ list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
428
+ end
429
+ private :use_ipv6?
430
+
431
+ ##
432
+ # Gets the hostname for +address+ from the DNS resolver.
433
+ #
434
+ # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
435
+ # name will be a Gem::Resolv::DNS::Name.
436
+
437
+ def getname(address)
438
+ each_name(address) {|name| return name}
439
+ raise ResolvError.new("DNS result has no information for #{address}")
440
+ end
441
+
442
+ ##
443
+ # Gets all hostnames for +address+ from the DNS resolver.
444
+ #
445
+ # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
446
+ # names will be Gem::Resolv::DNS::Name instances.
447
+
448
+ def getnames(address)
449
+ ret = []
450
+ each_name(address) {|name| ret << name}
451
+ return ret
452
+ end
453
+
454
+ ##
455
+ # Iterates over all hostnames for +address+ retrieved from the DNS
456
+ # resolver.
457
+ #
458
+ # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
459
+ # names will be Gem::Resolv::DNS::Name instances.
460
+
461
+ def each_name(address)
462
+ case address
463
+ when Name
464
+ ptr = address
465
+ when IPv4, IPv6
466
+ ptr = address.to_name
467
+ when IPv4::Regex
468
+ ptr = IPv4.create(address).to_name
469
+ when IPv6::Regex
470
+ ptr = IPv6.create(address).to_name
471
+ else
472
+ raise ResolvError.new("cannot interpret as address: #{address}")
473
+ end
474
+ each_resource(ptr, Resource::IN::PTR) {|resource| yield resource.name}
475
+ end
476
+
477
+ ##
478
+ # Look up the +typeclass+ DNS resource of +name+.
479
+ #
480
+ # +name+ must be a Gem::Resolv::DNS::Name or a String.
481
+ #
482
+ # +typeclass+ should be one of the following:
483
+ #
484
+ # * Gem::Resolv::DNS::Resource::IN::A
485
+ # * Gem::Resolv::DNS::Resource::IN::AAAA
486
+ # * Gem::Resolv::DNS::Resource::IN::ANY
487
+ # * Gem::Resolv::DNS::Resource::IN::CNAME
488
+ # * Gem::Resolv::DNS::Resource::IN::HINFO
489
+ # * Gem::Resolv::DNS::Resource::IN::MINFO
490
+ # * Gem::Resolv::DNS::Resource::IN::MX
491
+ # * Gem::Resolv::DNS::Resource::IN::NS
492
+ # * Gem::Resolv::DNS::Resource::IN::PTR
493
+ # * Gem::Resolv::DNS::Resource::IN::SOA
494
+ # * Gem::Resolv::DNS::Resource::IN::TXT
495
+ # * Gem::Resolv::DNS::Resource::IN::WKS
496
+ #
497
+ # Returned resource is represented as a Gem::Resolv::DNS::Resource instance,
498
+ # i.e. Gem::Resolv::DNS::Resource::IN::A.
499
+
500
+ def getresource(name, typeclass)
501
+ each_resource(name, typeclass) {|resource| return resource}
502
+ raise ResolvError.new("DNS result has no information for #{name}")
503
+ end
504
+
505
+ ##
506
+ # Looks up all +typeclass+ DNS resources for +name+. See #getresource for
507
+ # argument details.
508
+
509
+ def getresources(name, typeclass)
510
+ ret = []
511
+ each_resource(name, typeclass) {|resource| ret << resource}
512
+ return ret
513
+ end
514
+
515
+ ##
516
+ # Iterates over all +typeclass+ DNS resources for +name+. See
517
+ # #getresource for argument details.
518
+
519
+ def each_resource(name, typeclass, &proc)
520
+ fetch_resource(name, typeclass) {|reply, reply_name|
521
+ extract_resources(reply, reply_name, typeclass, &proc)
522
+ }
523
+ end
524
+
525
+ def fetch_resource(name, typeclass)
526
+ lazy_initialize
527
+ truncated = {}
528
+ requesters = {}
529
+ udp_requester = begin
530
+ make_udp_requester
531
+ rescue Errno::EACCES
532
+ # fall back to TCP
533
+ end
534
+ senders = {}
535
+
536
+ begin
537
+ @config.resolv(name) do |candidate, tout, nameserver, port|
538
+ msg = Message.new
539
+ msg.rd = 1
540
+ msg.add_question(candidate, typeclass)
541
+
542
+ requester = requesters.fetch([nameserver, port]) do
543
+ if !truncated[candidate] && udp_requester
544
+ udp_requester
545
+ else
546
+ requesters[[nameserver, port]] = make_tcp_requester(nameserver, port)
547
+ end
548
+ end
549
+
550
+ unless sender = senders[[candidate, requester, nameserver, port]]
551
+ sender = requester.sender(msg, candidate, nameserver, port)
552
+ next if !sender
553
+ senders[[candidate, requester, nameserver, port]] = sender
554
+ end
555
+ reply, reply_name = requester.request(sender, tout)
556
+ case reply.rcode
557
+ when RCode::NoError
558
+ if reply.tc == 1 and not Requester::TCP === requester
559
+ # Retry via TCP:
560
+ truncated[candidate] = true
561
+ redo
562
+ else
563
+ yield(reply, reply_name)
564
+ end
565
+ return
566
+ when RCode::NXDomain
567
+ raise Config::NXDomain.new(reply_name.to_s)
568
+ else
569
+ raise Config::OtherResolvError.new(reply_name.to_s)
570
+ end
571
+ end
572
+ ensure
573
+ udp_requester&.close
574
+ requesters.each_value { |requester| requester&.close }
575
+ end
576
+ end
577
+
578
+ def make_udp_requester # :nodoc:
579
+ nameserver_port = @config.nameserver_port
580
+ if nameserver_port.length == 1
581
+ Requester::ConnectedUDP.new(*nameserver_port[0])
582
+ else
583
+ Requester::UnconnectedUDP.new(*nameserver_port)
584
+ end
585
+ end
586
+
587
+ def make_tcp_requester(host, port) # :nodoc:
588
+ return Requester::TCP.new(host, port)
589
+ rescue Errno::ECONNREFUSED
590
+ # Treat a refused TCP connection attempt to a nameserver like a timeout,
591
+ # as Gem::Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a
592
+ # hint to try the next nameserver:
593
+ raise ResolvTimeout
594
+ end
595
+
596
+ def extract_resources(msg, name, typeclass) # :nodoc:
597
+ if typeclass < Resource::ANY
598
+ n0 = Name.create(name)
599
+ msg.each_resource {|n, ttl, data|
600
+ yield data if n0 == n
601
+ }
602
+ end
603
+ yielded = false
604
+ n0 = Name.create(name)
605
+ msg.each_resource {|n, ttl, data|
606
+ if n0 == n
607
+ case data
608
+ when typeclass
609
+ yield data
610
+ yielded = true
611
+ when Resource::CNAME
612
+ n0 = data.name
613
+ end
614
+ end
615
+ }
616
+ return if yielded
617
+ msg.each_resource {|n, ttl, data|
618
+ if n0 == n
619
+ case data
620
+ when typeclass
621
+ yield data
622
+ end
623
+ end
624
+ }
625
+ end
626
+
627
+ def self.random(arg) # :nodoc:
628
+ begin
629
+ Gem::SecureRandom.random_number(arg)
630
+ rescue NotImplementedError
631
+ rand(arg)
632
+ end
633
+ end
634
+
635
+ RequestID = {} # :nodoc:
636
+ RequestIDMutex = Thread::Mutex.new # :nodoc:
637
+
638
+ def self.allocate_request_id(host, port) # :nodoc:
639
+ id = nil
640
+ RequestIDMutex.synchronize {
641
+ h = (RequestID[[host, port]] ||= {})
642
+ begin
643
+ id = random(0x0000..0xffff)
644
+ end while h[id]
645
+ h[id] = true
646
+ }
647
+ id
648
+ end
649
+
650
+ def self.free_request_id(host, port, id) # :nodoc:
651
+ RequestIDMutex.synchronize {
652
+ key = [host, port]
653
+ if h = RequestID[key]
654
+ h.delete id
655
+ if h.empty?
656
+ RequestID.delete key
657
+ end
658
+ end
659
+ }
660
+ end
661
+
662
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
663
+ begin
664
+ port = random(1024..65535)
665
+ udpsock.bind(bind_host, port)
666
+ rescue Errno::EADDRINUSE, # POSIX
667
+ Errno::EACCES, # SunOS: See PRIV_SYS_NFS in privileges(5)
668
+ Errno::EPERM # FreeBSD: security.mac.portacl.port_high is configurable. See mac_portacl(4).
669
+ retry
670
+ end
671
+ end
672
+
673
+ class Requester # :nodoc:
674
+ def initialize
675
+ @senders = {}
676
+ @socks = nil
677
+ end
678
+
679
+ def request(sender, tout)
680
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
681
+ timelimit = start + tout
682
+ begin
683
+ sender.send
684
+ rescue Errno::EHOSTUNREACH, # multi-homed IPv6 may generate this
685
+ Errno::ENETUNREACH
686
+ raise ResolvTimeout
687
+ end
688
+ while true
689
+ before_select = Process.clock_gettime(Process::CLOCK_MONOTONIC)
690
+ timeout = timelimit - before_select
691
+ if timeout <= 0
692
+ raise ResolvTimeout
693
+ end
694
+ if @socks.size == 1
695
+ select_result = @socks[0].wait_readable(timeout) ? [ @socks ] : nil
696
+ else
697
+ select_result = IO.select(@socks, nil, nil, timeout)
698
+ end
699
+ if !select_result
700
+ after_select = Process.clock_gettime(Process::CLOCK_MONOTONIC)
701
+ next if after_select < timelimit
702
+ raise ResolvTimeout
703
+ end
704
+ begin
705
+ reply, from = recv_reply(select_result[0])
706
+ rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
707
+ Errno::ECONNRESET # Windows
708
+ # No name server running on the server?
709
+ # Don't wait anymore.
710
+ raise ResolvTimeout
711
+ end
712
+ begin
713
+ msg = Message.decode(reply)
714
+ rescue DecodeError
715
+ next # broken DNS message ignored
716
+ end
717
+ if sender == sender_for(from, msg)
718
+ break
719
+ else
720
+ # unexpected DNS message ignored
721
+ end
722
+ end
723
+ return msg, sender.data
724
+ end
725
+
726
+ def sender_for(addr, msg)
727
+ @senders[[addr,msg.id]]
728
+ end
729
+
730
+ def close
731
+ socks = @socks
732
+ @socks = nil
733
+ socks&.each(&:close)
734
+ end
735
+
736
+ class Sender # :nodoc:
737
+ def initialize(msg, data, sock)
738
+ @msg = msg
739
+ @data = data
740
+ @sock = sock
741
+ end
742
+ end
743
+
744
+ class UnconnectedUDP < Requester # :nodoc:
745
+ def initialize(*nameserver_port)
746
+ super()
747
+ @nameserver_port = nameserver_port
748
+ @initialized = false
749
+ @mutex = Thread::Mutex.new
750
+ end
751
+
752
+ def lazy_initialize
753
+ @mutex.synchronize {
754
+ next if @initialized
755
+ @initialized = true
756
+ @socks_hash = {}
757
+ @socks = []
758
+ @nameserver_port.each {|host, port|
759
+ if host.index(':')
760
+ bind_host = "::"
761
+ af = Socket::AF_INET6
762
+ else
763
+ bind_host = "0.0.0.0"
764
+ af = Socket::AF_INET
765
+ end
766
+ next if @socks_hash[bind_host]
767
+ begin
768
+ sock = UDPSocket.new(af)
769
+ rescue Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT
770
+ next # The kernel doesn't support the address family.
771
+ end
772
+ @socks << sock
773
+ @socks_hash[bind_host] = sock
774
+ sock.do_not_reverse_lookup = true
775
+ DNS.bind_random_port(sock, bind_host)
776
+ }
777
+ }
778
+ self
779
+ end
780
+
781
+ def recv_reply(readable_socks)
782
+ lazy_initialize
783
+ reply, from = readable_socks[0].recvfrom(UDPSize)
784
+ return reply, [from[3],from[1]]
785
+ end
786
+
787
+ def sender(msg, data, host, port=Port)
788
+ host = Addrinfo.ip(host).ip_address
789
+ lazy_initialize
790
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
791
+ return nil if !sock
792
+ service = [host, port]
793
+ id = DNS.allocate_request_id(host, port)
794
+ request = msg.encode
795
+ request[0,2] = [id].pack('n')
796
+ return @senders[[service, id]] =
797
+ Sender.new(request, data, sock, host, port)
798
+ end
799
+
800
+ def close
801
+ @mutex.synchronize {
802
+ if @initialized
803
+ super
804
+ @senders.each_key {|service, id|
805
+ DNS.free_request_id(service[0], service[1], id)
806
+ }
807
+ @initialized = false
808
+ end
809
+ }
810
+ end
811
+
812
+ class Sender < Requester::Sender # :nodoc:
813
+ def initialize(msg, data, sock, host, port)
814
+ super(msg, data, sock)
815
+ @host = host
816
+ @port = port
817
+ end
818
+ attr_reader :data
819
+
820
+ def send
821
+ raise "@sock is nil." if @sock.nil?
822
+ @sock.send(@msg, 0, @host, @port)
823
+ end
824
+ end
825
+ end
826
+
827
+ class ConnectedUDP < Requester # :nodoc:
828
+ def initialize(host, port=Port)
829
+ super()
830
+ @host = host
831
+ @port = port
832
+ @mutex = Thread::Mutex.new
833
+ @initialized = false
834
+ end
835
+
836
+ def lazy_initialize
837
+ @mutex.synchronize {
838
+ next if @initialized
839
+ @initialized = true
840
+ is_ipv6 = @host.index(':')
841
+ sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
842
+ @socks = [sock]
843
+ sock.do_not_reverse_lookup = true
844
+ DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
845
+ sock.connect(@host, @port)
846
+ }
847
+ self
848
+ end
849
+
850
+ def recv_reply(readable_socks)
851
+ lazy_initialize
852
+ reply = readable_socks[0].recv(UDPSize)
853
+ return reply, nil
854
+ end
855
+
856
+ def sender(msg, data, host=@host, port=@port)
857
+ lazy_initialize
858
+ unless host == @host && port == @port
859
+ raise RequestError.new("host/port don't match: #{host}:#{port}")
860
+ end
861
+ id = DNS.allocate_request_id(@host, @port)
862
+ request = msg.encode
863
+ request[0,2] = [id].pack('n')
864
+ return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
865
+ end
866
+
867
+ def close
868
+ @mutex.synchronize do
869
+ if @initialized
870
+ super
871
+ @senders.each_key {|from, id|
872
+ DNS.free_request_id(@host, @port, id)
873
+ }
874
+ @initialized = false
875
+ end
876
+ end
877
+ end
878
+
879
+ class Sender < Requester::Sender # :nodoc:
880
+ def send
881
+ raise "@sock is nil." if @sock.nil?
882
+ @sock.send(@msg, 0)
883
+ end
884
+ attr_reader :data
885
+ end
886
+ end
887
+
888
+ class MDNSOneShot < UnconnectedUDP # :nodoc:
889
+ def sender(msg, data, host, port=Port)
890
+ lazy_initialize
891
+ id = DNS.allocate_request_id(host, port)
892
+ request = msg.encode
893
+ request[0,2] = [id].pack('n')
894
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
895
+ return @senders[id] =
896
+ UnconnectedUDP::Sender.new(request, data, sock, host, port)
897
+ end
898
+
899
+ def sender_for(addr, msg)
900
+ lazy_initialize
901
+ @senders[msg.id]
902
+ end
903
+ end
904
+
905
+ class TCP < Requester # :nodoc:
906
+ def initialize(host, port=Port)
907
+ super()
908
+ @host = host
909
+ @port = port
910
+ sock = TCPSocket.new(@host, @port)
911
+ @socks = [sock]
912
+ @senders = {}
913
+ end
914
+
915
+ def recv_reply(readable_socks)
916
+ len = readable_socks[0].read(2).unpack('n')[0]
917
+ reply = @socks[0].read(len)
918
+ return reply, nil
919
+ end
920
+
921
+ def sender(msg, data, host=@host, port=@port)
922
+ unless host == @host && port == @port
923
+ raise RequestError.new("host/port don't match: #{host}:#{port}")
924
+ end
925
+ id = DNS.allocate_request_id(@host, @port)
926
+ request = msg.encode
927
+ request[0,2] = [request.length, id].pack('nn')
928
+ return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
929
+ end
930
+
931
+ class Sender < Requester::Sender # :nodoc:
932
+ def send
933
+ @sock.print(@msg)
934
+ @sock.flush
935
+ end
936
+ attr_reader :data
937
+ end
938
+
939
+ def close
940
+ super
941
+ @senders.each_key {|from,id|
942
+ DNS.free_request_id(@host, @port, id)
943
+ }
944
+ end
945
+ end
946
+
947
+ ##
948
+ # Indicates a problem with the DNS request.
949
+
950
+ class RequestError < StandardError
951
+ end
952
+ end
953
+
954
+ class Config # :nodoc:
955
+ def initialize(config_info=nil)
956
+ @mutex = Thread::Mutex.new
957
+ @config_info = config_info
958
+ @initialized = nil
959
+ @timeouts = nil
960
+ end
961
+
962
+ def timeouts=(values)
963
+ if values
964
+ values = Array(values)
965
+ values.each do |t|
966
+ Numeric === t or raise ArgumentError, "#{t.inspect} is not numeric"
967
+ t > 0.0 or raise ArgumentError, "timeout=#{t} must be positive"
968
+ end
969
+ @timeouts = values
970
+ else
971
+ @timeouts = nil
972
+ end
973
+ end
974
+
975
+ def Config.parse_resolv_conf(filename)
976
+ nameserver = []
977
+ search = nil
978
+ ndots = 1
979
+ File.open(filename, 'rb') {|f|
980
+ f.each {|line|
981
+ line.sub!(/[#;].*/, '')
982
+ keyword, *args = line.split(/\s+/)
983
+ next unless keyword
984
+ case keyword
985
+ when 'nameserver'
986
+ nameserver.concat(args)
987
+ when 'domain'
988
+ next if args.empty?
989
+ search = [args[0]]
990
+ when 'search'
991
+ next if args.empty?
992
+ search = args
993
+ when 'options'
994
+ args.each {|arg|
995
+ case arg
996
+ when /\Andots:(\d+)\z/
997
+ ndots = $1.to_i
998
+ end
999
+ }
1000
+ end
1001
+ }
1002
+ }
1003
+ return { :nameserver => nameserver, :search => search, :ndots => ndots }
1004
+ end
1005
+
1006
+ def Config.default_config_hash(filename="/etc/resolv.conf")
1007
+ if File.exist? filename
1008
+ config_hash = Config.parse_resolv_conf(filename)
1009
+ else
1010
+ if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
1011
+ require 'win32/resolv'
1012
+ search, nameserver = Win32::Resolv.get_resolv_info
1013
+ config_hash = {}
1014
+ config_hash[:nameserver] = nameserver if nameserver
1015
+ config_hash[:search] = [search].flatten if search
1016
+ end
1017
+ end
1018
+ config_hash || {}
1019
+ end
1020
+
1021
+ def lazy_initialize
1022
+ @mutex.synchronize {
1023
+ unless @initialized
1024
+ @nameserver_port = []
1025
+ @use_ipv6 = nil
1026
+ @search = nil
1027
+ @ndots = 1
1028
+ case @config_info
1029
+ when nil
1030
+ config_hash = Config.default_config_hash
1031
+ when String
1032
+ config_hash = Config.parse_resolv_conf(@config_info)
1033
+ when Hash
1034
+ config_hash = @config_info.dup
1035
+ if String === config_hash[:nameserver]
1036
+ config_hash[:nameserver] = [config_hash[:nameserver]]
1037
+ end
1038
+ if String === config_hash[:search]
1039
+ config_hash[:search] = [config_hash[:search]]
1040
+ end
1041
+ else
1042
+ raise ArgumentError.new("invalid resolv configuration: #{@config_info.inspect}")
1043
+ end
1044
+ if config_hash.include? :nameserver
1045
+ @nameserver_port = config_hash[:nameserver].map {|ns| [ns, Port] }
1046
+ end
1047
+ if config_hash.include? :nameserver_port
1048
+ @nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] }
1049
+ end
1050
+ if config_hash.include? :use_ipv6
1051
+ @use_ipv6 = config_hash[:use_ipv6]
1052
+ end
1053
+ @search = config_hash[:search] if config_hash.include? :search
1054
+ @ndots = config_hash[:ndots] if config_hash.include? :ndots
1055
+ @raise_timeout_errors = config_hash[:raise_timeout_errors]
1056
+
1057
+ if @nameserver_port.empty?
1058
+ @nameserver_port << ['0.0.0.0', Port]
1059
+ end
1060
+ if @search
1061
+ @search = @search.map {|arg| Label.split(arg) }
1062
+ else
1063
+ hostname = Socket.gethostname
1064
+ if /\./ =~ hostname
1065
+ @search = [Label.split($')]
1066
+ else
1067
+ @search = [[]]
1068
+ end
1069
+ end
1070
+
1071
+ if !@nameserver_port.kind_of?(Array) ||
1072
+ @nameserver_port.any? {|ns_port|
1073
+ !(Array === ns_port) ||
1074
+ ns_port.length != 2
1075
+ !(String === ns_port[0]) ||
1076
+ !(Integer === ns_port[1])
1077
+ }
1078
+ raise ArgumentError.new("invalid nameserver config: #{@nameserver_port.inspect}")
1079
+ end
1080
+
1081
+ if !@search.kind_of?(Array) ||
1082
+ !@search.all? {|ls| ls.all? {|l| Label::Str === l } }
1083
+ raise ArgumentError.new("invalid search config: #{@search.inspect}")
1084
+ end
1085
+
1086
+ if !@ndots.kind_of?(Integer)
1087
+ raise ArgumentError.new("invalid ndots config: #{@ndots.inspect}")
1088
+ end
1089
+
1090
+ @initialized = true
1091
+ end
1092
+ }
1093
+ self
1094
+ end
1095
+
1096
+ def single?
1097
+ lazy_initialize
1098
+ if @nameserver_port.length == 1
1099
+ return @nameserver_port[0]
1100
+ else
1101
+ return nil
1102
+ end
1103
+ end
1104
+
1105
+ def nameserver_port
1106
+ @nameserver_port
1107
+ end
1108
+
1109
+ def use_ipv6?
1110
+ @use_ipv6
1111
+ end
1112
+
1113
+ def generate_candidates(name)
1114
+ candidates = nil
1115
+ name = Name.create(name)
1116
+ if name.absolute?
1117
+ candidates = [name]
1118
+ else
1119
+ if @ndots <= name.length - 1
1120
+ candidates = [Name.new(name.to_a)]
1121
+ else
1122
+ candidates = []
1123
+ end
1124
+ candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)})
1125
+ fname = Name.create("#{name}.")
1126
+ if !candidates.include?(fname)
1127
+ candidates << fname
1128
+ end
1129
+ end
1130
+ return candidates
1131
+ end
1132
+
1133
+ InitialTimeout = 5
1134
+
1135
+ def generate_timeouts
1136
+ ts = [InitialTimeout]
1137
+ ts << ts[-1] * 2 / @nameserver_port.length
1138
+ ts << ts[-1] * 2
1139
+ ts << ts[-1] * 2
1140
+ return ts
1141
+ end
1142
+
1143
+ def resolv(name)
1144
+ candidates = generate_candidates(name)
1145
+ timeouts = @timeouts || generate_timeouts
1146
+ timeout_error = false
1147
+ begin
1148
+ candidates.each {|candidate|
1149
+ begin
1150
+ timeouts.each {|tout|
1151
+ @nameserver_port.each {|nameserver, port|
1152
+ begin
1153
+ yield candidate, tout, nameserver, port
1154
+ rescue ResolvTimeout
1155
+ end
1156
+ }
1157
+ }
1158
+ timeout_error = true
1159
+ raise ResolvError.new("DNS resolv timeout: #{name}")
1160
+ rescue NXDomain
1161
+ end
1162
+ }
1163
+ rescue ResolvError
1164
+ raise if @raise_timeout_errors && timeout_error
1165
+ end
1166
+ end
1167
+
1168
+ ##
1169
+ # Indicates no such domain was found.
1170
+
1171
+ class NXDomain < ResolvError
1172
+ end
1173
+
1174
+ ##
1175
+ # Indicates some other unhandled resolver error was encountered.
1176
+
1177
+ class OtherResolvError < ResolvError
1178
+ end
1179
+ end
1180
+
1181
+ module OpCode # :nodoc:
1182
+ Query = 0
1183
+ IQuery = 1
1184
+ Status = 2
1185
+ Notify = 4
1186
+ Update = 5
1187
+ end
1188
+
1189
+ module RCode # :nodoc:
1190
+ NoError = 0
1191
+ FormErr = 1
1192
+ ServFail = 2
1193
+ NXDomain = 3
1194
+ NotImp = 4
1195
+ Refused = 5
1196
+ YXDomain = 6
1197
+ YXRRSet = 7
1198
+ NXRRSet = 8
1199
+ NotAuth = 9
1200
+ NotZone = 10
1201
+ BADVERS = 16
1202
+ BADSIG = 16
1203
+ BADKEY = 17
1204
+ BADTIME = 18
1205
+ BADMODE = 19
1206
+ BADNAME = 20
1207
+ BADALG = 21
1208
+ end
1209
+
1210
+ ##
1211
+ # Indicates that the DNS response was unable to be decoded.
1212
+
1213
+ class DecodeError < StandardError
1214
+ end
1215
+
1216
+ ##
1217
+ # Indicates that the DNS request was unable to be encoded.
1218
+
1219
+ class EncodeError < StandardError
1220
+ end
1221
+
1222
+ module Label # :nodoc:
1223
+ def self.split(arg)
1224
+ labels = []
1225
+ arg.scan(/[^\.]+/) {labels << Str.new($&)}
1226
+ return labels
1227
+ end
1228
+
1229
+ class Str # :nodoc:
1230
+ def initialize(string)
1231
+ @string = string
1232
+ # case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
1233
+ # This assumes @string is given in ASCII compatible encoding.
1234
+ @downcase = string.b.downcase
1235
+ end
1236
+ attr_reader :string, :downcase
1237
+
1238
+ def to_s
1239
+ return @string
1240
+ end
1241
+
1242
+ def inspect
1243
+ return "#<#{self.class} #{self}>"
1244
+ end
1245
+
1246
+ def ==(other)
1247
+ return self.class == other.class && @downcase == other.downcase
1248
+ end
1249
+
1250
+ def eql?(other)
1251
+ return self == other
1252
+ end
1253
+
1254
+ def hash
1255
+ return @downcase.hash
1256
+ end
1257
+ end
1258
+ end
1259
+
1260
+ ##
1261
+ # A representation of a DNS name.
1262
+
1263
+ class Name
1264
+
1265
+ ##
1266
+ # Creates a new DNS name from +arg+. +arg+ can be:
1267
+ #
1268
+ # Name:: returns +arg+.
1269
+ # String:: Creates a new Name.
1270
+
1271
+ def self.create(arg)
1272
+ case arg
1273
+ when Name
1274
+ return arg
1275
+ when String
1276
+ return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
1277
+ else
1278
+ raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
1279
+ end
1280
+ end
1281
+
1282
+ def initialize(labels, absolute=true) # :nodoc:
1283
+ labels = labels.map {|label|
1284
+ case label
1285
+ when String then Label::Str.new(label)
1286
+ when Label::Str then label
1287
+ else
1288
+ raise ArgumentError, "unexpected label: #{label.inspect}"
1289
+ end
1290
+ }
1291
+ @labels = labels
1292
+ @absolute = absolute
1293
+ end
1294
+
1295
+ def inspect # :nodoc:
1296
+ "#<#{self.class}: #{self}#{@absolute ? '.' : ''}>"
1297
+ end
1298
+
1299
+ ##
1300
+ # True if this name is absolute.
1301
+
1302
+ def absolute?
1303
+ return @absolute
1304
+ end
1305
+
1306
+ def ==(other) # :nodoc:
1307
+ return false unless Name === other
1308
+ return false unless @absolute == other.absolute?
1309
+ return @labels == other.to_a
1310
+ end
1311
+
1312
+ alias eql? == # :nodoc:
1313
+
1314
+ ##
1315
+ # Returns true if +other+ is a subdomain.
1316
+ #
1317
+ # Example:
1318
+ #
1319
+ # domain = Gem::Resolv::DNS::Name.create("y.z")
1320
+ # p Gem::Resolv::DNS::Name.create("w.x.y.z").subdomain_of?(domain) #=> true
1321
+ # p Gem::Resolv::DNS::Name.create("x.y.z").subdomain_of?(domain) #=> true
1322
+ # p Gem::Resolv::DNS::Name.create("y.z").subdomain_of?(domain) #=> false
1323
+ # p Gem::Resolv::DNS::Name.create("z").subdomain_of?(domain) #=> false
1324
+ # p Gem::Resolv::DNS::Name.create("x.y.z.").subdomain_of?(domain) #=> false
1325
+ # p Gem::Resolv::DNS::Name.create("w.z").subdomain_of?(domain) #=> false
1326
+ #
1327
+
1328
+ def subdomain_of?(other)
1329
+ raise ArgumentError, "not a domain name: #{other.inspect}" unless Name === other
1330
+ return false if @absolute != other.absolute?
1331
+ other_len = other.length
1332
+ return false if @labels.length <= other_len
1333
+ return @labels[-other_len, other_len] == other.to_a
1334
+ end
1335
+
1336
+ def hash # :nodoc:
1337
+ return @labels.hash ^ @absolute.hash
1338
+ end
1339
+
1340
+ def to_a # :nodoc:
1341
+ return @labels
1342
+ end
1343
+
1344
+ def length # :nodoc:
1345
+ return @labels.length
1346
+ end
1347
+
1348
+ def [](i) # :nodoc:
1349
+ return @labels[i]
1350
+ end
1351
+
1352
+ ##
1353
+ # returns the domain name as a string.
1354
+ #
1355
+ # The domain name doesn't have a trailing dot even if the name object is
1356
+ # absolute.
1357
+ #
1358
+ # Example:
1359
+ #
1360
+ # p Gem::Resolv::DNS::Name.create("x.y.z.").to_s #=> "x.y.z"
1361
+ # p Gem::Resolv::DNS::Name.create("x.y.z").to_s #=> "x.y.z"
1362
+
1363
+ def to_s
1364
+ return @labels.join('.')
1365
+ end
1366
+ end
1367
+
1368
+ class Message # :nodoc:
1369
+ @@identifier = -1
1370
+
1371
+ def initialize(id = (@@identifier += 1) & 0xffff)
1372
+ @id = id
1373
+ @qr = 0
1374
+ @opcode = 0
1375
+ @aa = 0
1376
+ @tc = 0
1377
+ @rd = 0 # recursion desired
1378
+ @ra = 0 # recursion available
1379
+ @rcode = 0
1380
+ @question = []
1381
+ @answer = []
1382
+ @authority = []
1383
+ @additional = []
1384
+ end
1385
+
1386
+ attr_accessor :id, :qr, :opcode, :aa, :tc, :rd, :ra, :rcode
1387
+ attr_reader :question, :answer, :authority, :additional
1388
+
1389
+ def ==(other)
1390
+ return @id == other.id &&
1391
+ @qr == other.qr &&
1392
+ @opcode == other.opcode &&
1393
+ @aa == other.aa &&
1394
+ @tc == other.tc &&
1395
+ @rd == other.rd &&
1396
+ @ra == other.ra &&
1397
+ @rcode == other.rcode &&
1398
+ @question == other.question &&
1399
+ @answer == other.answer &&
1400
+ @authority == other.authority &&
1401
+ @additional == other.additional
1402
+ end
1403
+
1404
+ def add_question(name, typeclass)
1405
+ @question << [Name.create(name), typeclass]
1406
+ end
1407
+
1408
+ def each_question
1409
+ @question.each {|name, typeclass|
1410
+ yield name, typeclass
1411
+ }
1412
+ end
1413
+
1414
+ def add_answer(name, ttl, data)
1415
+ @answer << [Name.create(name), ttl, data]
1416
+ end
1417
+
1418
+ def each_answer
1419
+ @answer.each {|name, ttl, data|
1420
+ yield name, ttl, data
1421
+ }
1422
+ end
1423
+
1424
+ def add_authority(name, ttl, data)
1425
+ @authority << [Name.create(name), ttl, data]
1426
+ end
1427
+
1428
+ def each_authority
1429
+ @authority.each {|name, ttl, data|
1430
+ yield name, ttl, data
1431
+ }
1432
+ end
1433
+
1434
+ def add_additional(name, ttl, data)
1435
+ @additional << [Name.create(name), ttl, data]
1436
+ end
1437
+
1438
+ def each_additional
1439
+ @additional.each {|name, ttl, data|
1440
+ yield name, ttl, data
1441
+ }
1442
+ end
1443
+
1444
+ def each_resource
1445
+ each_answer {|name, ttl, data| yield name, ttl, data}
1446
+ each_authority {|name, ttl, data| yield name, ttl, data}
1447
+ each_additional {|name, ttl, data| yield name, ttl, data}
1448
+ end
1449
+
1450
+ def encode
1451
+ return MessageEncoder.new {|msg|
1452
+ msg.put_pack('nnnnnn',
1453
+ @id,
1454
+ (@qr & 1) << 15 |
1455
+ (@opcode & 15) << 11 |
1456
+ (@aa & 1) << 10 |
1457
+ (@tc & 1) << 9 |
1458
+ (@rd & 1) << 8 |
1459
+ (@ra & 1) << 7 |
1460
+ (@rcode & 15),
1461
+ @question.length,
1462
+ @answer.length,
1463
+ @authority.length,
1464
+ @additional.length)
1465
+ @question.each {|q|
1466
+ name, typeclass = q
1467
+ msg.put_name(name)
1468
+ msg.put_pack('nn', typeclass::TypeValue, typeclass::ClassValue)
1469
+ }
1470
+ [@answer, @authority, @additional].each {|rr|
1471
+ rr.each {|r|
1472
+ name, ttl, data = r
1473
+ msg.put_name(name)
1474
+ msg.put_pack('nnN', data.class::TypeValue, data.class::ClassValue, ttl)
1475
+ msg.put_length16 {data.encode_rdata(msg)}
1476
+ }
1477
+ }
1478
+ }.to_s
1479
+ end
1480
+
1481
+ class MessageEncoder # :nodoc:
1482
+ def initialize
1483
+ @data = ''.dup
1484
+ @names = {}
1485
+ yield self
1486
+ end
1487
+
1488
+ def to_s
1489
+ return @data
1490
+ end
1491
+
1492
+ def put_bytes(d)
1493
+ @data << d
1494
+ end
1495
+
1496
+ def put_pack(template, *d)
1497
+ @data << d.pack(template)
1498
+ end
1499
+
1500
+ def put_length16
1501
+ length_index = @data.length
1502
+ @data << "\0\0"
1503
+ data_start = @data.length
1504
+ yield
1505
+ data_end = @data.length
1506
+ @data[length_index, 2] = [data_end - data_start].pack("n")
1507
+ end
1508
+
1509
+ def put_string(d)
1510
+ self.put_pack("C", d.length)
1511
+ @data << d
1512
+ end
1513
+
1514
+ def put_string_list(ds)
1515
+ ds.each {|d|
1516
+ self.put_string(d)
1517
+ }
1518
+ end
1519
+
1520
+ def put_name(d, compress: true)
1521
+ put_labels(d.to_a, compress: compress)
1522
+ end
1523
+
1524
+ def put_labels(d, compress: true)
1525
+ d.each_index {|i|
1526
+ domain = d[i..-1]
1527
+ if compress && idx = @names[domain]
1528
+ self.put_pack("n", 0xc000 | idx)
1529
+ return
1530
+ else
1531
+ if @data.length < 0x4000
1532
+ @names[domain] = @data.length
1533
+ end
1534
+ self.put_label(d[i])
1535
+ end
1536
+ }
1537
+ @data << "\0"
1538
+ end
1539
+
1540
+ def put_label(d)
1541
+ self.put_string(d.to_s)
1542
+ end
1543
+ end
1544
+
1545
+ def Message.decode(m)
1546
+ o = Message.new(0)
1547
+ MessageDecoder.new(m) {|msg|
1548
+ id, flag, qdcount, ancount, nscount, arcount =
1549
+ msg.get_unpack('nnnnnn')
1550
+ o.id = id
1551
+ o.tc = (flag >> 9) & 1
1552
+ o.rcode = flag & 15
1553
+ return o unless o.tc.zero?
1554
+
1555
+ o.qr = (flag >> 15) & 1
1556
+ o.opcode = (flag >> 11) & 15
1557
+ o.aa = (flag >> 10) & 1
1558
+ o.rd = (flag >> 8) & 1
1559
+ o.ra = (flag >> 7) & 1
1560
+ (1..qdcount).each {
1561
+ name, typeclass = msg.get_question
1562
+ o.add_question(name, typeclass)
1563
+ }
1564
+ (1..ancount).each {
1565
+ name, ttl, data = msg.get_rr
1566
+ o.add_answer(name, ttl, data)
1567
+ }
1568
+ (1..nscount).each {
1569
+ name, ttl, data = msg.get_rr
1570
+ o.add_authority(name, ttl, data)
1571
+ }
1572
+ (1..arcount).each {
1573
+ name, ttl, data = msg.get_rr
1574
+ o.add_additional(name, ttl, data)
1575
+ }
1576
+ }
1577
+ return o
1578
+ end
1579
+
1580
+ class MessageDecoder # :nodoc:
1581
+ def initialize(data)
1582
+ @data = data
1583
+ @index = 0
1584
+ @limit = data.bytesize
1585
+ yield self
1586
+ end
1587
+
1588
+ def inspect
1589
+ "\#<#{self.class}: #{@data.byteslice(0, @index).inspect} #{@data.byteslice(@index..-1).inspect}>"
1590
+ end
1591
+
1592
+ def get_length16
1593
+ len, = self.get_unpack('n')
1594
+ save_limit = @limit
1595
+ @limit = @index + len
1596
+ d = yield(len)
1597
+ if @index < @limit
1598
+ raise DecodeError.new("junk exists")
1599
+ elsif @limit < @index
1600
+ raise DecodeError.new("limit exceeded")
1601
+ end
1602
+ @limit = save_limit
1603
+ return d
1604
+ end
1605
+
1606
+ def get_bytes(len = @limit - @index)
1607
+ raise DecodeError.new("limit exceeded") if @limit < @index + len
1608
+ d = @data.byteslice(@index, len)
1609
+ @index += len
1610
+ return d
1611
+ end
1612
+
1613
+ def get_unpack(template)
1614
+ len = 0
1615
+ template.each_byte {|byte|
1616
+ byte = "%c" % byte
1617
+ case byte
1618
+ when ?c, ?C
1619
+ len += 1
1620
+ when ?n
1621
+ len += 2
1622
+ when ?N
1623
+ len += 4
1624
+ else
1625
+ raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'")
1626
+ end
1627
+ }
1628
+ raise DecodeError.new("limit exceeded") if @limit < @index + len
1629
+ arr = @data.unpack("@#{@index}#{template}")
1630
+ @index += len
1631
+ return arr
1632
+ end
1633
+
1634
+ def get_string
1635
+ raise DecodeError.new("limit exceeded") if @limit <= @index
1636
+ len = @data.getbyte(@index)
1637
+ raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
1638
+ d = @data.byteslice(@index + 1, len)
1639
+ @index += 1 + len
1640
+ return d
1641
+ end
1642
+
1643
+ def get_string_list
1644
+ strings = []
1645
+ while @index < @limit
1646
+ strings << self.get_string
1647
+ end
1648
+ strings
1649
+ end
1650
+
1651
+ def get_list
1652
+ [].tap do |values|
1653
+ while @index < @limit
1654
+ values << yield
1655
+ end
1656
+ end
1657
+ end
1658
+
1659
+ def get_name
1660
+ return Name.new(self.get_labels)
1661
+ end
1662
+
1663
+ def get_labels
1664
+ prev_index = @index
1665
+ save_index = nil
1666
+ d = []
1667
+ while true
1668
+ raise DecodeError.new("limit exceeded") if @limit <= @index
1669
+ case @data.getbyte(@index)
1670
+ when 0
1671
+ @index += 1
1672
+ if save_index
1673
+ @index = save_index
1674
+ end
1675
+ return d
1676
+ when 192..255
1677
+ idx = self.get_unpack('n')[0] & 0x3fff
1678
+ if prev_index <= idx
1679
+ raise DecodeError.new("non-backward name pointer")
1680
+ end
1681
+ prev_index = idx
1682
+ if !save_index
1683
+ save_index = @index
1684
+ end
1685
+ @index = idx
1686
+ else
1687
+ d << self.get_label
1688
+ end
1689
+ end
1690
+ end
1691
+
1692
+ def get_label
1693
+ return Label::Str.new(self.get_string)
1694
+ end
1695
+
1696
+ def get_question
1697
+ name = self.get_name
1698
+ type, klass = self.get_unpack("nn")
1699
+ return name, Resource.get_class(type, klass)
1700
+ end
1701
+
1702
+ def get_rr
1703
+ name = self.get_name
1704
+ type, klass, ttl = self.get_unpack('nnN')
1705
+ typeclass = Resource.get_class(type, klass)
1706
+ res = self.get_length16 do
1707
+ begin
1708
+ typeclass.decode_rdata self
1709
+ rescue => e
1710
+ raise DecodeError, e.message, e.backtrace
1711
+ end
1712
+ end
1713
+ res.instance_variable_set :@ttl, ttl
1714
+ return name, ttl, res
1715
+ end
1716
+ end
1717
+ end
1718
+
1719
+ ##
1720
+ # SvcParams for service binding RRs. [RFC9460]
1721
+
1722
+ class SvcParams
1723
+ include Enumerable
1724
+
1725
+ ##
1726
+ # Create a list of SvcParams with the given initial content.
1727
+ #
1728
+ # +params+ has to be an enumerable of +SvcParam+s.
1729
+ # If its content has +SvcParam+s with the duplicate key,
1730
+ # the one appears last takes precedence.
1731
+
1732
+ def initialize(params = [])
1733
+ @params = {}
1734
+
1735
+ params.each do |param|
1736
+ add param
1737
+ end
1738
+ end
1739
+
1740
+ ##
1741
+ # Get SvcParam for the given +key+ in this list.
1742
+
1743
+ def [](key)
1744
+ @params[canonical_key(key)]
1745
+ end
1746
+
1747
+ ##
1748
+ # Get the number of SvcParams in this list.
1749
+
1750
+ def count
1751
+ @params.count
1752
+ end
1753
+
1754
+ ##
1755
+ # Get whether this list is empty.
1756
+
1757
+ def empty?
1758
+ @params.empty?
1759
+ end
1760
+
1761
+ ##
1762
+ # Add the SvcParam +param+ to this list, overwriting the existing one with the same key.
1763
+
1764
+ def add(param)
1765
+ @params[param.class.key_number] = param
1766
+ end
1767
+
1768
+ ##
1769
+ # Remove the +SvcParam+ with the given +key+ and return it.
1770
+
1771
+ def delete(key)
1772
+ @params.delete(canonical_key(key))
1773
+ end
1774
+
1775
+ ##
1776
+ # Enumerate the +SvcParam+s in this list.
1777
+
1778
+ def each(&block)
1779
+ return enum_for(:each) unless block
1780
+ @params.each_value(&block)
1781
+ end
1782
+
1783
+ def encode(msg) # :nodoc:
1784
+ @params.keys.sort.each do |key|
1785
+ msg.put_pack('n', key)
1786
+ msg.put_length16 do
1787
+ @params.fetch(key).encode(msg)
1788
+ end
1789
+ end
1790
+ end
1791
+
1792
+ def self.decode(msg) # :nodoc:
1793
+ params = msg.get_list do
1794
+ key, = msg.get_unpack('n')
1795
+ msg.get_length16 do
1796
+ SvcParam::ClassHash[key].decode(msg)
1797
+ end
1798
+ end
1799
+
1800
+ return self.new(params)
1801
+ end
1802
+
1803
+ private
1804
+
1805
+ def canonical_key(key) # :nodoc:
1806
+ case key
1807
+ when Integer
1808
+ key
1809
+ when /\Akey(\d+)\z/
1810
+ Integer($1)
1811
+ when Symbol
1812
+ SvcParam::ClassHash[key].key_number
1813
+ else
1814
+ raise TypeError, 'key must be either String or Symbol'
1815
+ end
1816
+ end
1817
+ end
1818
+
1819
+ ##
1820
+ # Base class for SvcParam. [RFC9460]
1821
+
1822
+ class SvcParam
1823
+
1824
+ ##
1825
+ # Get the presentation name of the SvcParamKey.
1826
+
1827
+ def self.key_name
1828
+ const_get(:KeyName)
1829
+ end
1830
+
1831
+ ##
1832
+ # Get the registered number of the SvcParamKey.
1833
+
1834
+ def self.key_number
1835
+ const_get(:KeyNumber)
1836
+ end
1837
+
1838
+ ClassHash = Hash.new do |h, key| # :nodoc:
1839
+ case key
1840
+ when Integer
1841
+ Generic.create(key)
1842
+ when /\Akey(?<key>\d+)\z/
1843
+ Generic.create(key.to_int)
1844
+ when Symbol
1845
+ raise KeyError, "unknown key #{key}"
1846
+ else
1847
+ raise TypeError, 'key must be either String or Symbol'
1848
+ end
1849
+ end
1850
+
1851
+ ##
1852
+ # Generic SvcParam abstract class.
1853
+
1854
+ class Generic < SvcParam
1855
+
1856
+ ##
1857
+ # SvcParamValue in wire-format byte string.
1858
+
1859
+ attr_reader :value
1860
+
1861
+ ##
1862
+ # Create generic SvcParam
1863
+
1864
+ def initialize(value)
1865
+ @value = value
1866
+ end
1867
+
1868
+ def encode(msg) # :nodoc:
1869
+ msg.put_bytes(@value)
1870
+ end
1871
+
1872
+ def self.decode(msg) # :nodoc:
1873
+ return self.new(msg.get_bytes)
1874
+ end
1875
+
1876
+ def self.create(key_number)
1877
+ c = Class.new(Generic)
1878
+ key_name = :"key#{key_number}"
1879
+ c.const_set(:KeyName, key_name)
1880
+ c.const_set(:KeyNumber, key_number)
1881
+ self.const_set(:"Key#{key_number}", c)
1882
+ ClassHash[key_name] = ClassHash[key_number] = c
1883
+ return c
1884
+ end
1885
+ end
1886
+
1887
+ ##
1888
+ # "mandatory" SvcParam -- Mandatory keys in service binding RR
1889
+
1890
+ class Mandatory < SvcParam
1891
+ KeyName = :mandatory
1892
+ KeyNumber = 0
1893
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1894
+
1895
+ ##
1896
+ # Mandatory keys.
1897
+
1898
+ attr_reader :keys
1899
+
1900
+ ##
1901
+ # Initialize "mandatory" ScvParam.
1902
+
1903
+ def initialize(keys)
1904
+ @keys = keys.map(&:to_int)
1905
+ end
1906
+
1907
+ def encode(msg) # :nodoc:
1908
+ @keys.sort.each do |key|
1909
+ msg.put_pack('n', key)
1910
+ end
1911
+ end
1912
+
1913
+ def self.decode(msg) # :nodoc:
1914
+ keys = msg.get_list { msg.get_unpack('n')[0] }
1915
+ return self.new(keys)
1916
+ end
1917
+ end
1918
+
1919
+ ##
1920
+ # "alpn" SvcParam -- Additional supported protocols
1921
+
1922
+ class ALPN < SvcParam
1923
+ KeyName = :alpn
1924
+ KeyNumber = 1
1925
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1926
+
1927
+ ##
1928
+ # Supported protocol IDs.
1929
+
1930
+ attr_reader :protocol_ids
1931
+
1932
+ ##
1933
+ # Initialize "alpn" ScvParam.
1934
+
1935
+ def initialize(protocol_ids)
1936
+ @protocol_ids = protocol_ids.map(&:to_str)
1937
+ end
1938
+
1939
+ def encode(msg) # :nodoc:
1940
+ msg.put_string_list(@protocol_ids)
1941
+ end
1942
+
1943
+ def self.decode(msg) # :nodoc:
1944
+ return self.new(msg.get_string_list)
1945
+ end
1946
+ end
1947
+
1948
+ ##
1949
+ # "no-default-alpn" SvcParam -- No support for default protocol
1950
+
1951
+ class NoDefaultALPN < SvcParam
1952
+ KeyName = :'no-default-alpn'
1953
+ KeyNumber = 2
1954
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1955
+
1956
+ def encode(msg) # :nodoc:
1957
+ # no payload
1958
+ end
1959
+
1960
+ def self.decode(msg) # :nodoc:
1961
+ return self.new
1962
+ end
1963
+ end
1964
+
1965
+ ##
1966
+ # "port" SvcParam -- Port for alternative endpoint
1967
+
1968
+ class Port < SvcParam
1969
+ KeyName = :port
1970
+ KeyNumber = 3
1971
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1972
+
1973
+ ##
1974
+ # Port number.
1975
+
1976
+ attr_reader :port
1977
+
1978
+ ##
1979
+ # Initialize "port" ScvParam.
1980
+
1981
+ def initialize(port)
1982
+ @port = port.to_int
1983
+ end
1984
+
1985
+ def encode(msg) # :nodoc:
1986
+ msg.put_pack('n', @port)
1987
+ end
1988
+
1989
+ def self.decode(msg) # :nodoc:
1990
+ port, = msg.get_unpack('n')
1991
+ return self.new(port)
1992
+ end
1993
+ end
1994
+
1995
+ ##
1996
+ # "ipv4hint" SvcParam -- IPv4 address hints
1997
+
1998
+ class IPv4Hint < SvcParam
1999
+ KeyName = :ipv4hint
2000
+ KeyNumber = 4
2001
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
2002
+
2003
+ ##
2004
+ # Set of IPv4 addresses.
2005
+
2006
+ attr_reader :addresses
2007
+
2008
+ ##
2009
+ # Initialize "ipv4hint" ScvParam.
2010
+
2011
+ def initialize(addresses)
2012
+ @addresses = addresses.map {|address| IPv4.create(address) }
2013
+ end
2014
+
2015
+ def encode(msg) # :nodoc:
2016
+ @addresses.each do |address|
2017
+ msg.put_bytes(address.address)
2018
+ end
2019
+ end
2020
+
2021
+ def self.decode(msg) # :nodoc:
2022
+ addresses = msg.get_list { IPv4.new(msg.get_bytes(4)) }
2023
+ return self.new(addresses)
2024
+ end
2025
+ end
2026
+
2027
+ ##
2028
+ # "ipv6hint" SvcParam -- IPv6 address hints
2029
+
2030
+ class IPv6Hint < SvcParam
2031
+ KeyName = :ipv6hint
2032
+ KeyNumber = 6
2033
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
2034
+
2035
+ ##
2036
+ # Set of IPv6 addresses.
2037
+
2038
+ attr_reader :addresses
2039
+
2040
+ ##
2041
+ # Initialize "ipv6hint" ScvParam.
2042
+
2043
+ def initialize(addresses)
2044
+ @addresses = addresses.map {|address| IPv6.create(address) }
2045
+ end
2046
+
2047
+ def encode(msg) # :nodoc:
2048
+ @addresses.each do |address|
2049
+ msg.put_bytes(address.address)
2050
+ end
2051
+ end
2052
+
2053
+ def self.decode(msg) # :nodoc:
2054
+ addresses = msg.get_list { IPv6.new(msg.get_bytes(16)) }
2055
+ return self.new(addresses)
2056
+ end
2057
+ end
2058
+
2059
+ ##
2060
+ # "dohpath" SvcParam -- DNS over HTTPS path template [RFC9461]
2061
+
2062
+ class DoHPath < SvcParam
2063
+ KeyName = :dohpath
2064
+ KeyNumber = 7
2065
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
2066
+
2067
+ ##
2068
+ # URI template for DoH queries.
2069
+
2070
+ attr_reader :template
2071
+
2072
+ ##
2073
+ # Initialize "dohpath" ScvParam.
2074
+
2075
+ def initialize(template)
2076
+ @template = template.encode('utf-8')
2077
+ end
2078
+
2079
+ def encode(msg) # :nodoc:
2080
+ msg.put_bytes(@template)
2081
+ end
2082
+
2083
+ def self.decode(msg) # :nodoc:
2084
+ template = msg.get_bytes.force_encoding('utf-8')
2085
+ return self.new(template)
2086
+ end
2087
+ end
2088
+ end
2089
+
2090
+ ##
2091
+ # A DNS query abstract class.
2092
+
2093
+ class Query
2094
+ def encode_rdata(msg) # :nodoc:
2095
+ raise EncodeError.new("#{self.class} is query.")
2096
+ end
2097
+
2098
+ def self.decode_rdata(msg) # :nodoc:
2099
+ raise DecodeError.new("#{self.class} is query.")
2100
+ end
2101
+ end
2102
+
2103
+ ##
2104
+ # A DNS resource abstract class.
2105
+
2106
+ class Resource < Query
2107
+
2108
+ ##
2109
+ # Remaining Time To Live for this Resource.
2110
+
2111
+ attr_reader :ttl
2112
+
2113
+ ClassHash = {} # :nodoc:
2114
+
2115
+ def encode_rdata(msg) # :nodoc:
2116
+ raise NotImplementedError.new
2117
+ end
2118
+
2119
+ def self.decode_rdata(msg) # :nodoc:
2120
+ raise NotImplementedError.new
2121
+ end
2122
+
2123
+ def ==(other) # :nodoc:
2124
+ return false unless self.class == other.class
2125
+ s_ivars = self.instance_variables
2126
+ s_ivars.sort!
2127
+ s_ivars.delete :@ttl
2128
+ o_ivars = other.instance_variables
2129
+ o_ivars.sort!
2130
+ o_ivars.delete :@ttl
2131
+ return s_ivars == o_ivars &&
2132
+ s_ivars.collect {|name| self.instance_variable_get name} ==
2133
+ o_ivars.collect {|name| other.instance_variable_get name}
2134
+ end
2135
+
2136
+ def eql?(other) # :nodoc:
2137
+ return self == other
2138
+ end
2139
+
2140
+ def hash # :nodoc:
2141
+ h = 0
2142
+ vars = self.instance_variables
2143
+ vars.delete :@ttl
2144
+ vars.each {|name|
2145
+ h ^= self.instance_variable_get(name).hash
2146
+ }
2147
+ return h
2148
+ end
2149
+
2150
+ def self.get_class(type_value, class_value) # :nodoc:
2151
+ return ClassHash[[type_value, class_value]] ||
2152
+ Generic.create(type_value, class_value)
2153
+ end
2154
+
2155
+ ##
2156
+ # A generic resource abstract class.
2157
+
2158
+ class Generic < Resource
2159
+
2160
+ ##
2161
+ # Creates a new generic resource.
2162
+
2163
+ def initialize(data)
2164
+ @data = data
2165
+ end
2166
+
2167
+ ##
2168
+ # Data for this generic resource.
2169
+
2170
+ attr_reader :data
2171
+
2172
+ def encode_rdata(msg) # :nodoc:
2173
+ msg.put_bytes(data)
2174
+ end
2175
+
2176
+ def self.decode_rdata(msg) # :nodoc:
2177
+ return self.new(msg.get_bytes)
2178
+ end
2179
+
2180
+ def self.create(type_value, class_value) # :nodoc:
2181
+ c = Class.new(Generic)
2182
+ c.const_set(:TypeValue, type_value)
2183
+ c.const_set(:ClassValue, class_value)
2184
+ Generic.const_set("Type#{type_value}_Class#{class_value}", c)
2185
+ ClassHash[[type_value, class_value]] = c
2186
+ return c
2187
+ end
2188
+ end
2189
+
2190
+ ##
2191
+ # Domain Name resource abstract class.
2192
+
2193
+ class DomainName < Resource
2194
+
2195
+ ##
2196
+ # Creates a new DomainName from +name+.
2197
+
2198
+ def initialize(name)
2199
+ @name = name
2200
+ end
2201
+
2202
+ ##
2203
+ # The name of this DomainName.
2204
+
2205
+ attr_reader :name
2206
+
2207
+ def encode_rdata(msg) # :nodoc:
2208
+ msg.put_name(@name)
2209
+ end
2210
+
2211
+ def self.decode_rdata(msg) # :nodoc:
2212
+ return self.new(msg.get_name)
2213
+ end
2214
+ end
2215
+
2216
+ # Standard (class generic) RRs
2217
+
2218
+ ClassValue = nil # :nodoc:
2219
+
2220
+ ##
2221
+ # An authoritative name server.
2222
+
2223
+ class NS < DomainName
2224
+ TypeValue = 2 # :nodoc:
2225
+ end
2226
+
2227
+ ##
2228
+ # The canonical name for an alias.
2229
+
2230
+ class CNAME < DomainName
2231
+ TypeValue = 5 # :nodoc:
2232
+ end
2233
+
2234
+ ##
2235
+ # Start Of Authority resource.
2236
+
2237
+ class SOA < Resource
2238
+
2239
+ TypeValue = 6 # :nodoc:
2240
+
2241
+ ##
2242
+ # Creates a new SOA record. See the attr documentation for the
2243
+ # details of each argument.
2244
+
2245
+ def initialize(mname, rname, serial, refresh, retry_, expire, minimum)
2246
+ @mname = mname
2247
+ @rname = rname
2248
+ @serial = serial
2249
+ @refresh = refresh
2250
+ @retry = retry_
2251
+ @expire = expire
2252
+ @minimum = minimum
2253
+ end
2254
+
2255
+ ##
2256
+ # Name of the host where the master zone file for this zone resides.
2257
+
2258
+ attr_reader :mname
2259
+
2260
+ ##
2261
+ # The person responsible for this domain name.
2262
+
2263
+ attr_reader :rname
2264
+
2265
+ ##
2266
+ # The version number of the zone file.
2267
+
2268
+ attr_reader :serial
2269
+
2270
+ ##
2271
+ # How often, in seconds, a secondary name server is to check for
2272
+ # updates from the primary name server.
2273
+
2274
+ attr_reader :refresh
2275
+
2276
+ ##
2277
+ # How often, in seconds, a secondary name server is to retry after a
2278
+ # failure to check for a refresh.
2279
+
2280
+ attr_reader :retry
2281
+
2282
+ ##
2283
+ # Time in seconds that a secondary name server is to use the data
2284
+ # before refreshing from the primary name server.
2285
+
2286
+ attr_reader :expire
2287
+
2288
+ ##
2289
+ # The minimum number of seconds to be used for TTL values in RRs.
2290
+
2291
+ attr_reader :minimum
2292
+
2293
+ def encode_rdata(msg) # :nodoc:
2294
+ msg.put_name(@mname)
2295
+ msg.put_name(@rname)
2296
+ msg.put_pack('NNNNN', @serial, @refresh, @retry, @expire, @minimum)
2297
+ end
2298
+
2299
+ def self.decode_rdata(msg) # :nodoc:
2300
+ mname = msg.get_name
2301
+ rname = msg.get_name
2302
+ serial, refresh, retry_, expire, minimum = msg.get_unpack('NNNNN')
2303
+ return self.new(
2304
+ mname, rname, serial, refresh, retry_, expire, minimum)
2305
+ end
2306
+ end
2307
+
2308
+ ##
2309
+ # A Pointer to another DNS name.
2310
+
2311
+ class PTR < DomainName
2312
+ TypeValue = 12 # :nodoc:
2313
+ end
2314
+
2315
+ ##
2316
+ # Host Information resource.
2317
+
2318
+ class HINFO < Resource
2319
+
2320
+ TypeValue = 13 # :nodoc:
2321
+
2322
+ ##
2323
+ # Creates a new HINFO running +os+ on +cpu+.
2324
+
2325
+ def initialize(cpu, os)
2326
+ @cpu = cpu
2327
+ @os = os
2328
+ end
2329
+
2330
+ ##
2331
+ # CPU architecture for this resource.
2332
+
2333
+ attr_reader :cpu
2334
+
2335
+ ##
2336
+ # Operating system for this resource.
2337
+
2338
+ attr_reader :os
2339
+
2340
+ def encode_rdata(msg) # :nodoc:
2341
+ msg.put_string(@cpu)
2342
+ msg.put_string(@os)
2343
+ end
2344
+
2345
+ def self.decode_rdata(msg) # :nodoc:
2346
+ cpu = msg.get_string
2347
+ os = msg.get_string
2348
+ return self.new(cpu, os)
2349
+ end
2350
+ end
2351
+
2352
+ ##
2353
+ # Mailing list or mailbox information.
2354
+
2355
+ class MINFO < Resource
2356
+
2357
+ TypeValue = 14 # :nodoc:
2358
+
2359
+ def initialize(rmailbx, emailbx)
2360
+ @rmailbx = rmailbx
2361
+ @emailbx = emailbx
2362
+ end
2363
+
2364
+ ##
2365
+ # Domain name responsible for this mail list or mailbox.
2366
+
2367
+ attr_reader :rmailbx
2368
+
2369
+ ##
2370
+ # Mailbox to use for error messages related to the mail list or mailbox.
2371
+
2372
+ attr_reader :emailbx
2373
+
2374
+ def encode_rdata(msg) # :nodoc:
2375
+ msg.put_name(@rmailbx)
2376
+ msg.put_name(@emailbx)
2377
+ end
2378
+
2379
+ def self.decode_rdata(msg) # :nodoc:
2380
+ rmailbx = msg.get_string
2381
+ emailbx = msg.get_string
2382
+ return self.new(rmailbx, emailbx)
2383
+ end
2384
+ end
2385
+
2386
+ ##
2387
+ # Mail Exchanger resource.
2388
+
2389
+ class MX < Resource
2390
+
2391
+ TypeValue= 15 # :nodoc:
2392
+
2393
+ ##
2394
+ # Creates a new MX record with +preference+, accepting mail at
2395
+ # +exchange+.
2396
+
2397
+ def initialize(preference, exchange)
2398
+ @preference = preference
2399
+ @exchange = exchange
2400
+ end
2401
+
2402
+ ##
2403
+ # The preference for this MX.
2404
+
2405
+ attr_reader :preference
2406
+
2407
+ ##
2408
+ # The host of this MX.
2409
+
2410
+ attr_reader :exchange
2411
+
2412
+ def encode_rdata(msg) # :nodoc:
2413
+ msg.put_pack('n', @preference)
2414
+ msg.put_name(@exchange)
2415
+ end
2416
+
2417
+ def self.decode_rdata(msg) # :nodoc:
2418
+ preference, = msg.get_unpack('n')
2419
+ exchange = msg.get_name
2420
+ return self.new(preference, exchange)
2421
+ end
2422
+ end
2423
+
2424
+ ##
2425
+ # Unstructured text resource.
2426
+
2427
+ class TXT < Resource
2428
+
2429
+ TypeValue = 16 # :nodoc:
2430
+
2431
+ def initialize(first_string, *rest_strings)
2432
+ @strings = [first_string, *rest_strings]
2433
+ end
2434
+
2435
+ ##
2436
+ # Returns an Array of Strings for this TXT record.
2437
+
2438
+ attr_reader :strings
2439
+
2440
+ ##
2441
+ # Returns the concatenated string from +strings+.
2442
+
2443
+ def data
2444
+ @strings.join("")
2445
+ end
2446
+
2447
+ def encode_rdata(msg) # :nodoc:
2448
+ msg.put_string_list(@strings)
2449
+ end
2450
+
2451
+ def self.decode_rdata(msg) # :nodoc:
2452
+ strings = msg.get_string_list
2453
+ return self.new(*strings)
2454
+ end
2455
+ end
2456
+
2457
+ ##
2458
+ # Location resource
2459
+
2460
+ class LOC < Resource
2461
+
2462
+ TypeValue = 29 # :nodoc:
2463
+
2464
+ def initialize(version, ssize, hprecision, vprecision, latitude, longitude, altitude)
2465
+ @version = version
2466
+ @ssize = Gem::Resolv::LOC::Size.create(ssize)
2467
+ @hprecision = Gem::Resolv::LOC::Size.create(hprecision)
2468
+ @vprecision = Gem::Resolv::LOC::Size.create(vprecision)
2469
+ @latitude = Gem::Resolv::LOC::Coord.create(latitude)
2470
+ @longitude = Gem::Resolv::LOC::Coord.create(longitude)
2471
+ @altitude = Gem::Resolv::LOC::Alt.create(altitude)
2472
+ end
2473
+
2474
+ ##
2475
+ # Returns the version value for this LOC record which should always be 00
2476
+
2477
+ attr_reader :version
2478
+
2479
+ ##
2480
+ # The spherical size of this LOC
2481
+ # in meters using scientific notation as 2 integers of XeY
2482
+
2483
+ attr_reader :ssize
2484
+
2485
+ ##
2486
+ # The horizontal precision using ssize type values
2487
+ # in meters using scientific notation as 2 integers of XeY
2488
+ # for precision use value/2 e.g. 2m = +/-1m
2489
+
2490
+ attr_reader :hprecision
2491
+
2492
+ ##
2493
+ # The vertical precision using ssize type values
2494
+ # in meters using scientific notation as 2 integers of XeY
2495
+ # for precision use value/2 e.g. 2m = +/-1m
2496
+
2497
+ attr_reader :vprecision
2498
+
2499
+ ##
2500
+ # The latitude for this LOC where 2**31 is the equator
2501
+ # in thousandths of an arc second as an unsigned 32bit integer
2502
+
2503
+ attr_reader :latitude
2504
+
2505
+ ##
2506
+ # The longitude for this LOC where 2**31 is the prime meridian
2507
+ # in thousandths of an arc second as an unsigned 32bit integer
2508
+
2509
+ attr_reader :longitude
2510
+
2511
+ ##
2512
+ # The altitude of the LOC above a reference sphere whose surface sits 100km below the WGS84 spheroid
2513
+ # in centimeters as an unsigned 32bit integer
2514
+
2515
+ attr_reader :altitude
2516
+
2517
+ def encode_rdata(msg) # :nodoc:
2518
+ msg.put_bytes(@version)
2519
+ msg.put_bytes(@ssize.scalar)
2520
+ msg.put_bytes(@hprecision.scalar)
2521
+ msg.put_bytes(@vprecision.scalar)
2522
+ msg.put_bytes(@latitude.coordinates)
2523
+ msg.put_bytes(@longitude.coordinates)
2524
+ msg.put_bytes(@altitude.altitude)
2525
+ end
2526
+
2527
+ def self.decode_rdata(msg) # :nodoc:
2528
+ version = msg.get_bytes(1)
2529
+ ssize = msg.get_bytes(1)
2530
+ hprecision = msg.get_bytes(1)
2531
+ vprecision = msg.get_bytes(1)
2532
+ latitude = msg.get_bytes(4)
2533
+ longitude = msg.get_bytes(4)
2534
+ altitude = msg.get_bytes(4)
2535
+ return self.new(
2536
+ version,
2537
+ Gem::Resolv::LOC::Size.new(ssize),
2538
+ Gem::Resolv::LOC::Size.new(hprecision),
2539
+ Gem::Resolv::LOC::Size.new(vprecision),
2540
+ Gem::Resolv::LOC::Coord.new(latitude,"lat"),
2541
+ Gem::Resolv::LOC::Coord.new(longitude,"lon"),
2542
+ Gem::Resolv::LOC::Alt.new(altitude)
2543
+ )
2544
+ end
2545
+ end
2546
+
2547
+ ##
2548
+ # A Query type requesting any RR.
2549
+
2550
+ class ANY < Query
2551
+ TypeValue = 255 # :nodoc:
2552
+ end
2553
+
2554
+ ##
2555
+ # CAA resource record defined in RFC 8659
2556
+ #
2557
+ # These records identify certificate authority allowed to issue
2558
+ # certificates for the given domain.
2559
+
2560
+ class CAA < Resource
2561
+ TypeValue = 257
2562
+
2563
+ ##
2564
+ # Creates a new CAA for +flags+, +tag+ and +value+.
2565
+
2566
+ def initialize(flags, tag, value)
2567
+ unless (0..255) === flags
2568
+ raise ArgumentError.new('flags must be an Integer between 0 and 255')
2569
+ end
2570
+ unless (1..15) === tag.bytesize
2571
+ raise ArgumentError.new('length of tag must be between 1 and 15')
2572
+ end
2573
+
2574
+ @flags = flags
2575
+ @tag = tag
2576
+ @value = value
2577
+ end
2578
+
2579
+ ##
2580
+ # Flags for this proprty:
2581
+ # - Bit 0 : 0 = not critical, 1 = critical
2582
+
2583
+ attr_reader :flags
2584
+
2585
+ ##
2586
+ # Property tag ("issue", "issuewild", "iodef"...).
2587
+
2588
+ attr_reader :tag
2589
+
2590
+ ##
2591
+ # Property value.
2592
+
2593
+ attr_reader :value
2594
+
2595
+ ##
2596
+ # Whether the critical flag is set on this property.
2597
+
2598
+ def critical?
2599
+ flags & 0x80 != 0
2600
+ end
2601
+
2602
+ def encode_rdata(msg) # :nodoc:
2603
+ msg.put_pack('C', @flags)
2604
+ msg.put_string(@tag)
2605
+ msg.put_bytes(@value)
2606
+ end
2607
+
2608
+ def self.decode_rdata(msg) # :nodoc:
2609
+ flags, = msg.get_unpack('C')
2610
+ tag = msg.get_string
2611
+ value = msg.get_bytes
2612
+ self.new flags, tag, value
2613
+ end
2614
+ end
2615
+
2616
+ ClassInsensitiveTypes = [ # :nodoc:
2617
+ NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, LOC, ANY, CAA
2618
+ ]
2619
+
2620
+ ##
2621
+ # module IN contains ARPA Internet specific RRs.
2622
+
2623
+ module IN
2624
+
2625
+ ClassValue = 1 # :nodoc:
2626
+
2627
+ ClassInsensitiveTypes.each {|s|
2628
+ c = Class.new(s)
2629
+ c.const_set(:TypeValue, s::TypeValue)
2630
+ c.const_set(:ClassValue, ClassValue)
2631
+ ClassHash[[s::TypeValue, ClassValue]] = c
2632
+ self.const_set(s.name.sub(/.*::/, ''), c)
2633
+ }
2634
+
2635
+ ##
2636
+ # IPv4 Address resource
2637
+
2638
+ class A < Resource
2639
+ TypeValue = 1
2640
+ ClassValue = IN::ClassValue
2641
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2642
+
2643
+ ##
2644
+ # Creates a new A for +address+.
2645
+
2646
+ def initialize(address)
2647
+ @address = IPv4.create(address)
2648
+ end
2649
+
2650
+ ##
2651
+ # The Gem::Resolv::IPv4 address for this A.
2652
+
2653
+ attr_reader :address
2654
+
2655
+ def encode_rdata(msg) # :nodoc:
2656
+ msg.put_bytes(@address.address)
2657
+ end
2658
+
2659
+ def self.decode_rdata(msg) # :nodoc:
2660
+ return self.new(IPv4.new(msg.get_bytes(4)))
2661
+ end
2662
+ end
2663
+
2664
+ ##
2665
+ # Well Known Service resource.
2666
+
2667
+ class WKS < Resource
2668
+ TypeValue = 11
2669
+ ClassValue = IN::ClassValue
2670
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2671
+
2672
+ def initialize(address, protocol, bitmap)
2673
+ @address = IPv4.create(address)
2674
+ @protocol = protocol
2675
+ @bitmap = bitmap
2676
+ end
2677
+
2678
+ ##
2679
+ # The host these services run on.
2680
+
2681
+ attr_reader :address
2682
+
2683
+ ##
2684
+ # IP protocol number for these services.
2685
+
2686
+ attr_reader :protocol
2687
+
2688
+ ##
2689
+ # A bit map of enabled services on this host.
2690
+ #
2691
+ # If protocol is 6 (TCP) then the 26th bit corresponds to the SMTP
2692
+ # service (port 25). If this bit is set, then an SMTP server should
2693
+ # be listening on TCP port 25; if zero, SMTP service is not
2694
+ # supported.
2695
+
2696
+ attr_reader :bitmap
2697
+
2698
+ def encode_rdata(msg) # :nodoc:
2699
+ msg.put_bytes(@address.address)
2700
+ msg.put_pack("n", @protocol)
2701
+ msg.put_bytes(@bitmap)
2702
+ end
2703
+
2704
+ def self.decode_rdata(msg) # :nodoc:
2705
+ address = IPv4.new(msg.get_bytes(4))
2706
+ protocol, = msg.get_unpack("n")
2707
+ bitmap = msg.get_bytes
2708
+ return self.new(address, protocol, bitmap)
2709
+ end
2710
+ end
2711
+
2712
+ ##
2713
+ # An IPv6 address record.
2714
+
2715
+ class AAAA < Resource
2716
+ TypeValue = 28
2717
+ ClassValue = IN::ClassValue
2718
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2719
+
2720
+ ##
2721
+ # Creates a new AAAA for +address+.
2722
+
2723
+ def initialize(address)
2724
+ @address = IPv6.create(address)
2725
+ end
2726
+
2727
+ ##
2728
+ # The Gem::Resolv::IPv6 address for this AAAA.
2729
+
2730
+ attr_reader :address
2731
+
2732
+ def encode_rdata(msg) # :nodoc:
2733
+ msg.put_bytes(@address.address)
2734
+ end
2735
+
2736
+ def self.decode_rdata(msg) # :nodoc:
2737
+ return self.new(IPv6.new(msg.get_bytes(16)))
2738
+ end
2739
+ end
2740
+
2741
+ ##
2742
+ # SRV resource record defined in RFC 2782
2743
+ #
2744
+ # These records identify the hostname and port that a service is
2745
+ # available at.
2746
+
2747
+ class SRV < Resource
2748
+ TypeValue = 33
2749
+ ClassValue = IN::ClassValue
2750
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2751
+
2752
+ # Create a SRV resource record.
2753
+ #
2754
+ # See the documentation for #priority, #weight, #port and #target
2755
+ # for +priority+, +weight+, +port and +target+ respectively.
2756
+
2757
+ def initialize(priority, weight, port, target)
2758
+ @priority = priority.to_int
2759
+ @weight = weight.to_int
2760
+ @port = port.to_int
2761
+ @target = Name.create(target)
2762
+ end
2763
+
2764
+ # The priority of this target host.
2765
+ #
2766
+ # A client MUST attempt to contact the target host with the
2767
+ # lowest-numbered priority it can reach; target hosts with the same
2768
+ # priority SHOULD be tried in an order defined by the weight field.
2769
+ # The range is 0-65535. Note that it is not widely implemented and
2770
+ # should be set to zero.
2771
+
2772
+ attr_reader :priority
2773
+
2774
+ # A server selection mechanism.
2775
+ #
2776
+ # The weight field specifies a relative weight for entries with the
2777
+ # same priority. Larger weights SHOULD be given a proportionately
2778
+ # higher probability of being selected. The range of this number is
2779
+ # 0-65535. Domain administrators SHOULD use Weight 0 when there
2780
+ # isn't any server selection to do, to make the RR easier to read
2781
+ # for humans (less noisy). Note that it is not widely implemented
2782
+ # and should be set to zero.
2783
+
2784
+ attr_reader :weight
2785
+
2786
+ # The port on this target host of this service.
2787
+ #
2788
+ # The range is 0-65535.
2789
+
2790
+ attr_reader :port
2791
+
2792
+ # The domain name of the target host.
2793
+ #
2794
+ # A target of "." means that the service is decidedly not available
2795
+ # at this domain.
2796
+
2797
+ attr_reader :target
2798
+
2799
+ def encode_rdata(msg) # :nodoc:
2800
+ msg.put_pack("n", @priority)
2801
+ msg.put_pack("n", @weight)
2802
+ msg.put_pack("n", @port)
2803
+ msg.put_name(@target, compress: false)
2804
+ end
2805
+
2806
+ def self.decode_rdata(msg) # :nodoc:
2807
+ priority, = msg.get_unpack("n")
2808
+ weight, = msg.get_unpack("n")
2809
+ port, = msg.get_unpack("n")
2810
+ target = msg.get_name
2811
+ return self.new(priority, weight, port, target)
2812
+ end
2813
+ end
2814
+
2815
+ ##
2816
+ # Common implementation for SVCB-compatible resource records.
2817
+
2818
+ class ServiceBinding
2819
+
2820
+ ##
2821
+ # Create a service binding resource record.
2822
+
2823
+ def initialize(priority, target, params = [])
2824
+ @priority = priority.to_int
2825
+ @target = Name.create(target)
2826
+ @params = SvcParams.new(params)
2827
+ end
2828
+
2829
+ ##
2830
+ # The priority of this target host.
2831
+ #
2832
+ # The range is 0-65535.
2833
+ # If set to 0, this RR is in AliasMode. Otherwise, it is in ServiceMode.
2834
+
2835
+ attr_reader :priority
2836
+
2837
+ ##
2838
+ # The domain name of the target host.
2839
+
2840
+ attr_reader :target
2841
+
2842
+ ##
2843
+ # The service parameters for the target host.
2844
+
2845
+ attr_reader :params
2846
+
2847
+ ##
2848
+ # Whether this RR is in AliasMode.
2849
+
2850
+ def alias_mode?
2851
+ self.priority == 0
2852
+ end
2853
+
2854
+ ##
2855
+ # Whether this RR is in ServiceMode.
2856
+
2857
+ def service_mode?
2858
+ !alias_mode?
2859
+ end
2860
+
2861
+ def encode_rdata(msg) # :nodoc:
2862
+ msg.put_pack("n", @priority)
2863
+ msg.put_name(@target, compress: false)
2864
+ @params.encode(msg)
2865
+ end
2866
+
2867
+ def self.decode_rdata(msg) # :nodoc:
2868
+ priority, = msg.get_unpack("n")
2869
+ target = msg.get_name
2870
+ params = SvcParams.decode(msg)
2871
+ return self.new(priority, target, params)
2872
+ end
2873
+ end
2874
+
2875
+ ##
2876
+ # SVCB resource record [RFC9460]
2877
+
2878
+ class SVCB < ServiceBinding
2879
+ TypeValue = 64
2880
+ ClassValue = IN::ClassValue
2881
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2882
+ end
2883
+
2884
+ ##
2885
+ # HTTPS resource record [RFC9460]
2886
+
2887
+ class HTTPS < ServiceBinding
2888
+ TypeValue = 65
2889
+ ClassValue = IN::ClassValue
2890
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2891
+ end
2892
+ end
2893
+ end
2894
+ end
2895
+
2896
+ ##
2897
+ # A Gem::Resolv::DNS IPv4 address.
2898
+
2899
+ class IPv4
2900
+
2901
+ ##
2902
+ # Regular expression IPv4 addresses must match.
2903
+
2904
+ Regex256 = /0
2905
+ |1(?:[0-9][0-9]?)?
2906
+ |2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
2907
+ |[3-9][0-9]?/x
2908
+ Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
2909
+
2910
+ def self.create(arg)
2911
+ case arg
2912
+ when IPv4
2913
+ return arg
2914
+ when Regex
2915
+ if (0..255) === (a = $1.to_i) &&
2916
+ (0..255) === (b = $2.to_i) &&
2917
+ (0..255) === (c = $3.to_i) &&
2918
+ (0..255) === (d = $4.to_i)
2919
+ return self.new([a, b, c, d].pack("CCCC"))
2920
+ else
2921
+ raise ArgumentError.new("IPv4 address with invalid value: " + arg)
2922
+ end
2923
+ else
2924
+ raise ArgumentError.new("cannot interpret as IPv4 address: #{arg.inspect}")
2925
+ end
2926
+ end
2927
+
2928
+ def initialize(address) # :nodoc:
2929
+ unless address.kind_of?(String)
2930
+ raise ArgumentError, 'IPv4 address must be a string'
2931
+ end
2932
+ unless address.length == 4
2933
+ raise ArgumentError, "IPv4 address expects 4 bytes but #{address.length} bytes"
2934
+ end
2935
+ @address = address
2936
+ end
2937
+
2938
+ ##
2939
+ # A String representation of this IPv4 address.
2940
+
2941
+ ##
2942
+ # The raw IPv4 address as a String.
2943
+
2944
+ attr_reader :address
2945
+
2946
+ def to_s # :nodoc:
2947
+ return sprintf("%d.%d.%d.%d", *@address.unpack("CCCC"))
2948
+ end
2949
+
2950
+ def inspect # :nodoc:
2951
+ return "#<#{self.class} #{self}>"
2952
+ end
2953
+
2954
+ ##
2955
+ # Turns this IPv4 address into a Gem::Resolv::DNS::Name.
2956
+
2957
+ def to_name
2958
+ return DNS::Name.create(
2959
+ '%d.%d.%d.%d.in-addr.arpa.' % @address.unpack('CCCC').reverse)
2960
+ end
2961
+
2962
+ def ==(other) # :nodoc:
2963
+ return @address == other.address
2964
+ end
2965
+
2966
+ def eql?(other) # :nodoc:
2967
+ return self == other
2968
+ end
2969
+
2970
+ def hash # :nodoc:
2971
+ return @address.hash
2972
+ end
2973
+ end
2974
+
2975
+ ##
2976
+ # A Gem::Resolv::DNS IPv6 address.
2977
+
2978
+ class IPv6
2979
+
2980
+ ##
2981
+ # IPv6 address format a:b:c:d:e:f:g:h
2982
+ Regex_8Hex = /\A
2983
+ (?:[0-9A-Fa-f]{1,4}:){7}
2984
+ [0-9A-Fa-f]{1,4}
2985
+ \z/x
2986
+
2987
+ ##
2988
+ # Compressed IPv6 address format a::b
2989
+
2990
+ Regex_CompressedHex = /\A
2991
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
2992
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
2993
+ \z/x
2994
+
2995
+ ##
2996
+ # IPv4 mapped IPv6 address format a:b:c:d:e:f:w.x.y.z
2997
+
2998
+ Regex_6Hex4Dec = /\A
2999
+ ((?:[0-9A-Fa-f]{1,4}:){6,6})
3000
+ (\d+)\.(\d+)\.(\d+)\.(\d+)
3001
+ \z/x
3002
+
3003
+ ##
3004
+ # Compressed IPv4 mapped IPv6 address format a::b:w.x.y.z
3005
+
3006
+ Regex_CompressedHex4Dec = /\A
3007
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
3008
+ ((?:[0-9A-Fa-f]{1,4}:)*)
3009
+ (\d+)\.(\d+)\.(\d+)\.(\d+)
3010
+ \z/x
3011
+
3012
+ ##
3013
+ # IPv6 link local address format fe80:b:c:d:e:f:g:h%em1
3014
+ Regex_8HexLinkLocal = /\A
3015
+ [Ff][Ee]80
3016
+ (?::[0-9A-Fa-f]{1,4}){7}
3017
+ %[-0-9A-Za-z._~]+
3018
+ \z/x
3019
+
3020
+ ##
3021
+ # Compressed IPv6 link local address format fe80::b%em1
3022
+
3023
+ Regex_CompressedHexLinkLocal = /\A
3024
+ [Ff][Ee]80:
3025
+ (?:
3026
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
3027
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
3028
+ |
3029
+ :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
3030
+ )?
3031
+ :[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+
3032
+ \z/x
3033
+
3034
+ ##
3035
+ # A composite IPv6 address Regexp.
3036
+
3037
+ Regex = /
3038
+ (?:#{Regex_8Hex}) |
3039
+ (?:#{Regex_CompressedHex}) |
3040
+ (?:#{Regex_6Hex4Dec}) |
3041
+ (?:#{Regex_CompressedHex4Dec}) |
3042
+ (?:#{Regex_8HexLinkLocal}) |
3043
+ (?:#{Regex_CompressedHexLinkLocal})
3044
+ /x
3045
+
3046
+ ##
3047
+ # Creates a new IPv6 address from +arg+ which may be:
3048
+ #
3049
+ # IPv6:: returns +arg+.
3050
+ # String:: +arg+ must match one of the IPv6::Regex* constants
3051
+
3052
+ def self.create(arg)
3053
+ case arg
3054
+ when IPv6
3055
+ return arg
3056
+ when String
3057
+ address = ''.b
3058
+ if Regex_8Hex =~ arg
3059
+ arg.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
3060
+ elsif Regex_CompressedHex =~ arg
3061
+ prefix = $1
3062
+ suffix = $2
3063
+ a1 = ''.b
3064
+ a2 = ''.b
3065
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
3066
+ suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
3067
+ omitlen = 16 - a1.length - a2.length
3068
+ address << a1 << "\0" * omitlen << a2
3069
+ elsif Regex_6Hex4Dec =~ arg
3070
+ prefix, a, b, c, d = $1, $2.to_i, $3.to_i, $4.to_i, $5.to_i
3071
+ if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
3072
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
3073
+ address << [a, b, c, d].pack('CCCC')
3074
+ else
3075
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
3076
+ end
3077
+ elsif Regex_CompressedHex4Dec =~ arg
3078
+ prefix, suffix, a, b, c, d = $1, $2, $3.to_i, $4.to_i, $5.to_i, $6.to_i
3079
+ if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
3080
+ a1 = ''.b
3081
+ a2 = ''.b
3082
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
3083
+ suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
3084
+ omitlen = 12 - a1.length - a2.length
3085
+ address << a1 << "\0" * omitlen << a2 << [a, b, c, d].pack('CCCC')
3086
+ else
3087
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
3088
+ end
3089
+ else
3090
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
3091
+ end
3092
+ return IPv6.new(address)
3093
+ else
3094
+ raise ArgumentError.new("cannot interpret as IPv6 address: #{arg.inspect}")
3095
+ end
3096
+ end
3097
+
3098
+ def initialize(address) # :nodoc:
3099
+ unless address.kind_of?(String) && address.length == 16
3100
+ raise ArgumentError.new('IPv6 address must be 16 bytes')
3101
+ end
3102
+ @address = address
3103
+ end
3104
+
3105
+ ##
3106
+ # The raw IPv6 address as a String.
3107
+
3108
+ attr_reader :address
3109
+
3110
+ def to_s # :nodoc:
3111
+ sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *@address.unpack("nnnnnnnn")).sub(/(^|:)0(:0)+(:|$)/, '::')
3112
+ end
3113
+
3114
+ def inspect # :nodoc:
3115
+ return "#<#{self.class} #{self}>"
3116
+ end
3117
+
3118
+ ##
3119
+ # Turns this IPv6 address into a Gem::Resolv::DNS::Name.
3120
+ #--
3121
+ # ip6.arpa should be searched too. [RFC3152]
3122
+
3123
+ def to_name
3124
+ return DNS::Name.new(
3125
+ @address.unpack("H32")[0].split(//).reverse + ['ip6', 'arpa'])
3126
+ end
3127
+
3128
+ def ==(other) # :nodoc:
3129
+ return @address == other.address
3130
+ end
3131
+
3132
+ def eql?(other) # :nodoc:
3133
+ return self == other
3134
+ end
3135
+
3136
+ def hash # :nodoc:
3137
+ return @address.hash
3138
+ end
3139
+ end
3140
+
3141
+ ##
3142
+ # Gem::Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver. It blindly
3143
+ # makes queries to the mDNS addresses without understanding anything about
3144
+ # multicast ports.
3145
+ #
3146
+ # Information taken form the following places:
3147
+ #
3148
+ # * RFC 6762
3149
+
3150
+ class MDNS < DNS
3151
+
3152
+ ##
3153
+ # Default mDNS Port
3154
+
3155
+ Port = 5353
3156
+
3157
+ ##
3158
+ # Default IPv4 mDNS address
3159
+
3160
+ AddressV4 = '224.0.0.251'
3161
+
3162
+ ##
3163
+ # Default IPv6 mDNS address
3164
+
3165
+ AddressV6 = 'ff02::fb'
3166
+
3167
+ ##
3168
+ # Default mDNS addresses
3169
+
3170
+ Addresses = [
3171
+ [AddressV4, Port],
3172
+ [AddressV6, Port],
3173
+ ]
3174
+
3175
+ ##
3176
+ # Creates a new one-shot Multicast DNS (mDNS) resolver.
3177
+ #
3178
+ # +config_info+ can be:
3179
+ #
3180
+ # nil::
3181
+ # Uses the default mDNS addresses
3182
+ #
3183
+ # Hash::
3184
+ # Must contain :nameserver or :nameserver_port like
3185
+ # Gem::Resolv::DNS#initialize.
3186
+
3187
+ def initialize(config_info=nil)
3188
+ if config_info then
3189
+ super({ nameserver_port: Addresses }.merge(config_info))
3190
+ else
3191
+ super(nameserver_port: Addresses)
3192
+ end
3193
+ end
3194
+
3195
+ ##
3196
+ # Iterates over all IP addresses for +name+ retrieved from the mDNS
3197
+ # resolver, provided name ends with "local". If the name does not end in
3198
+ # "local" no records will be returned.
3199
+ #
3200
+ # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved addresses will
3201
+ # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
3202
+
3203
+ def each_address(name)
3204
+ name = Gem::Resolv::DNS::Name.create(name)
3205
+
3206
+ return unless name[-1].to_s == 'local'
3207
+
3208
+ super(name)
3209
+ end
3210
+
3211
+ def make_udp_requester # :nodoc:
3212
+ nameserver_port = @config.nameserver_port
3213
+ Requester::MDNSOneShot.new(*nameserver_port)
3214
+ end
3215
+
3216
+ end
3217
+
3218
+ module LOC
3219
+
3220
+ ##
3221
+ # A Gem::Resolv::LOC::Size
3222
+
3223
+ class Size
3224
+
3225
+ Regex = /^(\d+\.*\d*)[m]$/
3226
+
3227
+ ##
3228
+ # Creates a new LOC::Size from +arg+ which may be:
3229
+ #
3230
+ # LOC::Size:: returns +arg+.
3231
+ # String:: +arg+ must match the LOC::Size::Regex constant
3232
+
3233
+ def self.create(arg)
3234
+ case arg
3235
+ when Size
3236
+ return arg
3237
+ when String
3238
+ scalar = ''
3239
+ if Regex =~ arg
3240
+ scalar = [(($1.to_f*(1e2)).to_i.to_s[0].to_i*(2**4)+(($1.to_f*(1e2)).to_i.to_s.length-1))].pack("C")
3241
+ else
3242
+ raise ArgumentError.new("not a properly formed Size string: " + arg)
3243
+ end
3244
+ return Size.new(scalar)
3245
+ else
3246
+ raise ArgumentError.new("cannot interpret as Size: #{arg.inspect}")
3247
+ end
3248
+ end
3249
+
3250
+ def initialize(scalar)
3251
+ @scalar = scalar
3252
+ end
3253
+
3254
+ ##
3255
+ # The raw size
3256
+
3257
+ attr_reader :scalar
3258
+
3259
+ def to_s # :nodoc:
3260
+ s = @scalar.unpack("H2").join.to_s
3261
+ return ((s[0].to_i)*(10**(s[1].to_i-2))).to_s << "m"
3262
+ end
3263
+
3264
+ def inspect # :nodoc:
3265
+ return "#<#{self.class} #{self}>"
3266
+ end
3267
+
3268
+ def ==(other) # :nodoc:
3269
+ return @scalar == other.scalar
3270
+ end
3271
+
3272
+ def eql?(other) # :nodoc:
3273
+ return self == other
3274
+ end
3275
+
3276
+ def hash # :nodoc:
3277
+ return @scalar.hash
3278
+ end
3279
+
3280
+ end
3281
+
3282
+ ##
3283
+ # A Gem::Resolv::LOC::Coord
3284
+
3285
+ class Coord
3286
+
3287
+ Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
3288
+
3289
+ ##
3290
+ # Creates a new LOC::Coord from +arg+ which may be:
3291
+ #
3292
+ # LOC::Coord:: returns +arg+.
3293
+ # String:: +arg+ must match the LOC::Coord::Regex constant
3294
+
3295
+ def self.create(arg)
3296
+ case arg
3297
+ when Coord
3298
+ return arg
3299
+ when String
3300
+ coordinates = ''
3301
+ if Regex =~ arg && $1.to_f < 180
3302
+ m = $~
3303
+ hemi = (m[4][/[NE]/]) || (m[4][/[SW]/]) ? 1 : -1
3304
+ coordinates = [ ((m[1].to_i*(36e5)) + (m[2].to_i*(6e4)) +
3305
+ (m[3].to_f*(1e3))) * hemi+(2**31) ].pack("N")
3306
+ orientation = m[4][/[NS]/] ? 'lat' : 'lon'
3307
+ else
3308
+ raise ArgumentError.new("not a properly formed Coord string: " + arg)
3309
+ end
3310
+ return Coord.new(coordinates,orientation)
3311
+ else
3312
+ raise ArgumentError.new("cannot interpret as Coord: #{arg.inspect}")
3313
+ end
3314
+ end
3315
+
3316
+ def initialize(coordinates,orientation)
3317
+ unless coordinates.kind_of?(String)
3318
+ raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
3319
+ end
3320
+ unless orientation.kind_of?(String) && orientation[/^lon$|^lat$/]
3321
+ raise ArgumentError.new('Coord expects orientation to be a String argument of "lat" or "lon"')
3322
+ end
3323
+ @coordinates = coordinates
3324
+ @orientation = orientation
3325
+ end
3326
+
3327
+ ##
3328
+ # The raw coordinates
3329
+
3330
+ attr_reader :coordinates
3331
+
3332
+ ## The orientation of the hemisphere as 'lat' or 'lon'
3333
+
3334
+ attr_reader :orientation
3335
+
3336
+ def to_s # :nodoc:
3337
+ c = @coordinates.unpack("N").join.to_i
3338
+ val = (c - (2**31)).abs
3339
+ fracsecs = (val % 1e3).to_i.to_s
3340
+ val = val / 1e3
3341
+ secs = (val % 60).to_i.to_s
3342
+ val = val / 60
3343
+ mins = (val % 60).to_i.to_s
3344
+ degs = (val / 60).to_i.to_s
3345
+ posi = (c >= 2**31)
3346
+ case posi
3347
+ when true
3348
+ hemi = @orientation[/^lat$/] ? "N" : "E"
3349
+ else
3350
+ hemi = @orientation[/^lon$/] ? "W" : "S"
3351
+ end
3352
+ return degs << " " << mins << " " << secs << "." << fracsecs << " " << hemi
3353
+ end
3354
+
3355
+ def inspect # :nodoc:
3356
+ return "#<#{self.class} #{self}>"
3357
+ end
3358
+
3359
+ def ==(other) # :nodoc:
3360
+ return @coordinates == other.coordinates
3361
+ end
3362
+
3363
+ def eql?(other) # :nodoc:
3364
+ return self == other
3365
+ end
3366
+
3367
+ def hash # :nodoc:
3368
+ return @coordinates.hash
3369
+ end
3370
+
3371
+ end
3372
+
3373
+ ##
3374
+ # A Gem::Resolv::LOC::Alt
3375
+
3376
+ class Alt
3377
+
3378
+ Regex = /^([+-]*\d+\.*\d*)[m]$/
3379
+
3380
+ ##
3381
+ # Creates a new LOC::Alt from +arg+ which may be:
3382
+ #
3383
+ # LOC::Alt:: returns +arg+.
3384
+ # String:: +arg+ must match the LOC::Alt::Regex constant
3385
+
3386
+ def self.create(arg)
3387
+ case arg
3388
+ when Alt
3389
+ return arg
3390
+ when String
3391
+ altitude = ''
3392
+ if Regex =~ arg
3393
+ altitude = [($1.to_f*(1e2))+(1e7)].pack("N")
3394
+ else
3395
+ raise ArgumentError.new("not a properly formed Alt string: " + arg)
3396
+ end
3397
+ return Alt.new(altitude)
3398
+ else
3399
+ raise ArgumentError.new("cannot interpret as Alt: #{arg.inspect}")
3400
+ end
3401
+ end
3402
+
3403
+ def initialize(altitude)
3404
+ @altitude = altitude
3405
+ end
3406
+
3407
+ ##
3408
+ # The raw altitude
3409
+
3410
+ attr_reader :altitude
3411
+
3412
+ def to_s # :nodoc:
3413
+ a = @altitude.unpack("N").join.to_i
3414
+ return ((a.to_f/1e2)-1e5).to_s + "m"
3415
+ end
3416
+
3417
+ def inspect # :nodoc:
3418
+ return "#<#{self.class} #{self}>"
3419
+ end
3420
+
3421
+ def ==(other) # :nodoc:
3422
+ return @altitude == other.altitude
3423
+ end
3424
+
3425
+ def eql?(other) # :nodoc:
3426
+ return self == other
3427
+ end
3428
+
3429
+ def hash # :nodoc:
3430
+ return @altitude.hash
3431
+ end
3432
+
3433
+ end
3434
+
3435
+ end
3436
+
3437
+ ##
3438
+ # Default resolver to use for Gem::Resolv class methods.
3439
+
3440
+ DefaultResolver = self.new
3441
+
3442
+ ##
3443
+ # Replaces the resolvers in the default resolver with +new_resolvers+. This
3444
+ # allows resolvers to be changed for resolv-replace.
3445
+
3446
+ def DefaultResolver.replace_resolvers new_resolvers
3447
+ @resolvers = new_resolvers
3448
+ end
3449
+
3450
+ ##
3451
+ # Address Regexp to use for matching IP addresses.
3452
+
3453
+ AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
3454
+
3455
+ end