Capcode 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,7 @@ module Capcode
12
12
  def post
13
13
  FileUtils.cp(
14
14
  params["upfile"][:tempfile].path,
15
- File.join( static[:path], params["upfile"][:filename] )
15
+ ::File.join( static[:path], params["upfile"][:filename] )
16
16
  )
17
17
  render :static => params["upfile"][:filename]
18
18
  end
@@ -6,7 +6,7 @@ require 'logger'
6
6
  Logger.class_eval { alias :write :<< } unless Logger.instance_methods.include? "write"
7
7
  require 'optparse'
8
8
  require 'irb'
9
- require 'mime/types'
9
+ require 'active_support'
10
10
  require 'capcode/version'
11
11
  require 'capcode/core_ext'
12
12
  require 'capcode/helpers/auth'
@@ -14,17 +14,9 @@ require 'capcode/render/text'
14
14
  require 'capcode/configuration'
15
15
  require 'capcode/filters'
16
16
 
17
+ require 'capcode/ext/rack/urlmap'
18
+
17
19
  module Capcode
18
- #@@__ROUTES = {}
19
- #@@__STATIC_DIR = nil
20
- #@@__APP = nil
21
-
22
- # @@__FILTERS = []
23
- # def self.before_filter( opts, &b )
24
- # opts[:action] = b
25
- # @@__FILTERS << opts
26
- # end
27
-
28
20
  class ParameterError < ArgumentError #:nodoc: all
29
21
  end
30
22
 
@@ -42,7 +34,6 @@ module Capcode
42
34
 
43
35
  # Helpers contains methods available in your controllers
44
36
  module Helpers
45
- #@@__ARGS__ = nil
46
37
  def self.args
47
38
  @args ||= nil
48
39
  end
@@ -85,33 +76,32 @@ module Capcode
85
76
  render_type = nil
86
77
  possible_code_renderer = nil
87
78
 
88
- if render_type.nil?
89
- hash.keys.each do |key|
90
- begin
91
- gem "capcode-render-#{key.to_s}"
92
- require "capcode/render/#{key.to_s}"
93
- rescue Gem::LoadError
94
- nil
95
- rescue LoadError
96
- raise Capcode::RenderError, "Hum... The #{key} renderer is malformated! Please try to install a new version or use an other renderer!", caller
97
- end
98
-
99
- if self.respond_to?("render_#{key.to_s}")
100
- unless render_type.nil?
101
- raise Capcode::RenderError, "Can't use multiple renderer (`#{render_type}' and `#{key}') !", caller
102
- end
103
- render_type = key
104
- end
105
-
106
- if key.class == Fixnum
107
- possible_code_renderer = key
79
+ hash.keys.each do |key|
80
+ begin
81
+ gem "capcode-render-#{key.to_s}"
82
+ require "capcode/render/#{key.to_s}"
83
+ rescue Gem::LoadError
84
+ nil
85
+ rescue LoadError
86
+ raise Capcode::RenderError, "Hum... The #{key} renderer is malformated! Please try to install a new version or use an other renderer!", caller
87
+ end
88
+
89
+ if self.respond_to?("render_#{key.to_s}")
90
+ unless render_type.nil?
91
+ raise Capcode::RenderError, "Can't use multiple renderer (`#{render_type}' and `#{key}') !", caller
108
92
  end
93
+ render_type = key
109
94
  end
110
95
 
111
- if render_type.nil? and possible_code_renderer.nil?
112
- raise Capcode::RenderError, "Renderer type not specified!", caller
96
+ if key.class == Fixnum
97
+ possible_code_renderer = key
113
98
  end
114
99
  end
100
+
101
+ if render_type.nil? and possible_code_renderer.nil?
102
+ raise Capcode::RenderError, "Renderer type not specified!", caller
103
+ end
104
+
115
105
  unless self.respond_to?("render_#{render_type.to_s}")
116
106
  if possible_code_renderer.nil?
117
107
  raise Capcode::RenderError, "#{render_type} renderer not present ! please require 'capcode/render/#{render_type}'", caller
@@ -123,7 +113,8 @@ module Capcode
123
113
  k = k.to_s.split(/_/).map{|e| e.capitalize}.join("-")
124
114
  header[k] = v
125
115
  end
126
- [code, hash, body]
116
+
117
+ [code, header, body]
127
118
  end
128
119
  else
129
120
  render_name = hash.delete(render_type)
@@ -212,17 +203,39 @@ module Capcode
212
203
  # URL( Capcode::Hello, "you" ) # => /hello/you
213
204
  def URL( klass, *a )
214
205
  path = nil
206
+ result = {}
207
+
215
208
  a = a.delete_if{ |x| x.nil? }
216
209
 
217
210
  if klass.class == Class
218
- Capcode.routes.each do |p, k|
219
- path = p if k.class == klass
211
+ last_size = 0
212
+
213
+ klass.__urls__[0].each do |cpath, regexp|
214
+ data = a.clone
215
+
216
+ n = Regexp.new( regexp ).number_of_captures
217
+ equart = (a.size - n).abs
218
+
219
+ rtable = regexp.dup.gsub( /\\\(/, "" ).gsub( /\\\)/, "" ).split( /\([^\)]*\)/ )
220
+
221
+ rtable.each do |r|
222
+ if r == ""
223
+ cpath = cpath + "/#{data.shift}"
224
+ else
225
+ cpath = cpath + "/#{r}"
226
+ end
227
+ end
228
+
229
+ cpath = (cpath + "/" + data.join( "/" )).gsub( /\/\//, "/" ).gsub( /\/$/, "" )
230
+ result[equart] = cpath
220
231
  end
232
+
233
+ path = result[result.keys.min]
221
234
  else
222
235
  path = klass
223
236
  end
224
237
 
225
- (ENV['RACK_BASE_URI']||'')+path+((a.size>0)?("/"+a.join("/")):(""))
238
+ (ENV['RACK_BASE_URI']||'')+path
226
239
  end
227
240
 
228
241
  # Calling content_for stores a block of markup in an identifier.
@@ -258,7 +271,6 @@ module Capcode
258
271
  # end
259
272
  # end
260
273
  def content_for( x )
261
- #if @@__ARGS__.map{|_| _.to_s }.include?(x.to_s)
262
274
  if Capcode::Helpers.args.map{|_| _.to_s }.include?(x.to_s)
263
275
  yield
264
276
  end
@@ -293,6 +305,18 @@ module Capcode
293
305
  # end
294
306
  # end
295
307
  #
308
+ # the rXXX method can also receive a second optional parameter corresponding
309
+ # of the header's Hash :
310
+ #
311
+ # module Capcode
312
+ # class HTTPError
313
+ # def r404(f, h)
314
+ # h['Content-Type'] = 'text/plain'
315
+ # "You are here ---> X (#{f} point)"
316
+ # end
317
+ # end
318
+ # end
319
+ #
296
320
  # Do the same (r500, r501, r403) to customize 500, 501, 403 errors
297
321
  class HTTPError
298
322
  def initialize(app) #:nodoc:
@@ -301,16 +325,23 @@ module Capcode
301
325
 
302
326
  def call(env) #:nodoc:
303
327
  status, headers, body = @app.call(env)
304
-
305
328
  if self.methods.include? "r#{status}"
306
- body = self.send( "r#{status}", env['REQUEST_PATH'] )
329
+ headers.delete('Content-Type') if headers.keys.include?('Content-Type')
330
+ body = begin
331
+ self.send( "r#{status}", env['REQUEST_PATH'], headers )
332
+ rescue
333
+ self.send( "r#{status}", env['REQUEST_PATH'] )
334
+ end
307
335
  headers['Content-Length'] = body.length.to_s
336
+ headers['Content-Type'] = "text/html" unless headers.keys.include?('Content-Type')
308
337
  end
309
338
 
310
339
  [status, headers, body]
311
340
  end
312
341
  end
313
342
 
343
+ require 'capcode/response'
344
+
314
345
  class << self
315
346
  attr :__auth__, true #:nodoc:
316
347
 
@@ -332,8 +363,10 @@ module Capcode
332
363
  #
333
364
  # If the regexp in the route does not match, all arguments will be <tt>nil</tt>
334
365
  def Route *routes_paths
366
+ create_path = routes_paths[0].nil?
335
367
  Class.new {
336
368
  meta_def(:__urls__) {
369
+ routes_paths = ['/'+self.to_s.gsub( /^Capcode::/, "" ).underscore] if create_path == true
337
370
  # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
338
371
  # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'},
339
372
  # 2,
@@ -391,21 +424,6 @@ module Capcode
391
424
  @response = Rack::Response.new
392
425
  @request = Rack::Request.new(@env)
393
426
 
394
- # __k = self.class.to_s.split( /::/ )[-1].downcase.to_sym
395
- # @@__FILTERS.each do |f|
396
- # proc = f.delete(:action)
397
- # __run = true
398
- # if f[:only]
399
- # __run = f[:only].include?(__k)
400
- # end
401
- # if f[:except]
402
- # __run = !f[:except].include?(__k)
403
- # end
404
- #
405
- # # proc.call(self) if __run
406
- # puts "call #{proc} for #{__k}"
407
- # end
408
-
409
427
  # Check authz
410
428
  authz_options = nil
411
429
  if Capcode.__auth__ and Capcode.__auth__.size > 0
@@ -441,14 +459,17 @@ module Capcode
441
459
  xPath = p.gsub( /^\//, "" ).split( "/" )
442
460
  if (xPath - aPath).size == 0
443
461
  diffArgs = aPath - xPath
444
- diffNArgs = diffArgs.size
462
+ diffNArgs = diffArgs.size - 1
445
463
  if finalNArgs.nil? or finalNArgs > diffNArgs
446
464
  finalPath = p
447
465
  finalNArgs = diffNArgs
448
466
  finalArgs = diffArgs
449
467
  end
450
468
  end
451
-
469
+ end
470
+
471
+ if finalNArgs > self.class.__urls__[1]
472
+ return [404, {'Content-Type' => 'text/plain'}, "Not Found: #{@request.path}"]
452
473
  end
453
474
 
454
475
  nargs = self.class.__urls__[1]
@@ -481,32 +502,33 @@ module Capcode
481
502
  filter_output
482
503
  end
483
504
  }
505
+
484
506
  if r.respond_to?(:to_ary)
485
507
  @response.status = r.shift #r[0]
486
508
  #r[1].each do |k,v|
487
509
  r.shift.each do |k,v|
488
510
  @response[k] = v
489
511
  end
490
- @response.body = r.shift #r[2]
512
+ @response.write r.shift #r[2]
491
513
  else
492
514
  @response.write r
493
515
  end
494
-
516
+
495
517
  @response.finish
496
518
  end
497
519
 
498
520
  include Capcode::Helpers
499
- include Capcode::Views
521
+ include Capcode::Views
500
522
  }
501
523
  end
502
-
524
+ Capcode::Route = Capcode::Route(nil)
525
+
503
526
  # This method help you to map and URL to a Rack or What you want Helper
504
527
  #
505
528
  # Capcode.map( "/file" ) do
506
529
  # Rack::File.new( "." )
507
530
  # end
508
531
  def map( route, &b )
509
- #@@__ROUTES[route] = yield
510
532
  Capcode.routes[route] = yield
511
533
  end
512
534
 
@@ -570,15 +592,28 @@ module Capcode
570
592
  def application( args = {} )
571
593
  Capcode::Configuration.configuration(args)
572
594
 
573
- Capcode.constants.each do |k|
595
+ Capcode.constants.clone.delete_if {|k|
596
+ not( Capcode.const_get(k).to_s =~ /Capcode/ ) or [
597
+ "Filter",
598
+ "Helpers",
599
+ "RouteError",
600
+ "Views",
601
+ "ParameterError",
602
+ "HTTPError",
603
+ "Configuration",
604
+ "MissingLibrary",
605
+ "Route",
606
+ "RenderError"
607
+ ].include?(k)
608
+ }.each do |k|
574
609
  begin
575
610
  if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
576
- hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
611
+ hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
577
612
  hash_of_routes.keys.each do |current_route_path|
578
613
  #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path)
579
614
  raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
580
- #@@__ROUTES[current_route_path] = klass.new
581
- Capcode.routes[current_route_path] = klass.new
615
+ # Capcode.routes[current_route_path] = klass.new
616
+ Capcode.routes[current_route_path] = klass
582
617
  end
583
618
  end
584
619
  rescue => e
@@ -587,13 +622,12 @@ module Capcode
587
622
  end
588
623
 
589
624
  # Set Static directory
590
- #@@__STATIC_DIR = (conf[:static][0].chr == "/")?conf[:static]:"/"+conf[:static] unless conf[:static].nil?
591
625
  Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
592
626
 
593
627
  # Initialize Rack App
594
628
  puts "** Map routes." if Capcode::Configuration.get(:verbose)
595
- #app = Rack::URLMap.new(@@__ROUTES)
596
- app = Rack::URLMap.new(Capcode.routes)
629
+ # app = Rack::URLMap.new(Capcode.routes)
630
+ app = Capcode::Ext::Rack::URLMap.new(Capcode.routes)
597
631
  puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
598
632
  app = Rack::Static.new(
599
633
  app,
@@ -608,7 +642,6 @@ module Capcode
608
642
  app = Rack::Lint.new(app)
609
643
  app = Rack::ShowExceptions.new(app)
610
644
  #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
611
- # app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) )
612
645
 
613
646
  middlewares.each do |mw|
614
647
  middleware, args, block = mw
@@ -626,6 +659,7 @@ module Capcode
626
659
  end
627
660
 
628
661
  if block_given?
662
+ puts "** Execute block" if Capcode::Configuration.get(:verbose)
629
663
  yield( self )
630
664
  end
631
665
 
@@ -763,16 +797,13 @@ module Capcode
763
797
  end
764
798
 
765
799
  def routes #:nodoc:
766
- #@@__ROUTES
767
800
  @routes ||= {}
768
801
  end
769
802
 
770
803
  def static #:nodoc:
771
- #@@__STATIC_DIR
772
804
  @static_dir ||= nil
773
805
  end
774
806
  def static=(x) #:nodoc:
775
- #@@__STATIC_DIR
776
807
  @static_dir = x
777
808
  end
778
809
 
@@ -0,0 +1,59 @@
1
+ module Capcode
2
+ module Ext
3
+ module Rack
4
+ # Rack::URLMap takes a hash mapping urls or paths to apps, and
5
+ # dispatches accordingly. Support for HTTP/1.1 host names exists if
6
+ # the URLs start with <tt>http://</tt> or <tt>https://</tt>.
7
+ #
8
+ # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part
9
+ # relevant for dispatch is in the SCRIPT_NAME, and the rest in the
10
+ # PATH_INFO. This should be taken care of when you need to
11
+ # reconstruct the URL in order to create links.
12
+ #
13
+ # URLMap dispatches in such a way that the longest paths are tried
14
+ # first, since they are most specific.
15
+
16
+ class URLMap
17
+ def initialize(map = {})
18
+ remap(map)
19
+ end
20
+
21
+ def remap(map)
22
+ @mapping = map.map { |location, app|
23
+ if location =~ %r{\Ahttps?://(.*?)(/.*)}
24
+ host, location = $1, $2
25
+ else
26
+ host = nil
27
+ end
28
+
29
+ unless location[0] == ?/
30
+ raise ArgumentError, "paths need to start with /"
31
+ end
32
+ location = location.chomp('/')
33
+ match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
34
+
35
+ [host, location, match, app]
36
+ }.sort_by { |(h, l, m, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] } # Longest path first
37
+ end
38
+
39
+ def call(env)
40
+ path = env["PATH_INFO"].to_s
41
+ script_name = env['SCRIPT_NAME']
42
+ hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
43
+ @mapping.each { |host, location, match, app|
44
+ next unless (hHost == host || sName == host \
45
+ || (host.nil? && (hHost == sName || hHost == sName+':'+sPort)))
46
+ next unless path =~ match && rest = $1
47
+ next unless rest.empty? || rest[0] == ?/
48
+
49
+ return app.new.call(
50
+ env.merge(
51
+ 'SCRIPT_NAME' => (script_name + location),
52
+ 'PATH_INFO' => rest))
53
+ }
54
+ [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]]
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,6 +1,7 @@
1
1
  module Capcode
2
2
  module Helpers
3
3
  def render_text( f, _ ) #:nodoc:
4
+ @response['Content-Type'] = 'text/plain'
4
5
  f
5
6
  end
6
7
  end
@@ -1,3 +1,3 @@
1
1
  module Capcode
2
- CAPCOD_VERION="0.9.3"
2
+ CAPCOD_VERION="0.9.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Capcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ hash: 51
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 4
10
+ version: 0.9.4
5
11
  platform: ruby
6
12
  authors:
7
13
  - "Gr\xC3\xA9goire Lejeune"
@@ -9,19 +15,37 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-02-10 00:00:00 +01:00
18
+ date: 2010-05-28 00:00:00 +02:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: rack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
17
33
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: activesupport
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
20
40
  requirements:
21
41
  - - ">="
22
42
  - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
23
46
  version: "0"
24
- version:
47
+ type: :runtime
48
+ version_requirements: *id002
25
49
  description: Capcode is a web microframework
26
50
  email: gregoire.lejeune@free.fr
27
51
  executables: []
@@ -67,6 +91,7 @@ files:
67
91
  - lib/capcode/base/db.rb
68
92
  - lib/capcode/configuration.rb
69
93
  - lib/capcode/core_ext.rb
94
+ - lib/capcode/ext/rack/urlmap.rb
70
95
  - lib/capcode/filters.rb
71
96
  - lib/capcode/helpers/auth.rb
72
97
  - lib/capcode/render/text.rb
@@ -89,6 +114,7 @@ files:
89
114
  - examples/rest-run.rb
90
115
  - examples/rest.rb
91
116
  - examples/rest.ru
117
+ - examples/route.rb
92
118
  - examples/sample.rb
93
119
  - examples/session.rb
94
120
  - examples/soapbox/public/jquery.js
@@ -144,21 +170,29 @@ rdoc_options:
144
170
  require_paths:
145
171
  - lib
146
172
  required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
147
174
  requirements:
148
175
  - - ">="
149
176
  - !ruby/object:Gem::Version
177
+ hash: 53
178
+ segments:
179
+ - 1
180
+ - 8
181
+ - 1
150
182
  version: 1.8.1
151
- version:
152
183
  required_rubygems_version: !ruby/object:Gem::Requirement
184
+ none: false
153
185
  requirements:
154
186
  - - ">="
155
187
  - !ruby/object:Gem::Version
188
+ hash: 3
189
+ segments:
190
+ - 0
156
191
  version: "0"
157
- version:
158
192
  requirements: []
159
193
 
160
194
  rubyforge_project: capcode
161
- rubygems_version: 1.3.5
195
+ rubygems_version: 1.3.7
162
196
  signing_key:
163
197
  specification_version: 3
164
198
  summary: Capcode is a web microframework