rubygems-update 3.4.10 → 3.5.22

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