rubygems-update 2.6.1 → 3.5.0

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