lanyon 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1d734e248758a22e846cf73dc15b13a323548a6
4
- data.tar.gz: b7f4ed547b531a6d746f5a0caf31928af6ad968e
3
+ metadata.gz: 3ba71c4bb36491071c4f3918250373339f2b06fe
4
+ data.tar.gz: 77bf257ad911b6e56e1420a7c2443b61b1e149df
5
5
  SHA512:
6
- metadata.gz: 36f129ec0ff9053464adcfaec6984d10eb04d6d9252538ab4f434ed0fd2de5aeaa3348d68507eb0b906b3664a44d526bd333668ae0a1757f24f526796850106b
7
- data.tar.gz: 33a2dc54b3b19c0108773903e18d525808875dcce69f98abf725b5f4fe7bc3cc52f97b0d2d61bffce8c89186495bf24cce627c392a4e6b06c97a626f6b96e960
6
+ metadata.gz: 2595d1de19d7f28071efdc3288708089ad6d316ae16406174197eb02c35ad8ff7cc1d113cc99247070179c8bb7ab1eb64571623618c295778fcf820b1c342b0e
7
+ data.tar.gz: 8f8870aba29ea1fe713f93ef87b633965288a747e210297925bd420833c368b804640603bc06f3c8f80ad7f32b3d0cee82becfd3f084b7ac1cb5d079ee530f42
@@ -41,7 +41,7 @@ module Lanyon
41
41
  private
42
42
 
43
43
  def response(filename) # :nodoc:
44
- response = Rack::Response.new(File.read(filename))
44
+ response = Rack::Response.new(File.binread(filename))
45
45
  response["Content-Type"] = media_type(filename)
46
46
  response["Last-Modified"] = modification_time(filename)
47
47
 
data/lib/lanyon/router.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require "rack/utils"
2
+
3
+
1
4
  module Lanyon
2
5
 
3
6
  # Router class for Lanyon applications.
@@ -17,17 +20,12 @@ module Lanyon
17
20
  # - +:must_redirect+ if the request must be redirected to <tt>path/</tt>.
18
21
  #
19
22
  def endpoint(path)
20
- fullpath = File.join(@root, path)
21
-
22
- if fullpath.end_with?("/")
23
- normalized = fullpath + "index.html"
24
- else
25
- normalized = fullpath
26
- end
23
+ normalized = normalize_path_info(path)
27
24
 
28
- endpoint = if FileTest.file?(normalized)
29
- normalized
30
- elsif needs_redirect_to_dir?(normalized)
25
+ fullpath = File.join(@root, normalized)
26
+ endpoint = if FileTest.file?(fullpath)
27
+ fullpath
28
+ elsif needs_redirect_to_dir?(fullpath)
31
29
  :must_redirect
32
30
  else
33
31
  :not_found
@@ -40,7 +38,7 @@ module Lanyon
40
38
  def custom_404_body
41
39
  filename = File.join(root, "404.html")
42
40
 
43
- File.exist?(filename) ? File.read(filename) : nil
41
+ File.exist?(filename) ? File.binread(filename) : nil
44
42
  end
45
43
 
46
44
  private
@@ -48,5 +46,15 @@ module Lanyon
48
46
  def needs_redirect_to_dir?(fullpath) # :nodoc:
49
47
  !fullpath.end_with?("/") && FileTest.file?(fullpath + "/index.html")
50
48
  end
49
+
50
+ def normalize_path_info(path)
51
+ if path.end_with?("/")
52
+ normalized = path + "index.html"
53
+ else
54
+ normalized = path
55
+ end
56
+
57
+ Rack::Utils.clean_path_info(normalized)
58
+ end
51
59
  end
52
60
  end
@@ -1,4 +1,4 @@
1
1
  module Lanyon
2
- VERSION = '0.2.0'
3
- DATE = '2015-11-11'
2
+ VERSION = '0.2.2'
3
+ DATE = '2015-12-06'
4
4
  end
data/lib/lanyon.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  # See Lanyon module for documentation.
4
4
 
5
5
  require "jekyll"
6
+ require "rack"
6
7
 
7
8
  require "lanyon/application"
8
9
  require "lanyon/router"
@@ -18,7 +19,8 @@ require "lanyon/version"
18
19
  #
19
20
  module Lanyon
20
21
 
21
- # Builds the Jekyll site and returns a Rack application.
22
+ # Builds the Jekyll site, prepares the middleware stack,
23
+ # and returns the Rack application.
22
24
  #
23
25
  # Options:
24
26
  #
@@ -38,7 +40,7 @@ module Lanyon
38
40
  if skip_build
39
41
  puts skip_build_warning
40
42
  else
41
- build(config)
43
+ process(config)
42
44
  end
43
45
 
44
46
  destination = config["destination"]
@@ -71,7 +73,11 @@ module Lanyon
71
73
  end
72
74
 
73
75
  # @private
74
- def self.build(config) # :nodoc:
76
+ #
77
+ # Wraps Jekyll::Site's process method that builds the site.
78
+ #
79
+ # Takes a Jekyll configuration hash as argument.
80
+ def self.process(config) # :nodoc:
75
81
  site = ::Jekyll::Site.new(config)
76
82
  puts "Generating site: #{site.source} -> #{site.dest}"
77
83
  site.process
@@ -0,0 +1,4 @@
1
+ File
2
+ with
3
+ CRLF
4
+ newlines
@@ -177,6 +177,18 @@ describe "when handling requests" do
177
177
  end
178
178
 
179
179
 
180
+ describe "when asked for paths with directory traversal" do
181
+
182
+ it "returns status 404 for unsafe directory traversal" do
183
+ filename = File.join(@destdir, "/../_site/index.html")
184
+ assert File.exist?(filename)
185
+
186
+ @response = @request.get("/../_site/index.html")
187
+ @response.status.must_equal 404
188
+ end
189
+ end
190
+
191
+
180
192
  describe "when a directory is requested" do
181
193
 
182
194
  it "redirects to 'directory/' for 'directory' with index.html" do
@@ -233,7 +245,8 @@ describe "when handling requests" do
233
245
  end
234
246
 
235
247
  it "returns correct body" do
236
- @response.body.must_match %r{<p>¡Buenos días!</p>}
248
+ response_body = @response.body.force_encoding("UTF-8")
249
+ response_body.must_match %r{<p>¡Buenos días!</p>}
237
250
  end
238
251
 
239
252
  it "returns the bytesize as Content-Length header" do
@@ -242,6 +255,23 @@ describe "when handling requests" do
242
255
  end
243
256
 
244
257
 
258
+ describe "when resource contains CRLF newlines" do
259
+
260
+ before do
261
+ @response = @request.get("/crlf.dat")
262
+ end
263
+
264
+ it "returns correct body" do
265
+ expected = "File\r\nwith\r\nCRLF\r\nnewlines\r\n"
266
+ @response.body.must_equal expected
267
+ end
268
+
269
+ it "returns the bytesize as Content-Length header" do
270
+ @response.original_headers["Content-Length"].must_equal "28"
271
+ end
272
+ end
273
+
274
+
245
275
  describe "when handling If-Modified-Since requests" do
246
276
 
247
277
  before do
data/test/test_router.rb CHANGED
@@ -79,6 +79,35 @@ describe Lanyon::Router do
79
79
  end
80
80
 
81
81
 
82
+ describe "when asked for paths with directory traversal" do
83
+
84
+ it "discards leading '..' for existing path" do
85
+ filename = File.join(@sitedir, "page.html")
86
+ @router.endpoint("/../../page.html").must_equal filename
87
+ end
88
+
89
+ it "allows safe directory traversal" do
90
+ filename = File.join(@sitedir, "index.html")
91
+ @router.endpoint("/dir1/../").must_equal filename
92
+ end
93
+
94
+ it "returns :not_found for unsafe directory traversal 1" do
95
+ filename = File.join(@sitedir, "/../_site/page.html")
96
+ assert File.exist?(filename)
97
+
98
+ @router.endpoint("/../_site/page.html").must_equal :not_found
99
+ end
100
+
101
+ it "returns :not_found for unsafe directory traversal 2" do
102
+ @router.endpoint("/%2E%2E/_site/").must_equal :not_found
103
+ end
104
+
105
+ it "returns :not_found for unsafe directory traversal 3" do
106
+ @router.endpoint("/dir1/../dir1/../../_site/").must_equal :not_found
107
+ end
108
+ end
109
+
110
+
82
111
  describe "when asked for #custom_404_body" do
83
112
 
84
113
  describe "when 404.html does not exist" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lanyon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcus Stollsteimer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-11 00:00:00.000000000 Z
11
+ date: 2015-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -97,6 +97,7 @@ files:
97
97
  - test/helper.rb
98
98
  - test/source/_posts/2015-11-05-hello-world.md
99
99
  - test/source/buenos_dias.md
100
+ - test/source/crlf.dat
100
101
  - test/source/css/test.css
101
102
  - test/source/dir-with-index/index.md
102
103
  - test/source/dir-without-index/page.md