cuca 0.01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/application_skeleton/README +21 -0
  2. data/application_skeleton/app/_controllers/application.rb +7 -0
  3. data/application_skeleton/app/_layouts/simple.rb +19 -0
  4. data/application_skeleton/app/_widgets/sourcecode.rb +21 -0
  5. data/application_skeleton/app/_widgets/test.rb +23 -0
  6. data/application_skeleton/app/demo.rb +64 -0
  7. data/application_skeleton/app/index.rb +39 -0
  8. data/application_skeleton/app/user/__default_username/index.rb +7 -0
  9. data/application_skeleton/conf/environment.rb +16 -0
  10. data/application_skeleton/log/access.log +1 -0
  11. data/application_skeleton/log/error.log +1 -0
  12. data/application_skeleton/log/messages +1 -0
  13. data/application_skeleton/public/css/style.css +27 -0
  14. data/application_skeleton/public/dispatch.cgi +31 -0
  15. data/application_skeleton/public/dispatch.fcgi +36 -0
  16. data/application_skeleton/public/img/cuca-seagull.png +0 -0
  17. data/application_skeleton/scripts/console +5 -0
  18. data/application_skeleton/scripts/console.rb +5 -0
  19. data/application_skeleton/scripts/server-lighttpd-fcgi.rb +116 -0
  20. data/application_skeleton/scripts/server-lighttpd.rb +109 -0
  21. data/application_skeleton/scripts/server-webrick.rb +26 -0
  22. data/application_skeleton/scripts/test.rb +8 -0
  23. data/application_skeleton/tests/widgets/link.rb +22 -0
  24. data/bin/cuca +43 -0
  25. data/lib/cuca/app.rb +317 -0
  26. data/lib/cuca/cgi_emu.rb +67 -0
  27. data/lib/cuca/cgi_fix.rb +58 -0
  28. data/lib/cuca/const.rb +3 -0
  29. data/lib/cuca/controller.rb +240 -0
  30. data/lib/cuca/generator/markaby.rb +80 -0
  31. data/lib/cuca/generator/view.rb +121 -0
  32. data/lib/cuca/layout.rb +62 -0
  33. data/lib/cuca/mimetypes.rb +89 -0
  34. data/lib/cuca/session.rb +143 -0
  35. data/lib/cuca/sessionflash.rb +56 -0
  36. data/lib/cuca/sessionpage.rb +41 -0
  37. data/lib/cuca/stdlib/arform.rb +208 -0
  38. data/lib/cuca/stdlib/arview.rb +16 -0
  39. data/lib/cuca/stdlib/form.rb +137 -0
  40. data/lib/cuca/stdlib/formerrors.rb +20 -0
  41. data/lib/cuca/stdlib/link.rb +37 -0
  42. data/lib/cuca/stdlib/list.rb +3 -0
  43. data/lib/cuca/stdlib/listwidget/dblist.rb +122 -0
  44. data/lib/cuca/stdlib/listwidget/list.rb +189 -0
  45. data/lib/cuca/stdlib/listwidget/querydef.rb +167 -0
  46. data/lib/cuca/stdlib/listwidget/staticdatalist.rb +79 -0
  47. data/lib/cuca/stdlib/slink.rb +30 -0
  48. data/lib/cuca/test/helpers.rb +42 -0
  49. data/lib/cuca/urlmap.rb +267 -0
  50. data/lib/cuca/widget.rb +212 -0
  51. data/lib/cuca.rb +68 -0
  52. metadata +141 -0
@@ -0,0 +1,80 @@
1
+ require 'markaby'
2
+
3
+ # Modify Markaby's method_missing function so we find our own widgets
4
+ #
5
+ class ::Markaby::Builder # :nodoc:
6
+ alias :old_method_missing :method_missing
7
+
8
+ def method_missing(sym, *args, &block ) # :nodoc:
9
+ class_name = sym.id2name
10
+ begin
11
+ c=Object::const_get(class_name+"Widget")
12
+ rescue NameError => e
13
+ return old_method_missing(sym,*args,&block)
14
+ end
15
+
16
+ # $stderr.puts "Widget in markaby: Class: #{class_name}, \n\n assigns: #{@assigns.inspect} \n\n"
17
+
18
+ widget = c.new({:args => args,
19
+ :assigns => @assigns },
20
+ &block)
21
+
22
+ # $stderr.puts "Widget:" + widget.inspect
23
+ @builder << widget.to_s
24
+
25
+ # $stderr.puts "Good"
26
+ end
27
+ end
28
+
29
+ module Cuca
30
+
31
+ # == Generator
32
+ # A generator is a mixin to Cuca::Widget. It should provide functions that generate
33
+ # content.
34
+ # Visible within a generator function should be all instance variables, all instance
35
+ # methods and an easy accessor to widgets. For example the view and markaby generators
36
+ # that come with cuca you can call a widget like:
37
+ # Link(a,b,c..) { block}
38
+ # and it will initialize the LinkWidget
39
+ module Generator
40
+
41
+ # == Markaby Generator
42
+ #
43
+ # Markaby Generator provides the mab and mabtext functions to generate content.
44
+ #
45
+ # Usage example within a controller:
46
+ #
47
+ # require 'cuca/generator/markaby'
48
+ # class IndexController < ApplicationController
49
+ # include Cuca::Generator::Markaby
50
+ # def run
51
+ # mab { Link('/to/somewhere') { b { "Click" }}}
52
+ # end
53
+ # end
54
+ #
55
+ # The above will make use of widget 'LinkWidget' (must be defined)
56
+ #
57
+ # For more information of Markaby pls see the markaby website.
58
+ #
59
+ # === Performance Warning
60
+ #
61
+ # Unfortunately Markaby is not famous to be fast. Using it on recuring widgets
62
+ # can significantly slow down your application.
63
+ #
64
+ #
65
+ module Markaby
66
+ # use this to add markaby code to @content
67
+ def mab(&block)
68
+ @_content << ::Markaby::Builder.new(get_assigns, self, &block).to_s
69
+ end
70
+
71
+ # Use this to generate html code with a markaby block and have it as a string
72
+ def mabtext(&block)
73
+ ::Markaby::Builder.new(get_assigns, self, &block).to_s
74
+ end
75
+
76
+ end
77
+
78
+ end # Module Generator
79
+ end # Module Cuca
80
+
@@ -0,0 +1,121 @@
1
+ require 'erb'
2
+
3
+
4
+ module Cuca
5
+ module Generator
6
+
7
+ # == View Generator
8
+ #
9
+ # The view generator allows you to define content using an ERB template - similar to
10
+ # Ruby on Rails.
11
+ #
12
+ # Example use within a Controller:
13
+ #
14
+ # require 'cuca/generator/view'
15
+ # class IndexController
16
+ # include Cuca::Generator::View
17
+ #
18
+ # def run
19
+ # @some_variable = "Stuff"
20
+ # @page_title = "Hello World"
21
+ # view('template.rhtml')
22
+ # end
23
+ # end
24
+ #
25
+ # And the template (template.rhtml)
26
+ #
27
+ # <html>
28
+ # <head>
29
+ # <title><%= @page_title %></title>
30
+ # </head>
31
+ # <body>
32
+ # <% (1..10).each do |idx| %> <!-- Embedded Ruby Code ->
33
+ # <%= idx.to_s %> - <b>Some variable: <%= @stuff %></b><br/>
34
+ # <% end %>
35
+ # An external Widget: <%= Link('/to/somewhere') { b { "Click me" }} %>
36
+ # </body>
37
+ # </html>
38
+ #
39
+ # For more information about ERB templates visit it's website.
40
+ #
41
+ module View
42
+
43
+ class AssignBindings # :nodoc:
44
+ def get_bindings
45
+ binding
46
+ end
47
+
48
+ def initialize(assigns, base_object)
49
+ assigns.each_pair do |k,v|
50
+ instance_variable_set("@#{k}", v)
51
+ end
52
+ @base = base_object
53
+ end
54
+
55
+ def method_missing(sym, *args, &block )
56
+ class_name = sym.id2name
57
+
58
+ begin
59
+ # 1st try to find method in the base widget
60
+ if @base.methods.include?(class_name) then
61
+ return @base.send(class_name, *args, &block)
62
+ end
63
+ # 2nd try to find a widget
64
+ c=Object::const_get(class_name+"Widget")
65
+ rescue NameError => e
66
+ raise "Undefined method: #{sym.id2name}"
67
+ end
68
+
69
+ widget = c.new({:args => args,
70
+ :assigns => @assigns },
71
+ &block)
72
+
73
+ # $stderr.puts "Widget:" + widget.inspect
74
+ return widget.to_s
75
+
76
+ # $stderr.puts "Good"
77
+ end
78
+ end
79
+
80
+
81
+ # VIEW_DIR = $cuca_path+'app/_views'
82
+
83
+
84
+ # Procuce content by a template file.
85
+ # This will return the generated markup as a string
86
+ def viewtext(filename=nil)
87
+ view_dir = $cuca_path + '/' + App::config['view_directory']
88
+ begin
89
+ f = File.open(VIEW_DIR + "/#{filename}", 'r')
90
+ rescue => e
91
+ return "Error opening template: #{e}"
92
+ end
93
+
94
+ template = f.read
95
+ f.close
96
+
97
+ viewtext_p(template)
98
+ end
99
+
100
+
101
+ # Procuce content and append to widget.
102
+ def view(filename)
103
+ @_content << viewtext(filename)
104
+ end
105
+
106
+ # Normally you have your view (the template) within a separate file. Nevertheless
107
+ # you can passing as a string to this function.
108
+ def viewtext_p(template)
109
+ ERB.new(template).result(AssignBindings.new(get_assigns, self).get_bindings)
110
+ end
111
+
112
+ # Equivaltent to view but take template as a string.
113
+ def view_p(template)
114
+ @_content << viewtext_p(template)
115
+ end
116
+
117
+ end
118
+
119
+ end # Mod: Generator
120
+ end # Mod: Cuca
121
+
@@ -0,0 +1,62 @@
1
+ module Cuca
2
+
3
+ # === Layout
4
+ # A Layout just behaves as a normal widget plus it will give you the @content_for_layout
5
+ # instance variable with the content generated from the controller.
6
+ #
7
+ # == Naming
8
+ # Name it FilenameLayout (ending always with Layout, for example: 'StandardLayout' or 'FancyLayout').
9
+ # When you specify your layout in the controller simply do a
10
+ # layout 'standard'
11
+ #
12
+ # == Examples
13
+ # Layout Class:
14
+ #
15
+ # class PlainLayout < Cuca::Layout
16
+ #
17
+ # def output
18
+ # content << <<-EOI
19
+ # <html>
20
+ # <head><title>#{@page_title}</title></head>
21
+ # <body>
22
+ # #{@content_for_layout}
23
+ # <hr>
24
+ # <small>Rendered using the Plain Layout - at #{Time.new.to_s}</small>
25
+ # </body>
26
+ # </html>
27
+ # EOI
28
+ # end
29
+ # end
30
+ #
31
+ #
32
+ # Example Controller that would work with the above layout:
33
+ #
34
+ # class IndexController < Cuca::Controller
35
+ # layout 'plain'
36
+ #
37
+ # def run
38
+ # @page_title = "Main Page"
39
+ # content << "<h3>Welcome to my Webpage</h3>
40
+ # end
41
+ # end
42
+ #
43
+ # Note: The above example doesn't make use of a generator - which would simplify the development of
44
+ # larger layouts and controllers.
45
+ class Layout < Widget
46
+
47
+ # the controller will create the layout. The controller will also set the content_for_layout
48
+ # assign besides other assigns from the controller.
49
+ def initialize(params = {}, &block)
50
+ params[:assigns].each_pair do |k,v|
51
+ instance_variable_set("@#{k.to_s}", v)
52
+ end
53
+ super
54
+ end
55
+
56
+ def to_s
57
+ output
58
+ return content.to_s
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,89 @@
1
+ module Cuca
2
+
3
+ #
4
+ # MimeTypes is a self-writing hash.
5
+ # Will take the data of the mime.types file
6
+ # key is the file extension.
7
+ #
8
+ # MimeTypes.new['avi'] = > video/x-msvideo
9
+ #class MimeTypes < Hash
10
+ #
11
+ # def initialize(fn = '/etc/mime.types')
12
+ #
13
+ # f = File.new(fn, 'r') or throw StandardError("Can't open #{fn}")
14
+ # while (line = f.readline) do
15
+ # line = line.chomp
16
+ # next if line.length == 0
17
+ # next if line[0] == '#'[0]
18
+ # ls = line.scan(/[a-zA-Z\-\/0-9]+/)
19
+ # next if line.size == 0
20
+ # ls[1..-1].each { |e| self[e] = ls[0] }
21
+ # end
22
+ # f.close
23
+ #
24
+ # rescue EOFError
25
+ # f.close
26
+ # end
27
+ # end
28
+
29
+ class MimeTypes < Hash # :nodoc:
30
+ def initialize
31
+ super
32
+ {"rpm" => "application/x-rpm",
33
+ "pdf" => "application/pdf",
34
+ "sig" => "application/pgp-signature",
35
+ "spl" => "application/futuresplash",
36
+ "class" => "application/octet-stream",
37
+ "ps" => "application/postscript",
38
+ "torrent" => "application/x-bittorrent",
39
+ "dvi" => "application/x-dvi",
40
+ "gz" => "application/x-gzip",
41
+ "pac" => "application/x-ns-proxy-autoconfig",
42
+ "swf" => "application/x-shockwave-flash",
43
+ "tar.gz" => "application/x-tgz",
44
+ "tgz" => "application/x-tgz",
45
+ "tar" => "application/x-tar",
46
+ "zip" => "application/zip",
47
+ "mp3" => "audio/mpeg",
48
+ "m3u" => "audio/x-mpegurl",
49
+ "wma" => "audio/x-ms-wma",
50
+ "wax" => "audio/x-ms-wax",
51
+ "ogg" => "audio/x-wav",
52
+ "wav" => "audio/x-wav",
53
+ "gif" => "image/gif",
54
+ "jpg" => "image/jpeg",
55
+ "jpeg" => "image/jpeg",
56
+ "png" => "image/png",
57
+ "xbm" => "image/x-xbitmap",
58
+ "xpm" => "image/x-xpixmap",
59
+ "xwd" => "image/x-xwindowdump",
60
+ "css" => "text/css",
61
+ "html" => "text/html",
62
+ "htm" => "text/html",
63
+ "js" => "text/javascript",
64
+ "asc" => "text/plain",
65
+ "c" => "text/plain",
66
+ "conf" => "text/plain",
67
+ "text" => "text/plain",
68
+ "txt" => "text/plain",
69
+ "dtd" => "text/xml",
70
+ "xml" => "text/xml",
71
+ "mpeg" => "video/mpeg",
72
+ "mpg" => "video/mpeg",
73
+ "mov" => "video/quicktime",
74
+ "qt" => "video/quicktime",
75
+ "avi" => "video/x-msvideo",
76
+ "asf" => "video/x-ms-asf",
77
+ "asx" => "video/x-ms-asf",
78
+ "wmv" => "video/x-ms-wmv",
79
+ "bz2" => "application/x-bzip",
80
+ "tbz" => "application/x-bzip-compressed-tar",
81
+ "tar.bz2" => "application/x-bzip-compressed-tar"}.each_pair { |k,v| self[k] = v }
82
+ end
83
+ end
84
+
85
+
86
+ end
87
+
88
+ # puts Cuca::MimeTypes.new['avi']
89
+
@@ -0,0 +1,143 @@
1
+
2
+ require 'cgi/session'
3
+ require 'cgi/session/pstore'
4
+
5
+ require 'cuca/app'
6
+ require 'cuca/widget'
7
+ require 'cuca/sessionflash'
8
+ require 'cuca/sessionpage'
9
+
10
+ module Cuca
11
+
12
+
13
+ # == Description
14
+ # Session can be used to store stateful data. It is not loaded by default, to make
15
+ # use of it you must require this module and tell a controller to use a session.
16
+ #
17
+ # == Example Use (permanent data)
18
+ #
19
+ # Initialize (using a controller):
20
+ #
21
+ # class ApplicationController < Cuca::Controller
22
+ # use_session
23
+ # end
24
+ #
25
+ # Save and Load data (from any widgets e.g. controller):
26
+ #
27
+ # class IndexController < ApplicationController
28
+ #
29
+ # def run
30
+ # session[:stuff_to_remember] = "hello world"
31
+ # @stuff = session[:stuff_to_remember]
32
+ # end
33
+ # end
34
+ #
35
+ # == Flash Memory
36
+ #
37
+ # The flash memory can be used to store temporarily data for the current and
38
+ # next action. A typical example are messages after a post event, like:
39
+ #
40
+ # class LoginController < ApplicationController
41
+ # (...)
42
+ # def post
43
+ # if (params['username'] == 'root' && params['pass'] == 'stuff') then
44
+ # session.flash[:message] = "You are logged in"
45
+ # session[:username] = 'root'
46
+ # stop :redirect => 'index'
47
+ # end
48
+ # end
49
+ # end
50
+ #
51
+ # If you want to keep the flash memory for another cycle you can call:
52
+ #
53
+ # session.flash.keep
54
+ #
55
+ #
56
+ # == Page Memory
57
+ #
58
+ # Page memory is a container to store data only valid for the current action.
59
+ # It will be erased once you leave to a different action.
60
+ #
61
+ #
62
+ #
63
+ # == Configuration
64
+ #
65
+ # Session is using some values from App::Config :
66
+ #
67
+ # 'session_prefix'
68
+ # 'session_valid'
69
+ # 'session_key'
70
+ #
71
+ class Session
72
+ attr_reader :flash
73
+ attr_reader :page
74
+
75
+ private
76
+ def make_session
77
+ @sess = CGI::Session.new(@cgi, @session_parameters)
78
+ end
79
+
80
+ public
81
+ def reset
82
+ begin
83
+ @sess.delete
84
+ rescue
85
+ end
86
+ make_session
87
+ end
88
+
89
+ # returns true/false if a session exists
90
+ def exists?
91
+ begin
92
+ p = @parameters.clone
93
+ p['new_session'] = false
94
+ session = CGI::Session.new(cgi, p)
95
+ rescue ArgumentError
96
+ return false
97
+ end
98
+ return true
99
+ end
100
+
101
+ def initialize(cgi)
102
+ @cgi = cgi
103
+
104
+ @session_parameters = {
105
+ 'database_manager' => CGI::Session::PStore,
106
+ 'session_key' => App::config["session_key"],
107
+ 'session_path' => '/',
108
+ 'session_expires' => Time.now + App::config["session_valid"].to_i,
109
+ 'prefix' => App::config["session_prefix"] }
110
+
111
+ make_session
112
+
113
+ @flash = SessionFlash.new(self)
114
+ @page = SessionPage.new(self)
115
+ end
116
+
117
+ def []=(key, value)
118
+ @sess[key] = value
119
+ end
120
+
121
+ def [](key)
122
+ return @sess[key]
123
+ end
124
+
125
+ def close
126
+ @sess.close
127
+ end
128
+
129
+ end
130
+
131
+ class Widget
132
+ def self.use_session
133
+ @@session ||= Session.new($cgi)
134
+ end
135
+ def session
136
+ @@session
137
+ end
138
+ end
139
+
140
+
141
+
142
+ end
143
+
@@ -0,0 +1,56 @@
1
+ module Cuca
2
+
3
+ # Whatever you write into flash will be valid for the current and for the
4
+ # next action. You can keep the content for another cycle by calling the
5
+ # keep method. Access via session.flash. (See Cuca::Session)
6
+ class SessionFlash
7
+ class SessionFlashItem # :nodoc:
8
+ def value
9
+ @value
10
+ end
11
+ def initialize(val)
12
+ @value = val
13
+ @cyc = 0
14
+ end
15
+ def inc
16
+ @cyc+=1
17
+ end
18
+ def expired?
19
+ @cyc > 1
20
+ end
21
+ def keep
22
+ @cyc=@cyc-1
23
+ end
24
+ end
25
+
26
+ private
27
+ def flashmem
28
+ @ses[:SessionFlash]
29
+ end
30
+
31
+ public
32
+ def initialize(session)
33
+ @ses = session
34
+ @ses[:SessionFlash] ||= {}
35
+ expire
36
+ end
37
+
38
+ def [](key)
39
+ flashmem[key] ? flashmem[key].value : nil
40
+ end
41
+
42
+ def []=(key, value)
43
+ flashmem[key] = SessionFlashItem.new(value)
44
+ end
45
+
46
+ def keep
47
+ flashmem.each_pair { |k,v| v.keep }
48
+ end
49
+
50
+ private
51
+ def expire
52
+ flashmem.each_pair { |k,v| v.inc; flashmem.delete(k) if v.expired? }
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,41 @@
1
+ module Cuca
2
+
3
+ # A session page (access via session.page) is memory that is only valid
4
+ # for the current action. Once you leave to another page it will
5
+ # be erased. (see Cuca::Session)
6
+ class SessionPage
7
+ private
8
+ def pagekey
9
+ "Pk_#{$app.urlmap.script.gsub(/[\/\\]/, '_')}".intern
10
+ end
11
+
12
+ def pagemem
13
+ @ses[:SessionPage]
14
+ end
15
+
16
+
17
+ public
18
+ def initialize(session)
19
+ @ses = session
20
+ @ses[:SessionPage] ||= {}
21
+ pagemem[pagekey] ||= {}
22
+ expire
23
+ end
24
+
25
+ def [](key)
26
+ pagemem[pagekey][key] ? pagemem[pagekey][key] : nil
27
+ end
28
+
29
+ def []=(key,value)
30
+ pagemem[pagekey][key] = value
31
+ end
32
+
33
+ private
34
+ def expire
35
+ pagemem.each_pair do |k,v|
36
+ pagemem.delete(k) if k != pagekey
37
+ end
38
+ end
39
+ end
40
+
41
+ end