rubygems-update 2.7.5 → 2.7.6
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.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.txt +19 -0
- data/lib/rubygems.rb +1 -1
- data/lib/rubygems/commands/owner_command.rb +1 -1
- data/lib/rubygems/package.rb +33 -4
- data/lib/rubygems/package/tar_header.rb +14 -9
- data/lib/rubygems/package/tar_writer.rb +2 -0
- data/lib/rubygems/server.rb +13 -1
- data/lib/rubygems/specification.rb +11 -4
- data/test/rubygems/test_gem_commands_owner_command.rb +25 -0
- data/test/rubygems/test_gem_package.rb +73 -1
- data/test/rubygems/test_gem_package_tar_header.rb +20 -0
- data/test/rubygems/test_gem_server.rb +165 -0
- data/test/rubygems/test_gem_specification.rb +16 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fa366bda5b1ed46730b8c276ce161ef32966ec9dde14f974663508163df41da
|
4
|
+
data.tar.gz: 76d8c2583652ec7266303e5af81014b7b6c440ff207e1d4cbe483959226db55d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd712f404f5e736191c312af58dafdfe897e155b9cdec68a634547606846bb31bae7cdefc46ace35eb143db7f8281c20092a534a7ccb94760ad5701d8c0ca06f
|
7
|
+
data.tar.gz: 1d80df8990549a07c91d94c5e848141f72045a71046ef0a3be5b871e8af9f0909187b196d117b6c508ec9fd0c9238a0ed96e4f9a8c7f6a9f6b59feac8a7df25b
|
data/History.txt
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# coding: UTF-8
|
2
2
|
|
3
|
+
=== 2.7.6 / 2018-02-16
|
4
|
+
|
5
|
+
Security fixes:
|
6
|
+
|
7
|
+
* Prevent path traversal when writing to a symlinked basedir outside of the root.
|
8
|
+
Discovered by nmalkin, fixed by Jonathan Claudius and Samuel Giddins.
|
9
|
+
* Fix possible Unsafe Object Deserialization Vulnerability in gem owner.
|
10
|
+
Fixed by Jonathan Claudius.
|
11
|
+
* Strictly interpret octal fields in tar headers.
|
12
|
+
Discoved by plover, fixed by Samuel Giddins.
|
13
|
+
* Raise a security error when there are duplicate files in a package.
|
14
|
+
Discovered by plover, fixed by Samuel Giddins.
|
15
|
+
* Enforce URL validation on spec homepage attribute.
|
16
|
+
Discovered by Yasin Soliman, fixed by Jonathan Claudius.
|
17
|
+
* Mitigate XSS vulnerability in homepage attribute when displayed via `gem server`.
|
18
|
+
Discovered by Yasin Soliman, fixed by Jonathan Claudius.
|
19
|
+
* Prevent Path Traversal issue during gem installation.
|
20
|
+
Discovered by nmalkin.
|
21
|
+
|
3
22
|
=== 2.7.4
|
4
23
|
|
5
24
|
Bug fixes:
|
data/lib/rubygems.rb
CHANGED
data/lib/rubygems/package.rb
CHANGED
@@ -378,7 +378,7 @@ EOM
|
|
378
378
|
File.dirname destination
|
379
379
|
end
|
380
380
|
|
381
|
-
|
381
|
+
mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
|
382
382
|
|
383
383
|
File.open destination, 'wb' do |out|
|
384
384
|
out.write entry.read
|
@@ -416,20 +416,35 @@ EOM
|
|
416
416
|
raise Gem::Package::PathError.new(filename, destination_dir) if
|
417
417
|
filename.start_with? '/'
|
418
418
|
|
419
|
-
destination_dir =
|
420
|
-
File.respond_to? :realpath
|
419
|
+
destination_dir = realpath destination_dir
|
421
420
|
destination_dir = File.expand_path destination_dir
|
422
421
|
|
423
422
|
destination = File.join destination_dir, filename
|
424
423
|
destination = File.expand_path destination
|
425
424
|
|
426
425
|
raise Gem::Package::PathError.new(destination, destination_dir) unless
|
427
|
-
destination.start_with? destination_dir
|
426
|
+
destination.start_with? destination_dir + '/'
|
428
427
|
|
429
428
|
destination.untaint
|
430
429
|
destination
|
431
430
|
end
|
432
431
|
|
432
|
+
def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name
|
433
|
+
destination_dir = realpath File.expand_path(destination_dir)
|
434
|
+
parts = mkdir.split(File::SEPARATOR)
|
435
|
+
parts.reduce do |path, basename|
|
436
|
+
path = realpath path unless path == ""
|
437
|
+
path = File.expand_path(path + File::SEPARATOR + basename)
|
438
|
+
lstat = File.lstat path rescue nil
|
439
|
+
if !lstat || !lstat.directory?
|
440
|
+
unless path.start_with? destination_dir and (FileUtils.mkdir path, mkdir_options rescue false)
|
441
|
+
raise Gem::Package::PathError.new(file_name, destination_dir)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
path
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
433
448
|
##
|
434
449
|
# Loads a Gem::Specification from the TarEntry +entry+
|
435
450
|
|
@@ -603,6 +618,10 @@ EOM
|
|
603
618
|
raise Gem::Package::FormatError.new \
|
604
619
|
'package content (data.tar.gz) is missing', @gem
|
605
620
|
end
|
621
|
+
|
622
|
+
if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any?
|
623
|
+
raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})"
|
624
|
+
end
|
606
625
|
end
|
607
626
|
|
608
627
|
##
|
@@ -616,6 +635,16 @@ EOM
|
|
616
635
|
raise Gem::Package::FormatError.new(e.message, entry.full_name)
|
617
636
|
end
|
618
637
|
|
638
|
+
if File.respond_to? :realpath
|
639
|
+
def realpath file
|
640
|
+
File.realpath file
|
641
|
+
end
|
642
|
+
else
|
643
|
+
def realpath file
|
644
|
+
file
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
619
648
|
end
|
620
649
|
|
621
650
|
require 'rubygems/package/digest_io'
|
@@ -104,25 +104,30 @@ class Gem::Package::TarHeader
|
|
104
104
|
fields = header.unpack UNPACK_FORMAT
|
105
105
|
|
106
106
|
new :name => fields.shift,
|
107
|
-
:mode => fields.shift
|
108
|
-
:uid => fields.shift
|
109
|
-
:gid => fields.shift
|
110
|
-
:size => fields.shift
|
111
|
-
:mtime => fields.shift
|
112
|
-
:checksum => fields.shift
|
107
|
+
:mode => strict_oct(fields.shift),
|
108
|
+
:uid => strict_oct(fields.shift),
|
109
|
+
:gid => strict_oct(fields.shift),
|
110
|
+
:size => strict_oct(fields.shift),
|
111
|
+
:mtime => strict_oct(fields.shift),
|
112
|
+
:checksum => strict_oct(fields.shift),
|
113
113
|
:typeflag => fields.shift,
|
114
114
|
:linkname => fields.shift,
|
115
115
|
:magic => fields.shift,
|
116
|
-
:version => fields.shift
|
116
|
+
:version => strict_oct(fields.shift),
|
117
117
|
:uname => fields.shift,
|
118
118
|
:gname => fields.shift,
|
119
|
-
:devmajor => fields.shift
|
120
|
-
:devminor => fields.shift
|
119
|
+
:devmajor => strict_oct(fields.shift),
|
120
|
+
:devminor => strict_oct(fields.shift),
|
121
121
|
:prefix => fields.shift,
|
122
122
|
|
123
123
|
:empty => empty
|
124
124
|
end
|
125
125
|
|
126
|
+
def self.strict_oct(str)
|
127
|
+
return str.oct if str =~ /\A[0-7]*\z/
|
128
|
+
raise ArgumentError, "#{str.inspect} is not an octal string"
|
129
|
+
end
|
130
|
+
|
126
131
|
##
|
127
132
|
# Creates a new TarHeader using +vals+
|
128
133
|
|
@@ -196,6 +196,8 @@ class Gem::Package::TarWriter
|
|
196
196
|
digest_name == signer.digest_name
|
197
197
|
end
|
198
198
|
|
199
|
+
raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest
|
200
|
+
|
199
201
|
if signer.key then
|
200
202
|
signature = signer.sign signature_digest.digest
|
201
203
|
|
data/lib/rubygems/server.rb
CHANGED
@@ -623,6 +623,18 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
623
623
|
executables = nil if executables.empty?
|
624
624
|
executables.last["is_last"] = true if executables
|
625
625
|
|
626
|
+
# Pre-process spec homepage for safety reasons
|
627
|
+
begin
|
628
|
+
homepage_uri = URI.parse(spec.homepage)
|
629
|
+
if [URI::HTTP, URI::HTTPS].member? homepage_uri.class
|
630
|
+
homepage_uri = spec.homepage
|
631
|
+
else
|
632
|
+
homepage_uri = "."
|
633
|
+
end
|
634
|
+
rescue URI::InvalidURIError
|
635
|
+
homepage_uri = "."
|
636
|
+
end
|
637
|
+
|
626
638
|
specs << {
|
627
639
|
"authors" => spec.authors.sort.join(", "),
|
628
640
|
"date" => spec.date.to_s,
|
@@ -632,7 +644,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
632
644
|
"only_one_executable" => (executables && executables.size == 1),
|
633
645
|
"full_name" => spec.full_name,
|
634
646
|
"has_deps" => !deps.empty?,
|
635
|
-
"homepage" =>
|
647
|
+
"homepage" => homepage_uri,
|
636
648
|
"name" => spec.name,
|
637
649
|
"rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?,
|
638
650
|
"ri_installed" => Gem::RDoc.new(spec).ri_installed?,
|
@@ -15,6 +15,7 @@ require 'rubygems/basic_specification'
|
|
15
15
|
require 'rubygems/stub_specification'
|
16
16
|
require 'rubygems/util/list'
|
17
17
|
require 'stringio'
|
18
|
+
require 'uri'
|
18
19
|
|
19
20
|
##
|
20
21
|
# The Specification class contains the information for a Gem. Typically
|
@@ -2822,10 +2823,16 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
2822
2823
|
raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
|
2823
2824
|
end
|
2824
2825
|
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2826
|
+
# Make sure a homepage is valid HTTP/HTTPS URI
|
2827
|
+
if homepage and not homepage.empty?
|
2828
|
+
begin
|
2829
|
+
homepage_uri = URI.parse(homepage)
|
2830
|
+
unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class
|
2831
|
+
raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
|
2832
|
+
end
|
2833
|
+
rescue URI::InvalidURIError
|
2834
|
+
raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
|
2835
|
+
end
|
2829
2836
|
end
|
2830
2837
|
|
2831
2838
|
# Warnings
|
@@ -43,6 +43,31 @@ EOF
|
|
43
43
|
assert_match %r{- 4}, @ui.output
|
44
44
|
end
|
45
45
|
|
46
|
+
def test_show_owners_dont_load_objects
|
47
|
+
skip "testing a psych-only API" unless defined?(::Psych::DisallowedClass)
|
48
|
+
|
49
|
+
response = <<EOF
|
50
|
+
---
|
51
|
+
- email: !ruby/object:Object {}
|
52
|
+
id: 1
|
53
|
+
handle: user1
|
54
|
+
- email: user2@example.com
|
55
|
+
- id: 3
|
56
|
+
handle: user3
|
57
|
+
- id: 4
|
58
|
+
EOF
|
59
|
+
|
60
|
+
@fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
|
61
|
+
|
62
|
+
assert_raises Psych::DisallowedClass do
|
63
|
+
use_ui @ui do
|
64
|
+
@cmd.show_owners("freewill")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
46
71
|
def test_show_owners_setting_up_host_through_env_var
|
47
72
|
response = "- email: user1@example.com\n"
|
48
73
|
host = "http://rubygems.example"
|
@@ -455,6 +455,31 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
455
455
|
File.read(extracted)
|
456
456
|
end
|
457
457
|
|
458
|
+
def test_extract_symlink_parent
|
459
|
+
skip 'symlink not supported' if Gem.win_platform?
|
460
|
+
|
461
|
+
package = Gem::Package.new @gem
|
462
|
+
|
463
|
+
tgz_io = util_tar_gz do |tar|
|
464
|
+
tar.mkdir 'lib', 0755
|
465
|
+
tar.add_symlink 'lib/link', '../..', 0644
|
466
|
+
tar.add_file 'lib/link/outside.txt', 0644 do |io| io.write 'hi' end
|
467
|
+
end
|
468
|
+
|
469
|
+
# Extract into a subdirectory of @destination; if this test fails it writes
|
470
|
+
# a file outside destination_subdir, but we want the file to remain inside
|
471
|
+
# @destination so it will be cleaned up.
|
472
|
+
destination_subdir = File.join @destination, 'subdir'
|
473
|
+
FileUtils.mkdir_p destination_subdir
|
474
|
+
|
475
|
+
e = assert_raises Gem::Package::PathError do
|
476
|
+
package.extract_tar_gz tgz_io, destination_subdir
|
477
|
+
end
|
478
|
+
|
479
|
+
assert_equal("installing into parent path lib/link/outside.txt of " +
|
480
|
+
"#{destination_subdir} is not allowed", e.message)
|
481
|
+
end
|
482
|
+
|
458
483
|
def test_extract_tar_gz_directory
|
459
484
|
package = Gem::Package.new @gem
|
460
485
|
|
@@ -566,6 +591,21 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
566
591
|
"#{@destination} is not allowed", e.message)
|
567
592
|
end
|
568
593
|
|
594
|
+
def test_install_location_suffix
|
595
|
+
package = Gem::Package.new @gem
|
596
|
+
|
597
|
+
filename = "../#{File.basename(@destination)}suffix.rb"
|
598
|
+
|
599
|
+
e = assert_raises Gem::Package::PathError do
|
600
|
+
package.install_location filename, @destination
|
601
|
+
end
|
602
|
+
|
603
|
+
parent = File.expand_path File.join @destination, filename
|
604
|
+
|
605
|
+
assert_equal("installing into parent path #{parent} of " +
|
606
|
+
"#{@destination} is not allowed", e.message)
|
607
|
+
end
|
608
|
+
|
569
609
|
def test_load_spec
|
570
610
|
entry = StringIO.new Gem.gzip @spec.to_yaml
|
571
611
|
def entry.full_name() 'metadata.gz' end
|
@@ -723,6 +763,32 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
723
763
|
assert_match %r%nonexistent.gem$%, e.message
|
724
764
|
end
|
725
765
|
|
766
|
+
def test_verify_duplicate_file
|
767
|
+
FileUtils.mkdir_p 'lib'
|
768
|
+
FileUtils.touch 'lib/code.rb'
|
769
|
+
|
770
|
+
build = Gem::Package.new @gem
|
771
|
+
build.spec = @spec
|
772
|
+
build.setup_signer
|
773
|
+
open @gem, 'wb' do |gem_io|
|
774
|
+
Gem::Package::TarWriter.new gem_io do |gem|
|
775
|
+
build.add_metadata gem
|
776
|
+
build.add_contents gem
|
777
|
+
|
778
|
+
gem.add_file_simple 'a.sig', 0444, 0
|
779
|
+
gem.add_file_simple 'a.sig', 0444, 0
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
package = Gem::Package.new @gem
|
784
|
+
|
785
|
+
e = assert_raises Gem::Security::Exception do
|
786
|
+
package.verify
|
787
|
+
end
|
788
|
+
|
789
|
+
assert_equal 'duplicate files in the package: ("a.sig")', e.message
|
790
|
+
end
|
791
|
+
|
726
792
|
def test_verify_security_policy
|
727
793
|
skip 'openssl is missing' unless defined?(OpenSSL::SSL)
|
728
794
|
|
@@ -780,7 +846,13 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
780
846
|
|
781
847
|
# write bogus data.tar.gz to foil signature
|
782
848
|
bogus_data = Gem.gzip 'hello'
|
783
|
-
|
849
|
+
fake_signer = Class.new do
|
850
|
+
def digest_name; 'SHA512'; end
|
851
|
+
def digest_algorithm; Digest(:SHA512); end
|
852
|
+
def key; 'key'; end
|
853
|
+
def sign(*); 'fake_sig'; end
|
854
|
+
end
|
855
|
+
gem.add_file_signed 'data2.tar.gz', 0444, fake_signer.new do |io|
|
784
856
|
io.write bogus_data
|
785
857
|
end
|
786
858
|
|
@@ -143,5 +143,25 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
|
|
143
143
|
assert_equal '012467', @tar_header.checksum
|
144
144
|
end
|
145
145
|
|
146
|
+
def test_from_bad_octal
|
147
|
+
test_cases = [
|
148
|
+
"00000006,44\000", # bogus character
|
149
|
+
"00000006789\000", # non-octal digit
|
150
|
+
"+0000001234\000", # positive sign
|
151
|
+
"-0000001000\000", # negative sign
|
152
|
+
"0x000123abc\000", # radix prefix
|
153
|
+
]
|
154
|
+
|
155
|
+
test_cases.each do |val|
|
156
|
+
header_s = @tar_header.to_s
|
157
|
+
# overwrite the size field
|
158
|
+
header_s[124, 12] = val
|
159
|
+
io = TempIO.new header_s
|
160
|
+
assert_raises ArgumentError do
|
161
|
+
new_header = Gem::Package::TarHeader.from io
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
146
166
|
end
|
147
167
|
|
@@ -353,6 +353,171 @@ class TestGemServer < Gem::TestCase
|
|
353
353
|
assert_match 'z 9', @res.body
|
354
354
|
end
|
355
355
|
|
356
|
+
|
357
|
+
def test_xss_homepage_fix_289313
|
358
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
359
|
+
dir = "#{@gemhome}2"
|
360
|
+
|
361
|
+
spec = util_spec 'xsshomepagegem', 1
|
362
|
+
spec.homepage = "javascript:confirm(document.domain)"
|
363
|
+
|
364
|
+
specs_dir = File.join dir, 'specifications'
|
365
|
+
FileUtils.mkdir_p specs_dir
|
366
|
+
|
367
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
368
|
+
io.write spec.to_ruby
|
369
|
+
end
|
370
|
+
|
371
|
+
server = Gem::Server.new dir, process_based_port, false
|
372
|
+
|
373
|
+
@req.parse data
|
374
|
+
|
375
|
+
server.root @req, @res
|
376
|
+
|
377
|
+
assert_equal 200, @res.status
|
378
|
+
assert_match 'xsshomepagegem 1', @res.body
|
379
|
+
|
380
|
+
# This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
|
381
|
+
# valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
|
382
|
+
# but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
|
383
|
+
# validated in future versions of Gem::Specification.
|
384
|
+
#
|
385
|
+
# There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
|
386
|
+
#
|
387
|
+
# Variant #1 - rdoc not installed
|
388
|
+
#
|
389
|
+
# <b>xsshomepagegem 1</b>
|
390
|
+
#
|
391
|
+
#
|
392
|
+
# <span title="rdoc not installed">[rdoc]</span>
|
393
|
+
#
|
394
|
+
#
|
395
|
+
#
|
396
|
+
# <a href="." title=".">[www]</a>
|
397
|
+
#
|
398
|
+
# Variant #2 - rdoc installed
|
399
|
+
#
|
400
|
+
# <b>xsshomepagegem 1</b>
|
401
|
+
#
|
402
|
+
#
|
403
|
+
# <a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>
|
404
|
+
#
|
405
|
+
#
|
406
|
+
#
|
407
|
+
# <a href="." title=".">[www]</a>
|
408
|
+
regex_match = /xsshomepagegem 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="\." title="\.">\[www\]<\/a>/
|
409
|
+
assert_match regex_match, @res.body
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_invalid_homepage
|
413
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
414
|
+
dir = "#{@gemhome}2"
|
415
|
+
|
416
|
+
spec = util_spec 'invalidhomepagegem', 1
|
417
|
+
spec.homepage = "notavalidhomepageurl"
|
418
|
+
|
419
|
+
specs_dir = File.join dir, 'specifications'
|
420
|
+
FileUtils.mkdir_p specs_dir
|
421
|
+
|
422
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
423
|
+
io.write spec.to_ruby
|
424
|
+
end
|
425
|
+
|
426
|
+
server = Gem::Server.new dir, process_based_port, false
|
427
|
+
|
428
|
+
@req.parse data
|
429
|
+
|
430
|
+
server.root @req, @res
|
431
|
+
|
432
|
+
assert_equal 200, @res.status
|
433
|
+
assert_match 'invalidhomepagegem 1', @res.body
|
434
|
+
|
435
|
+
# This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
|
436
|
+
# valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
|
437
|
+
# but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
|
438
|
+
# validated in future versions of Gem::Specification.
|
439
|
+
#
|
440
|
+
# There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
|
441
|
+
#
|
442
|
+
# Variant #1 - rdoc not installed
|
443
|
+
#
|
444
|
+
# <b>invalidhomepagegem 1</b>
|
445
|
+
#
|
446
|
+
#
|
447
|
+
# <span title="rdoc not installed">[rdoc]</span>
|
448
|
+
#
|
449
|
+
#
|
450
|
+
#
|
451
|
+
# <a href="." title=".">[www]</a>
|
452
|
+
#
|
453
|
+
# Variant #2 - rdoc installed
|
454
|
+
#
|
455
|
+
# <b>invalidhomepagegem 1</b>
|
456
|
+
#
|
457
|
+
#
|
458
|
+
# <a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>
|
459
|
+
#
|
460
|
+
#
|
461
|
+
#
|
462
|
+
# <a href="." title=".">[www]</a>
|
463
|
+
regex_match = /invalidhomepagegem 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="\." title="\.">\[www\]<\/a>/
|
464
|
+
assert_match regex_match, @res.body
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_valid_homepage_http
|
468
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
469
|
+
dir = "#{@gemhome}2"
|
470
|
+
|
471
|
+
spec = util_spec 'validhomepagegemhttp', 1
|
472
|
+
spec.homepage = "http://rubygems.org"
|
473
|
+
|
474
|
+
specs_dir = File.join dir, 'specifications'
|
475
|
+
FileUtils.mkdir_p specs_dir
|
476
|
+
|
477
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
478
|
+
io.write spec.to_ruby
|
479
|
+
end
|
480
|
+
|
481
|
+
server = Gem::Server.new dir, process_based_port, false
|
482
|
+
|
483
|
+
@req.parse data
|
484
|
+
|
485
|
+
server.root @req, @res
|
486
|
+
|
487
|
+
assert_equal 200, @res.status
|
488
|
+
assert_match 'validhomepagegemhttp 1', @res.body
|
489
|
+
|
490
|
+
regex_match = /validhomepagegemhttp 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttp-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="http:\/\/rubygems\.org" title="http:\/\/rubygems\.org">\[www\]<\/a>/
|
491
|
+
assert_match regex_match, @res.body
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_valid_homepage_https
|
495
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
496
|
+
dir = "#{@gemhome}2"
|
497
|
+
|
498
|
+
spec = util_spec 'validhomepagegemhttps', 1
|
499
|
+
spec.homepage = "https://rubygems.org"
|
500
|
+
|
501
|
+
specs_dir = File.join dir, 'specifications'
|
502
|
+
FileUtils.mkdir_p specs_dir
|
503
|
+
|
504
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
505
|
+
io.write spec.to_ruby
|
506
|
+
end
|
507
|
+
|
508
|
+
server = Gem::Server.new dir, process_based_port, false
|
509
|
+
|
510
|
+
@req.parse data
|
511
|
+
|
512
|
+
server.root @req, @res
|
513
|
+
|
514
|
+
assert_equal 200, @res.status
|
515
|
+
assert_match 'validhomepagegemhttps 1', @res.body
|
516
|
+
|
517
|
+
regex_match = /validhomepagegemhttps 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttps-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="https:\/\/rubygems\.org" title="https:\/\/rubygems\.org">\[www\]<\/a>/
|
518
|
+
assert_match regex_match, @res.body
|
519
|
+
end
|
520
|
+
|
356
521
|
def test_specs
|
357
522
|
data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
358
523
|
@req.parse data
|
@@ -2886,7 +2886,22 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
|
|
2886
2886
|
@a1.validate
|
2887
2887
|
end
|
2888
2888
|
|
2889
|
-
assert_equal '"over at my cool site" is not a URI', e.message
|
2889
|
+
assert_equal '"over at my cool site" is not a valid HTTP URI', e.message
|
2890
|
+
|
2891
|
+
@a1.homepage = 'ftp://rubygems.org'
|
2892
|
+
|
2893
|
+
e = assert_raises Gem::InvalidSpecificationException do
|
2894
|
+
@a1.validate
|
2895
|
+
end
|
2896
|
+
|
2897
|
+
assert_equal '"ftp://rubygems.org" is not a valid HTTP URI', e.message
|
2898
|
+
|
2899
|
+
@a1.homepage = 'http://rubygems.org'
|
2900
|
+
assert_equal true, @a1.validate
|
2901
|
+
|
2902
|
+
@a1.homepage = 'https://rubygems.org'
|
2903
|
+
assert_equal true, @a1.validate
|
2904
|
+
|
2890
2905
|
end
|
2891
2906
|
end
|
2892
2907
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubygems-update
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Weirich
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-02-
|
13
|
+
date: 2018-02-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: builder
|
@@ -804,7 +804,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
804
804
|
version: '0'
|
805
805
|
requirements: []
|
806
806
|
rubyforge_project:
|
807
|
-
rubygems_version: 2.7.
|
807
|
+
rubygems_version: 2.7.4
|
808
808
|
signing_key:
|
809
809
|
specification_version: 4
|
810
810
|
summary: ''
|