cuca 0.01

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 (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