bijou 0.1.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 (53) hide show
  1. data/ChangeLog.txt +4 -0
  2. data/LICENSE.txt +58 -0
  3. data/README.txt +48 -0
  4. data/Rakefile +105 -0
  5. data/doc/INSTALL.rdoc +260 -0
  6. data/doc/README.rdoc +314 -0
  7. data/doc/releases/bijou-0.1.0.rdoc +60 -0
  8. data/examples/birthday/birthday.rb +34 -0
  9. data/examples/holiday/holiday.rb +61 -0
  10. data/examples/holiday/letterhead.txt +4 -0
  11. data/examples/holiday/signature.txt +9 -0
  12. data/examples/phishing/letter.txt +29 -0
  13. data/examples/phishing/letterhead.txt +4 -0
  14. data/examples/phishing/phishing.rb +21 -0
  15. data/examples/phishing/signature.txt +9 -0
  16. data/examples/profile/profile.rb +46 -0
  17. data/lib/bijou.rb +15 -0
  18. data/lib/bijou/backend.rb +542 -0
  19. data/lib/bijou/cgi/adapter.rb +201 -0
  20. data/lib/bijou/cgi/handler.rb +5 -0
  21. data/lib/bijou/cgi/request.rb +37 -0
  22. data/lib/bijou/common.rb +12 -0
  23. data/lib/bijou/component.rb +108 -0
  24. data/lib/bijou/config.rb +60 -0
  25. data/lib/bijou/console/adapter.rb +167 -0
  26. data/lib/bijou/console/handler.rb +4 -0
  27. data/lib/bijou/console/request.rb +26 -0
  28. data/lib/bijou/context.rb +431 -0
  29. data/lib/bijou/diagnostics.rb +87 -0
  30. data/lib/bijou/errorformatter.rb +322 -0
  31. data/lib/bijou/exception.rb +39 -0
  32. data/lib/bijou/filters.rb +107 -0
  33. data/lib/bijou/httprequest.rb +108 -0
  34. data/lib/bijou/httpresponse.rb +268 -0
  35. data/lib/bijou/lexer.rb +513 -0
  36. data/lib/bijou/minicgi.rb +159 -0
  37. data/lib/bijou/parser.rb +1026 -0
  38. data/lib/bijou/processor.rb +404 -0
  39. data/lib/bijou/prstringio.rb +400 -0
  40. data/lib/bijou/webrick/adapter.rb +174 -0
  41. data/lib/bijou/webrick/handler.rb +32 -0
  42. data/lib/bijou/webrick/request.rb +45 -0
  43. data/script/cgi.rb +25 -0
  44. data/script/console.rb +7 -0
  45. data/script/server.rb +7 -0
  46. data/test/t1.cfg +5 -0
  47. data/test/tc_config.rb +26 -0
  48. data/test/tc_filter.rb +25 -0
  49. data/test/tc_lexer.rb +120 -0
  50. data/test/tc_response.rb +103 -0
  51. data/test/tc_ruby.rb +62 -0
  52. data/test/tc_stack.rb +50 -0
  53. metadata +121 -0
@@ -0,0 +1,174 @@
1
+
2
+ require 'cgi'
3
+ require 'bijou/processor'
4
+ require 'bijou/httpresponse'
5
+ require 'bijou/webrick/request'
6
+
7
+ module Bijou
8
+ #
9
+ # This module allows Bijou to run under the WEBrick server.
10
+ #
11
+ module WEBrick
12
+ #
13
+ # This adapter encapsulates the differences between the WEBrick server and
14
+ # the interfaces expected within the Bijou environment.
15
+ #
16
+ class Bijou::WEBrick::Adapter
17
+ def self.handle(req, res)
18
+ bijou_types =
19
+ [
20
+ [ 'rbb', 'text/html' ],
21
+ [ 'htm', 'text/html' ],
22
+ [ 'html', 'text/html' ],
23
+ ]
24
+
25
+ path_info = req.path
26
+ document_root = ENV['DOCUMENT_ROOT']
27
+ bijou_cache = ENV['BIJOU_CACHE']
28
+ bijou_config = ENV['BIJOU_CONFIG']
29
+
30
+ if bijou_config
31
+ begin
32
+ config = Bijou::Config.load_file(bijou_config)
33
+ rescue SyntaxError
34
+ error = $!.to_s
35
+ error << "\nStack: " + $@.join("\n")
36
+
37
+ return self::diagnostic(res, "Error",
38
+ "Error loading configuration.", error)
39
+ end
40
+
41
+ if (!config)
42
+ return self.error(res, 200, "Error",
43
+ "The configuration file path is invalid." +
44
+ " Please check the WEbrick configuration.")
45
+ end
46
+ else
47
+ config = Bijou::Config.new
48
+ end
49
+
50
+ # The config file overrides the environment settings.
51
+ if !config.document_root || config.document_root.empty?
52
+ if document_root
53
+ config.document_root = document_root
54
+ else
55
+ config.document_root = Dir.getwd
56
+ end
57
+ end
58
+
59
+ if !config.cache_root && bijou_cache
60
+ config.cache_root = bijou_cache
61
+ end
62
+
63
+ config.includes.each do |inc|
64
+ $:.push inc
65
+ end
66
+
67
+ # Remove any leading slashes so expand_path doesn't see it as absolute.
68
+ if path_info[0,1] == '/'
69
+ path_info = path_info[1..-1]
70
+ end
71
+
72
+ found = false
73
+ bijou_types.each {|type|
74
+ ext = type[0]
75
+ if path_info =~ /\.#{ext}$/
76
+ found = true
77
+ end
78
+ }
79
+
80
+ if !found
81
+ response = Bijou::Processor.handle_other(config, path_info)
82
+
83
+ res.status = response['status']
84
+ res['Content-Type'] = response['type']
85
+ res.body = response['body']
86
+ return
87
+ end
88
+
89
+ processor = Bijou::Processor.new
90
+
91
+ # Build the page from the request.
92
+ begin
93
+ context = processor.load(path_info, config)
94
+ rescue Exception
95
+ msg = Bijou::ErrorFormatter.format_error :html, 4
96
+ return self.formatted_error(res, "Error loading page", msg)
97
+ end
98
+
99
+ #
100
+ # Prepare the request data.
101
+ #
102
+
103
+ context.request = Bijou::WEBrick::Request.new(req)
104
+ context.response = HttpResponse.new
105
+
106
+ args = {}
107
+ args.replace(context.request.params);
108
+
109
+ begin
110
+ context.render(args)
111
+ rescue Exception
112
+ msg = Bijou::ErrorFormatter.format_error :html, 4, context
113
+ return self.formatted_error(res, "Error rendering page", msg)
114
+ end
115
+
116
+ res.status = 200
117
+ res['Content-Type'] = "text/html"
118
+ res.body = context.output;
119
+
120
+ # print_environment cgi
121
+ end
122
+
123
+ private
124
+
125
+ def self.error(res, num, title, message)
126
+ res.status = num
127
+ res['Content-Type'] = "text/html"
128
+ res.body = "<html>" +
129
+ "<h1>#{num} #{title}</h1>" +
130
+ "<p>#{message}</p>" +
131
+ "</html>"
132
+ end
133
+
134
+ def self.diagnostic(res, title, message, diagnostic)
135
+ # 'charset' => 'iso-8859-1',
136
+ res.status = 200
137
+ res['Content-Type'] = "text/html"
138
+ res.body = "<html>" +
139
+ "<h1>#{title}</h1>" +
140
+ "<p>#{message}</p>" +
141
+ "<pre>#{::CGI::escapeHTML(diagnostic)}</pre>" +
142
+ "</html>"
143
+ return nil
144
+ end
145
+
146
+ def self.formatted_error(res, title, message)
147
+ res.status = 200
148
+ res['Content-Type'] = "text/html"
149
+ res.body = "<html>" +
150
+ '<head><title>Bijou Error</title></head>' +
151
+ "<h1>#{title}</h1>" +
152
+ message +
153
+ '</html>'
154
+ return nil
155
+ end
156
+
157
+ def self.print_environment
158
+ # print "Content-type: text/html; charset=iso-8859-1\n\n"
159
+ # print "Hello, world!"
160
+ # puts $:
161
+
162
+ print "<pre>" +
163
+ ::CGI::escapeHTML(
164
+ "params: " + cgi.params.inspect + "\n" +
165
+ "cookies: " + cgi.cookies.inspect + "\n" +
166
+ ENV.collect() do |key, value|
167
+ key + " --> " + value + "\n"
168
+ end.join("")
169
+ ) +
170
+ "<pre>"
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,32 @@
1
+
2
+ require 'webrick'
3
+ require 'bijou/webrick/adapter'
4
+
5
+ include WEBrick
6
+
7
+ s = HTTPServer.new( :Port => 2000 )
8
+
9
+ #
10
+ # A basic WEBrick servlet to get started with Bijou. This servlet can be
11
+ # started by running 'ruby script/server.rb' on the local machine.
12
+ #
13
+ # Note that it does not support the POST method, so any forms must specifiy
14
+ # the attribute method="GET" or leave it unspecified (as the default is GET).
15
+ #
16
+ class Bijou::WEBrick::Servlet < HTTPServlet::AbstractServlet
17
+ # The GET handler dispatches incoming requests to the Bijou::WEBrick::Adapter
18
+ # class.
19
+ def do_GET(request, response)
20
+ servlet = Bijou::WEBrick::Adapter.handle(request, response)
21
+ end
22
+ end
23
+
24
+ #
25
+ # When a request beginning with '/' is received, the HTTPServer creates an
26
+ # instance of BijouServlet and calls do_[method]
27
+ #
28
+ s.mount("/", Bijou::WEBrick::Servlet)
29
+
30
+ trap("INT"){ s.shutdown }
31
+
32
+ s.start
@@ -0,0 +1,45 @@
1
+
2
+ require 'bijou/minicgi'
3
+ require 'bijou/httprequest'
4
+
5
+ module Bijou
6
+ module WEBrick
7
+ class Request < Bijou::HttpRequest
8
+ #
9
+ # Accepts a WEBrick::HTTPRequest object and adapts it to the HttpRequest
10
+ # object expected by the Bijou component.
11
+ #
12
+ def initialize(req)
13
+ super()
14
+
15
+ @req = req
16
+
17
+ if @req.query_string
18
+ query_string = ::CGI::parse(@req.query_string) || {}
19
+ @query_string = Bijou::MiniCGI.singularize(query_string)
20
+ else
21
+ @query_string = {}
22
+ end
23
+
24
+ @form = @query_string.clone
25
+ @params = @query_string.clone
26
+
27
+ #cookies = ::CGI::Cookie::parse(@req.cookies)
28
+ @cookies = @req.cookies
29
+
30
+ @http_method = @req.request_method
31
+ end
32
+
33
+ attr_reader :req
34
+
35
+ #--
36
+ # TODO: Standardize accessor name.
37
+ #++
38
+ def virtual_path
39
+ # @server_variables['REQUEST_URI']
40
+ # @server_variables['PATH_INFO']
41
+ @req.request_uri
42
+ end
43
+ end
44
+ end
45
+ end
data/script/cgi.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # The following comment was taken and adapted from the Apache config file:
4
+ #
5
+ # Apache parses all CGI scripts for the shebang line by default.
6
+ # This comment line, the first line of the script, consists of the symbols
7
+ # pound (#) and exclamation (!) followed by the path of the program that
8
+ # can execute this specific script. For a Ruby script, with ruby.exe in
9
+ # the C:\Program Files\Ruby directory, the shebang line should be:
10
+ #
11
+ #!c:/program files/ruby/bin/ruby
12
+ #
13
+ # Note you _must_not_ indent the actual shebang line, and it must be the
14
+ # first line of the file. Of course, CGI processing must be enabled by
15
+ # the appropriate ScriptAlias or Options ExecCGI directives for the files
16
+ # or directory in question.
17
+ #
18
+ # See doc/INSTALL.rdoc for more information regarding Apache configuration.
19
+ #
20
+ $:.push '../lib'
21
+
22
+ require 'rubygems'
23
+ require 'bijou'
24
+
25
+ load 'bijou/cgi/handler.rb'
data/script/console.rb ADDED
@@ -0,0 +1,7 @@
1
+
2
+ $:.push '../lib'
3
+
4
+ require 'rubygems'
5
+ require 'bijou'
6
+
7
+ load 'bijou/console/handler.rb'
data/script/server.rb ADDED
@@ -0,0 +1,7 @@
1
+
2
+ $:.push '../lib'
3
+
4
+ require 'rubygems'
5
+ require 'bijou'
6
+
7
+ load 'bijou/webrick/handler.rb'
data/test/t1.cfg ADDED
@@ -0,0 +1,5 @@
1
+
2
+ @document_root = '../web'
3
+ @cache_root = '../web_cache'
4
+ @debug = true
5
+ @trace_level = 3
data/test/tc_config.rb ADDED
@@ -0,0 +1,26 @@
1
+
2
+ $:.push '../lib'
3
+
4
+ require 'test/unit'
5
+ require 'bijou/config'
6
+
7
+ class ConfigTestCase < Test::Unit::TestCase
8
+ def setup
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def test_basic
15
+ file = File.expand_path('t1.cfg', File.dirname(__FILE__))
16
+
17
+ cfg = Bijou::Config.load_file(file)
18
+
19
+ assert cfg
20
+ assert cfg.document_root == '../web'
21
+ assert cfg.cache_root == '../web_cache'
22
+ assert cfg.debug == true
23
+ assert cfg.trace_level == Bijou::Log::Info
24
+ end
25
+
26
+ end
data/test/tc_filter.rb ADDED
@@ -0,0 +1,25 @@
1
+
2
+ $:.push '../lib'
3
+
4
+ require 'test/unit'
5
+ require 'bijou/filters'
6
+
7
+ class FilterTestCase < Test::Unit::TestCase
8
+ def setup
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ # Ensure attibute values are escaped as expected.
15
+ def test_attribute_value
16
+ assert_equal Bijou::EncodeAttributeValue.apply("'"), '&apos;'
17
+ assert_equal Bijou::EncodeAttributeValue.apply('"'), '&quot;'
18
+ assert_equal Bijou::EncodeAttributeValue.apply('<'), '&lt;'
19
+ assert_equal Bijou::EncodeAttributeValue.apply('&'), '&amp;'
20
+ assert_equal Bijou::EncodeAttributeValue.apply('<&\'"'),
21
+ '&lt;&amp;&apos;&quot;'
22
+ assert_equal Bijou::EncodeAttributeValue.apply('a<bc& \'" '),
23
+ 'a&lt;bc&amp; &apos;&quot; '
24
+ end
25
+ end
data/test/tc_lexer.rb ADDED
@@ -0,0 +1,120 @@
1
+
2
+ $:.push '../lib'
3
+ #$:.push File.expand_path(File.dirname(__FILE__) + '/..')
4
+
5
+ require 'test/unit'
6
+ require 'bijou/lexer'
7
+
8
+ #--
9
+ # Use stringio, if available. Otherwise, use the alternative.
10
+ #++
11
+ begin
12
+ require 'stringio'
13
+ rescue LoadError
14
+ require 'bijou/prstringio'
15
+
16
+ class StringIO < PureRubyStringIO
17
+ end
18
+ end
19
+
20
+ module LexerHelp
21
+ #
22
+ # Utility methods
23
+ #
24
+
25
+ def open_input(str)
26
+ file = StringIO.new(str)
27
+ diagnostics = Bijou::Parse::Diagnostics.new
28
+ input = Bijou::Parse::LexerInput.new(file, diagnostics)
29
+ return input
30
+ end
31
+
32
+ def scan_top(str)
33
+ input = open_input(str)
34
+ return Bijou::Parse::TextLexer.new(input)
35
+ end
36
+
37
+ def scan_tags(str)
38
+ input = open_input(str)
39
+ return Bijou::Parse::TagLexer.new(input)
40
+ end
41
+
42
+ end
43
+
44
+ class TopTestCase < Test::Unit::TestCase
45
+ include LexerHelp
46
+ include Bijou::Parse
47
+
48
+ def setup
49
+ end
50
+
51
+ def teardown
52
+ end
53
+
54
+ #
55
+ # Utility methods
56
+ #
57
+
58
+ #
59
+ # Test methods
60
+ #
61
+
62
+ def test_empty
63
+ lexer = scan_top("")
64
+ assert_equal(nil, lexer.next_token)
65
+ lexer.input.close
66
+ end
67
+
68
+ def test_opentokens
69
+ lexer = scan_top("<")
70
+ assert lexer.next_token == Token::Char && lexer.text == '<'
71
+ assert lexer.next_token == nil
72
+ lexer.input.close
73
+
74
+ lexer = scan_top("=")
75
+ assert lexer.next_token == Token::Char && lexer.text == '='
76
+ assert lexer.next_token == nil
77
+ lexer.input.close
78
+
79
+ lexer = scan_top("=")
80
+ lexer.tokenize_arguments = true
81
+ assert lexer.next_token == Token::Char && lexer.text == '='
82
+ assert lexer.next_token == nil
83
+ lexer.input.close
84
+
85
+ lexer = scan_top("'")
86
+ assert lexer.next_token == Token::Char && lexer.text == "'"
87
+ assert lexer.next_token == nil
88
+ lexer.input.close
89
+ end
90
+
91
+ def scan_unterminated_string(str)
92
+ lexer = scan_top(str)
93
+ lexer.tokenize_arguments = true
94
+ assert_equal nil, lexer.next_token
95
+ assert lexer.warnings.length == 1 &&
96
+ lexer.warnings[0].text =~ /unterminated string literal/,
97
+ 'unterminated string literal'
98
+ lexer.input.close
99
+ end
100
+
101
+ def test_unterminated_string
102
+ scan_unterminated_string('"')
103
+ scan_unterminated_string('" ')
104
+ scan_unterminated_string("' ")
105
+ scan_unterminated_string("'\n")
106
+ scan_unterminated_string("' \n")
107
+ scan_unterminated_string("'\n ")
108
+ scan_unterminated_string("' \n ")
109
+ end
110
+
111
+ def test_basic
112
+ lexer = scan_top("<")
113
+
114
+ while tok = lexer.next_token
115
+ puts "tok: #{tok} #{lexer.text}"
116
+ end
117
+
118
+ lexer.input.close
119
+ end
120
+ end