gopher 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b61e25f16a3e9ce60e827a065bfdd71345856b6f0eda25852b90d4d2d9186163
4
+ data.tar.gz: f297cf6b2f0b6198ef0e8bc0f3b19f78c92bcd3ca477b0b61013b4d699c49cee
5
+ SHA512:
6
+ metadata.gz: 2bd00e1620cd8ad3cc5ef3a6a885bad5ac6b9ca8809ee308031dbc5bfad68f99d48c688712254d4e4e191913e3791cb6cd958bb093ca3d62a7c66853e30a0369
7
+ data.tar.gz: a6a9ad35dd09825214acf723eb572f8e3539ff3fe94335c9497a9069a611f3d501886e3e910b6a41fc1eb56c5127acc6c56a920bcd468f41f07159298c35ae6f
data/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright 2009 umeldt
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README ADDED
@@ -0,0 +1,34 @@
1
+ # gopher
2
+
3
+ a gopher server and a simple DSL for setting up servers
4
+
5
+ ## installation
6
+
7
+ ```bash
8
+ gem install foobar
9
+ ```
10
+
11
+ ## usage
12
+
13
+ set up a server using ruby
14
+ ```ruby
15
+ gopher = Gopher.application do
16
+ host '0.0.0.0'
17
+ port 70
18
+
19
+ text '/time' do
20
+ line Time.now.to_s
21
+ end
22
+
23
+ mount '/', '/srv/gopher'
24
+ end
25
+ ```
26
+
27
+ serve the current directory over gopher
28
+ ```bash
29
+ gopher -p 70 -a 127.0.0.1
30
+ ```
31
+
32
+ ## license
33
+ [ISC](https://choosealicense.com/licenses/isc/)
34
+
data/bin/gopher CHANGED
@@ -3,12 +3,28 @@
3
3
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
 
5
5
  require 'gopher'
6
+ require 'optparse'
6
7
 
7
- Gopher.application do
8
- host '0.0.0.0'
9
- port 70
8
+ options = {}
9
+ OptionParser.new do |opts|
10
+ opts.banner = "usage: gopher [options]"
11
+
12
+ opts.on("-a=ADDRESS", "bind to address") { |v| options[:address] = v }
13
+ opts.on("-p=PORT", "port") { |v| options[:port] = v }
14
+ end.parse!
15
+
16
+ gopher = Gopher.application do
17
+ host options[:address] || '0.0.0.0'
18
+ port options[:port] || 70
10
19
 
11
20
  mount '/', '.'
12
21
  end
13
22
 
14
- Gopher.run
23
+ begin
24
+ STDERR.puts "Launching gopher server on #{gopher.host}:#{gopher.port}"
25
+ Gopher.run
26
+ rescue SystemExit, Interrupt
27
+ STDERR.puts "Stopping server"
28
+ Gopher.stop
29
+ end
30
+
@@ -0,0 +1,14 @@
1
+ class Module
2
+ def dsl_accessor(*accessors)
3
+ accessors.each do |accessor|
4
+ class_eval %{
5
+ attr_writer :#{accessor}
6
+
7
+ def #{accessor}(value=nil)
8
+ send "#{accessor}=", value if value
9
+ @#{accessor}
10
+ end
11
+ }
12
+ end
13
+ end
14
+ end
@@ -1,14 +1,12 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'ext/object'
4
- require 'ext/module'
1
+ require 'yaml'
5
2
 
6
3
  require 'textwrap'
7
- require 'yaml'
8
4
  require 'eventmachine'
9
5
 
6
+ require_relative 'ext/module'
7
+
10
8
  module Gopher
11
- VERSION = '0.5.1'
9
+ VERSION = '0.6.0'
12
10
 
13
11
  class Application
14
12
  dsl_accessor :host, :port
@@ -26,15 +24,18 @@ module Gopher
26
24
  end
27
25
 
28
26
  def mount(selector, path)
29
- add_handler "#{selector}/?(.*)", DirectoryHandler.new(path, selector).with(self)
27
+ add_handler "#{selector}/?(.*)",
28
+ DirectoryHandler.new(path, selector).with(self)
30
29
  end
31
30
 
32
31
  def map(selector, &block)
33
- add_handler selector.gsub(/:(.+)/, '(.+)'), MapHandler.new(&block).with(self)
32
+ add_handler selector.gsub(/:(.+)/, '(.+)'),
33
+ MapHandler.new(&block).with(self)
34
34
  end
35
35
 
36
36
  def text(selector, &block)
37
- add_handler selector.gsub(/:(.+)/, '(.+)'), TextHandler.new(&block).with(self)
37
+ add_handler selector.gsub(/:(.+)/, '(.+)'),
38
+ TextHandler.new(&block).with(self)
38
39
  end
39
40
 
40
41
  def helpers(&block)
@@ -42,9 +43,10 @@ module Gopher
42
43
  TextContext.class_eval(&block)
43
44
  end
44
45
 
45
- def application(selector, handler)
46
+ def app(selector, handler)
46
47
  add_handler selector, handler
47
48
  end
49
+ alias_method :application, :app
48
50
 
49
51
  def request(selector)
50
52
  handler, *args = lookup(selector)
@@ -71,15 +73,15 @@ module Gopher
71
73
  end
72
74
 
73
75
  class Handler
74
- attr_accessor :application
76
+ attr_accessor :app
75
77
 
76
- def with(application)
77
- @application = application
78
+ def with(app)
79
+ @app = app
78
80
  self
79
81
  end
80
82
 
81
- def host; application.respond_to?(:host) ? application.host : '0.0.0.0' end
82
- def port; application.respond_to?(:port) ? application.port : 70 end
83
+ def host; app.respond_to?(:host) ? app.host : '0.0.0.0' end
84
+ def port; app.respond_to?(:port) ? app.port : 70 end
83
85
 
84
86
  def call(*args); end
85
87
  end
@@ -125,9 +127,9 @@ module Gopher
125
127
  def call(*args)
126
128
  path = File.join(base, *args)
127
129
  if File.directory? path
128
- return DirectoryHandler.new(path, File.join(selector, args)).with(application).to_map
130
+ DirectoryHandler.new(path, File.join(selector, args)).with(app).to_map
129
131
  elsif File.file? path
130
- return File.open(path)
132
+ File.open(path)
131
133
  else
132
134
  raise NotFound
133
135
  end
@@ -195,7 +197,7 @@ module Gopher
195
197
  new(host, port).instance_exec(*args, &block)
196
198
  end
197
199
 
198
- def line(type, txt, selector, host = host, port = port)
200
+ def line(type, txt, selector, host = self.host, port = self.port)
199
201
  result << ["#{type}#{txt}", selector, host, port].join("\t")
200
202
  result << "\r\n"
201
203
  end
@@ -245,12 +247,12 @@ module Gopher
245
247
  end
246
248
 
247
249
  class Connection < EM::Connection
248
- attr_accessor :application
250
+ attr_accessor :app
249
251
 
250
252
  def receive_data(data)
251
253
  begin
252
254
  raise InvalidRequest if data.length > 255
253
- response = application.request(data)
255
+ response = app.request(data)
254
256
  case response
255
257
  when String then send_data(response)
256
258
  when StringIO then send_data(response.read)
@@ -270,29 +272,38 @@ module Gopher
270
272
  end
271
273
  end
272
274
 
273
- def self.application(&block)
274
- @application = Application.new(&block)
275
- end
275
+ class <<self
276
+ def app(&block)
277
+ @app = Application.new(&block)
278
+ end
279
+ alias_method :application, :app
276
280
 
277
- def self.reload(*files)
278
- @last_reload = Time.now
279
- @reloadables = files
280
- end
281
+ def reload(*files)
282
+ @last_reload = Time.now
283
+ @reloadables = files
284
+ end
281
285
 
282
- def self.reloadables
283
- @reloadables ||= []
284
- end
286
+ def reloadables
287
+ @reloadables ||= []
288
+ end
285
289
 
286
- def self.run
287
- return if EM.reactor_running?
288
- EM.run do
289
- EM.start_server(@application.host, @application.port, Gopher::Connection) do |c|
290
- c.application = @application
291
- reloadables.each do |f|
292
- load f if File.mtime(f) > @last_reload
293
- end
294
- @last_reload = Time.now
295
- end
290
+ def run
291
+ return if EM.reactor_running?
292
+ EM.run do
293
+ EM.start_server(@app.host, @app.port, Gopher::Connection) do |c|
294
+ c.app = @app
295
+ reloadables.each do |f|
296
+ load f if File.mtime(f) > @last_reload
297
+ end
298
+ @last_reload = Time.now
299
+ end
300
+ end
301
+ end
302
+
303
+ def stop
304
+ return unless EM.reactor_running?
305
+ EM.stop_server
296
306
  end
297
307
  end
298
308
  end
309
+
@@ -0,0 +1,297 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'ext/module'
4
+
5
+ require 'yaml'
6
+ require 'textwrap'
7
+ require 'eventmachine'
8
+
9
+ module Gopher
10
+ VERSION = '0.5.2'
11
+
12
+ class Application
13
+ dsl_accessor :host, :port
14
+ attr_accessor :selectors, :root
15
+
16
+ def initialize(&block)
17
+ reset!
18
+ self.instance_eval(&block)
19
+ end
20
+
21
+ def reload(*f); Gopher.reload(*f) end
22
+
23
+ def use(mod)
24
+ extend(mod)
25
+ end
26
+
27
+ def mount(selector, path)
28
+ add_handler "#{selector}/?(.*)", DirectoryHandler.new(path, selector).with(self)
29
+ end
30
+
31
+ def map(selector, &block)
32
+ add_handler selector.gsub(/:(.+)/, '(.+)'), MapHandler.new(&block).with(self)
33
+ end
34
+
35
+ def text(selector, &block)
36
+ add_handler selector.gsub(/:(.+)/, '(.+)'), TextHandler.new(&block).with(self)
37
+ end
38
+
39
+ def helpers(&block)
40
+ MapContext.class_eval(&block)
41
+ TextContext.class_eval(&block)
42
+ end
43
+
44
+ def application(selector, handler)
45
+ add_handler selector, handler
46
+ end
47
+
48
+ def request(selector)
49
+ handler, *args = lookup(selector)
50
+ handler.call(*args)
51
+ end
52
+
53
+ def lookup(selector)
54
+ selectors.find do |k, v|
55
+ return v, *$~[1..-1] if k =~ Gopher.sanitize_selector(selector)
56
+ end
57
+ raise NotFound
58
+ end
59
+
60
+ def add_handler(selector, handler)
61
+ selector = Gopher.sanitize_selector(selector)
62
+ selector.sub!(/^\/*/, '')
63
+ selectors[/^\/?#{selector}$/] = handler
64
+ end
65
+
66
+ private
67
+ def reset!
68
+ @selectors = {}
69
+ end
70
+ end
71
+
72
+ class Handler
73
+ attr_accessor :application
74
+
75
+ def with(application)
76
+ @application = application
77
+ self
78
+ end
79
+
80
+ def host; application.respond_to?(:host) ? application.host : '0.0.0.0' end
81
+ def port; application.respond_to?(:port) ? application.port : 70 end
82
+
83
+ def call(*args); end
84
+ end
85
+
86
+ class MapHandler < Handler
87
+ attr_accessor :block, :result
88
+
89
+ def initialize(&block)
90
+ @block = block
91
+ end
92
+
93
+ def call(*args)
94
+ context = MapContext.new(host, port)
95
+ context.instance_exec(*args, &block)
96
+ context.result
97
+ end
98
+ end
99
+
100
+ class TextHandler < Handler
101
+ attr_accessor :block, :result
102
+
103
+ def initialize(&block)
104
+ @block = block
105
+ end
106
+
107
+ def call(*args)
108
+ context = TextContext.new
109
+ context.instance_exec(*args, &block)
110
+ context.result
111
+ end
112
+ end
113
+
114
+ class DirectoryHandler < Handler
115
+ attr_accessor :base, :selector, :index
116
+
117
+ def initialize(path, selector = '')
118
+ raise DirectoryNotFound unless File.directory? path
119
+ @selector = selector
120
+ @base = File.expand_path(path)
121
+ @index = YAML.load_file(index_file) if File.exist?(index_file)
122
+ end
123
+
124
+ def call(*args)
125
+ path = File.join(base, *args)
126
+ if File.directory? path
127
+ return DirectoryHandler.new(path, File.join(selector, args)).with(application).to_map
128
+ elsif File.file? path
129
+ return File.open(path)
130
+ else
131
+ raise NotFound
132
+ end
133
+ end
134
+
135
+ def to_map
136
+ MapContext.with_block(host, port, self) do |handler|
137
+ if handler.index
138
+ paragraph handler.index['description']
139
+ handler.index['entries'].each do |txt, path|
140
+ link txt, File.join(handler.selector, path)
141
+ end
142
+ else
143
+ Dir["#{handler.base}/*"].each do |path|
144
+ basename = File.basename(path)
145
+ if File.directory? path
146
+ map basename, File.join(handler.selector, basename)
147
+ else
148
+ link basename, File.join(handler.selector, basename)
149
+ end
150
+ end
151
+ end
152
+ text Time.now
153
+ end
154
+ end
155
+
156
+ private
157
+ def index_file
158
+ File.join(base, '.gopher')
159
+ end
160
+ end
161
+
162
+ class TextContext
163
+ attr_accessor :result
164
+
165
+ def line(text)
166
+ result << text
167
+ result << "\r\n"
168
+ end
169
+
170
+ def text(text)
171
+ line text
172
+ end
173
+
174
+ def paragraph(txt, width=70)
175
+ txt.each_line do |line|
176
+ Textwrap.wrap(line, width).each { |chunk| text chunk }
177
+ end
178
+ end
179
+
180
+ def initialize
181
+ @result = ""
182
+ end
183
+ end
184
+
185
+ class MapContext
186
+ attr_accessor :host, :port, :result
187
+
188
+ def initialize(host, port)
189
+ @host, @port = host, port
190
+ @result = ""
191
+ end
192
+
193
+ def self.with_block(host, port, *args, &block)
194
+ new(host, port).instance_exec(*args, &block)
195
+ end
196
+
197
+ def line(type, txt, selector, host = self.host, port = self.port)
198
+ result << ["#{type}#{txt}", selector, host, port].join("\t")
199
+ result << "\r\n"
200
+ end
201
+
202
+ def link(text, selector, *args)
203
+ type = Gopher.determine_type(selector)
204
+ line type, text, scrub(selector), *args
205
+ end
206
+
207
+ def map(text, selector, *args)
208
+ line '1', text, scrub(selector), *args
209
+ end
210
+
211
+ def text(text)
212
+ line 'i', text, 'false', '(NULL)', 0
213
+ end
214
+
215
+ def paragraph(txt, width=70)
216
+ txt.each_line do |line|
217
+ Textwrap.wrap(line, width).each { |chunk| text chunk }
218
+ end
219
+ end
220
+
221
+ private
222
+ def scrub(s)
223
+ "/#{s.sub(/^\/+/,'')}"
224
+ end
225
+ end
226
+
227
+ class GopherError < StandardError; end
228
+ class DirectoryNotFound < GopherError; end
229
+ class NotFound < GopherError; end
230
+ class InvalidRequest < GopherError; end
231
+
232
+ def self.sanitize_selector(selector)
233
+ selector = selector.dup
234
+ selector.strip!
235
+ selector.gsub!(/\.+/, '.')
236
+ selector
237
+ end
238
+ def self.determine_type(selector)
239
+ case File.extname(selector).downcase
240
+ when '.jpg', '.png' then 'I'
241
+ when '.mp3' then 's'
242
+ else '0'
243
+ end
244
+ end
245
+
246
+ class Connection < EM::Connection
247
+ attr_accessor :application
248
+
249
+ def receive_data(data)
250
+ begin
251
+ raise InvalidRequest if data.length > 255
252
+ response = application.request(data)
253
+ case response
254
+ when String then send_data(response)
255
+ when StringIO then send_data(response.read)
256
+ when File
257
+ while chunk = response.read(8192) do
258
+ send_data(chunk)
259
+ end
260
+ end
261
+ close_connection_after_writing
262
+ rescue Gopher::NotFound
263
+ send_data "not found"
264
+ close_connection_after_writing
265
+ rescue => e
266
+ close_connection
267
+ raise e
268
+ end
269
+ end
270
+ end
271
+
272
+ def self.application(&block)
273
+ @application = Application.new(&block)
274
+ end
275
+
276
+ def self.reload(*files)
277
+ @last_reload = Time.now
278
+ @reloadables = files
279
+ end
280
+
281
+ def self.reloadables
282
+ @reloadables ||= []
283
+ end
284
+
285
+ def self.run
286
+ return if EM.reactor_running?
287
+ EM.run do
288
+ EM.start_server(@application.host, @application.port, Gopher::Connection) do |c|
289
+ c.application = @application
290
+ reloadables.each do |f|
291
+ load f if File.mtime(f) > @last_reload
292
+ end
293
+ @last_reload = Time.now
294
+ end
295
+ end
296
+ end
297
+ end
metadata CHANGED
@@ -1,69 +1,101 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: gopher
3
- version: !ruby/object:Gem::Version
4
- version: 0.5.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
5
  platform: ruby
6
- authors:
7
- - raspberry lemon
6
+ authors:
7
+ - umeldt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2008-05-22 00:00:00 +02:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description:
17
- email: lemon@raspberry-style.net
18
- executables:
11
+ date: 2019-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: textwrap
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: eventmachine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.0
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '1.2'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.0
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 10.4.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 10.4.2
61
+ description: ''
62
+ email: chris@svindseth.jp
63
+ executables:
19
64
  - gopher
20
65
  extensions: []
21
-
22
66
  extra_rdoc_files: []
23
-
24
- files:
67
+ files:
68
+ - LICENSE
69
+ - README
25
70
  - bin/gopher
26
- - lib/ext
27
71
  - lib/ext/module.rb
28
- - lib/ext/object.rb
29
- - lib/gopher
72
+ - lib/ext/module.rb~
73
+ - lib/gopher.rb
74
+ - lib/gopher.rb~
30
75
  - lib/gopher/redirect.erb
31
76
  - lib/gopher/redirect.rb
32
- - lib/gopher.rb
33
- - spec/application_spec.rb
34
- - spec/ext_spec.rb
35
- - spec/gopher_spec.rb
36
- - spec/handler_spec.rb
37
- - spec/sandbox
38
- - spec/sandbox/indexed
39
- - spec/sandbox/indexed/cake.txt
40
- - spec/sandbox/recipe.txt
41
- - spec/spec_helper.rb
42
- has_rdoc: false
43
- homepage: http://raspberry-style.net/
77
+ homepage: https://svindseth.jp/gopher
78
+ licenses:
79
+ - ISC
80
+ metadata: {}
44
81
  post_install_message:
45
82
  rdoc_options: []
46
-
47
- require_paths:
83
+ require_paths:
48
84
  - lib
49
- required_ruby_version: !ruby/object:Gem::Requirement
50
- requirements:
85
+ - bin
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
51
88
  - - ">="
52
- - !ruby/object:Gem::Version
53
- version: "0"
54
- version:
55
- required_rubygems_version: !ruby/object:Gem::Requirement
56
- requirements:
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
57
93
  - - ">="
58
- - !ruby/object:Gem::Version
59
- version: "0"
60
- version:
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
61
96
  requirements: []
62
-
63
- rubyforge_project:
64
- rubygems_version: 1.1.1
97
+ rubygems_version: 3.0.3
65
98
  signing_key:
66
- specification_version: 2
99
+ specification_version: 4
67
100
  summary: gopher server and dsl
68
101
  test_files: []
69
-
@@ -1,17 +0,0 @@
1
- # instance_exec for 1.8
2
- # Grabbed from Mauricio Fernandez (thanks!)
3
- # For more information, see http://eigenclass.org/hiki.rb?instance_exec
4
- class Object
5
- module InstanceExecHelper; end
6
- include InstanceExecHelper
7
- def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec
8
- mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}"
9
- InstanceExecHelper.module_eval{ define_method(mname, &block) }
10
- begin
11
- ret = send(mname, *args)
12
- ensure
13
- InstanceExecHelper.module_eval{ undef_method(mname) } rescue nil
14
- end
15
- ret
16
- end
17
- end
@@ -1,42 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '/spec_helper')
2
-
3
- describe Gopher::Application do
4
- before(:all) do
5
- @app = Gopher::Application.new do
6
- host 'pha.hk'
7
- port 7000
8
-
9
- helpers do
10
- def ruler
11
- text ("=-" * 40)
12
- end
13
- end
14
-
15
- mount 'documents', File.dirname(__FILE__)
16
- end
17
- end
18
-
19
- it 'should set the host' do
20
- @app.host.should == 'pha.hk'
21
- end
22
-
23
- it 'should set the port' do
24
- @app.port.should == 7000
25
- end
26
-
27
- it 'should mount directories' do
28
- @app.lookup('/documents').should be_instance_of(Array)
29
- end
30
-
31
- it 'should route properly to directories and their children' do
32
- @app.lookup('/documents/tasty').should include("tasty")
33
- end
34
-
35
- it 'should sanitize lookups' do
36
- @app.lookup('/documents/.././tasty...html').should include("././tasty.html")
37
- end
38
-
39
- it 'should add helpers' do
40
- Gopher::MapContext.public_instance_methods.should include('ruler')
41
- end
42
- end
@@ -1 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '/spec_helper')
@@ -1 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '/spec_helper')
@@ -1,45 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '/spec_helper')
2
-
3
- describe Gopher::DirectoryHandler do
4
- before(:all) do
5
- path = File.join(File.dirname(__FILE__), 'sandbox')
6
- @handler = Gopher::DirectoryHandler.new(path)
7
- end
8
-
9
- it 'should barf on non-existent directories' do
10
- proc { Gopher::DirectoryHandler.new(__FILE__) }.should raise_error(Gopher::DirectoryNotFound)
11
- end
12
-
13
- it 'should serve files under the directory' do
14
- @handler.call('recipe.txt').should be_instance_of(File)
15
- end
16
-
17
- it 'should raise a NotFound when files do not exist' do
18
- proc { @handler.call('recipe.tx') }.should raise_error(Gopher::NotFound)
19
- end
20
-
21
- it 'should serve generated directory maps' do
22
- @handler.call('indexed').should include("An indexed directory")
23
- end
24
-
25
- it 'should serve directory indexes when applicable' do
26
- @handler.call.should include("0recipe.txt\t/recipe.txt\t0.0.0.0\t70\r\n")
27
- end
28
- end
29
-
30
- describe Gopher::MapHandler do
31
- before(:all) do
32
- @handler = Gopher::MapHandler.new do
33
- text 'Cake recipes'
34
- link 'Image', 'cake.jpg'
35
- end
36
- end
37
-
38
- it 'should add text' do
39
- @handler.call.should include "iCake recipes\tfalse\t(NULL)\t0\r\n"
40
- end
41
-
42
- it 'should add links and figure out the types' do
43
- @handler.call.should include "IImage\t/cake.jpg\t0.0.0.0\t70\r\n"
44
- end
45
- end
File without changes
File without changes
@@ -1,2 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '/../lib/gopher')
2
- require 'spec'