utopia 0.9.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/ext/utopia/xnode/fast_scanner/extconf.rb +6 -0
  2. data/ext/utopia/xnode/fast_scanner/parser.c +289 -0
  3. data/lib/utopia.rb +2 -0
  4. data/lib/utopia/etanni.rb +96 -0
  5. data/lib/utopia/extensions.rb +87 -0
  6. data/lib/utopia/link.rb +243 -0
  7. data/lib/utopia/middleware.rb +33 -0
  8. data/lib/utopia/middleware/all.rb +24 -0
  9. data/lib/utopia/middleware/benchmark.rb +47 -0
  10. data/lib/utopia/middleware/content.rb +139 -0
  11. data/lib/utopia/middleware/content/node.rb +363 -0
  12. data/lib/utopia/middleware/controller.rb +198 -0
  13. data/lib/utopia/middleware/directory_index.rb +54 -0
  14. data/lib/utopia/middleware/localization.rb +94 -0
  15. data/lib/utopia/middleware/localization/name.rb +64 -0
  16. data/lib/utopia/middleware/logger.rb +68 -0
  17. data/lib/utopia/middleware/redirector.rb +171 -0
  18. data/lib/utopia/middleware/requester.rb +116 -0
  19. data/lib/utopia/middleware/static.rb +186 -0
  20. data/lib/utopia/path.rb +193 -0
  21. data/lib/utopia/response_helper.rb +22 -0
  22. data/lib/utopia/session/encrypted_cookie.rb +115 -0
  23. data/lib/utopia/tag.rb +84 -0
  24. data/lib/utopia/tags.rb +32 -0
  25. data/lib/utopia/tags/all.rb +25 -0
  26. data/lib/utopia/tags/env.rb +24 -0
  27. data/lib/utopia/tags/fortune.rb +20 -0
  28. data/lib/utopia/tags/gallery.rb +175 -0
  29. data/lib/utopia/tags/google_analytics.rb +37 -0
  30. data/lib/utopia/tags/node.rb +24 -0
  31. data/lib/utopia/tags/override.rb +28 -0
  32. data/lib/utopia/time_store.rb +102 -0
  33. data/lib/utopia/version.rb +24 -0
  34. data/lib/utopia/xnode.rb +17 -0
  35. data/lib/utopia/xnode/processor.rb +97 -0
  36. data/lib/utopia/xnode/scanner.rb +153 -0
  37. metadata +168 -0
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module Rack
17
+ class Response
18
+ def self.create(response, &block)
19
+ self.new(response[2], response[0], response[1], &block)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,115 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'openssl'
17
+ require 'digest/sha2'
18
+
19
+ module Utopia
20
+ module Session
21
+
22
+ class EncryptedCookie
23
+ RACK_SESSION = "rack.session"
24
+ RACK_SESSION_OPTIONS = "rack.session.options"
25
+
26
+ def initialize(app, options={})
27
+ @app = app
28
+ @cookie = options[:cookie] || (RACK_SESSION + ".encrypted")
29
+ @secret = Digest::SHA256.digest(options[:secret])
30
+
31
+ @default_options = {
32
+ :domain => nil,
33
+ :path => "/",
34
+ :expires_after => nil
35
+ }.merge(options)
36
+ end
37
+
38
+ def call(env)
39
+ original_session = load_session(env).dup
40
+
41
+ status, headers, body = @app.call(env)
42
+
43
+ if original_session != env[RACK_SESSION]
44
+ commit_session(env, status, headers, body)
45
+ end
46
+
47
+ return [status, headers, body]
48
+ end
49
+
50
+ private
51
+
52
+ def load_session(env)
53
+ session = {}
54
+
55
+ request = Rack::Request.new(env)
56
+ data = request.cookies[@cookie]
57
+
58
+ if data
59
+ session = decrypt(data) rescue session
60
+ end
61
+
62
+ env[RACK_SESSION] = session
63
+ env[RACK_SESSION_OPTIONS] = @default_options.dup
64
+
65
+ return session
66
+ end
67
+
68
+ def commit_session(env, status, headers, body)
69
+ session = env[RACK_SESSION]
70
+
71
+ data = encrypt(session)
72
+
73
+ if data.size > (1024 * 4)
74
+ env["rack.errors"].puts "Error: #{self.class.name} data exceeds 4K. Content Dropped!"
75
+ else
76
+ options = env[RACK_SESSION_OPTIONS]
77
+ cookie = {:value => data}
78
+ cookie[:expires] = Time.now + options[:expires_after] unless options[:expires_after].nil?
79
+
80
+ Rack::Utils.set_cookie_header!(headers, @cookie, cookie.merge(options))
81
+ end
82
+ end
83
+
84
+ def encrypt(hash)
85
+ c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
86
+ c.encrypt
87
+
88
+ # your pass is what is used to encrypt/decrypt
89
+ c.key = @secret
90
+ c.iv = iv = c.random_iv
91
+
92
+ e = c.update(Marshal.dump(hash))
93
+ e << c.final
94
+
95
+ return [iv, e].pack("m16m*")
96
+ end
97
+
98
+ def decrypt(data)
99
+ iv, e = data.unpack("m16m*")
100
+
101
+ c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
102
+ c.decrypt
103
+
104
+ c.key = @secret
105
+ c.iv = iv
106
+
107
+ d = c.update(e)
108
+ d << c.final
109
+
110
+ return Marshal.load(d)
111
+ end
112
+ end
113
+
114
+ end
115
+ end
data/lib/utopia/tag.rb ADDED
@@ -0,0 +1,84 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module Utopia
17
+
18
+ class Tag
19
+ def initialize(name, attributes = {})
20
+ @name = name
21
+ @attributes = attributes
22
+ @closed = false
23
+ end
24
+
25
+ attr :name
26
+ attr :attributes
27
+ attr :closed, true
28
+
29
+ def [](key)
30
+ @attributes[key]
31
+ end
32
+
33
+ def append(text)
34
+ @content ||= StringIO.new
35
+ @content.write text
36
+ end
37
+
38
+ def to_html(content = nil, buf = StringIO.new)
39
+ write_full_html(buf, content)
40
+
41
+ return buf.string
42
+ end
43
+
44
+ def to_hash
45
+ @attributes
46
+ end
47
+
48
+ def to_s
49
+ buf = StringIO.new
50
+ write_open_html(buf)
51
+ return buf.string
52
+ end
53
+
54
+ def write_open_html(buf, terminate = false)
55
+ buf ||= StringIO.new
56
+ buf.write "<#{name}"
57
+
58
+ @attributes.each do |key, value|
59
+ buf.write " #{key}=\"#{value}\""
60
+ end
61
+
62
+ if terminate
63
+ buf.write "/>"
64
+ else
65
+ buf.write ">"
66
+ end
67
+ end
68
+
69
+ def write_close_html(buf)
70
+ buf.write "</#{name}>"
71
+ end
72
+
73
+ def write_full_html(buf, content = nil)
74
+ if @closed && content == nil
75
+ write_open_html(buf, true)
76
+ else
77
+ write_open_html(buf)
78
+ buf.write(content)
79
+ write_close_html(buf)
80
+ end
81
+ end
82
+ end
83
+
84
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module Utopia
17
+ module Tags
18
+ @@all = {}
19
+
20
+ def self.register(name, tag)
21
+ @@all[name] = tag
22
+ end
23
+
24
+ def self.create(name, &block)
25
+ @@all[name] = Proc.new(&block)
26
+ end
27
+
28
+ def self.all
29
+ @@all
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'pathname'
17
+
18
+ Pathname.new(__FILE__).dirname.entries.grep(/\.rb$/).each do |path|
19
+ name = File.basename(path.to_s, ".rb")
20
+
21
+ if name != "all"
22
+ require "utopia/tags/#{name}"
23
+ end
24
+ end
25
+
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'utopia/tags'
17
+
18
+ Utopia::Tags.create("env") do |transaction, state|
19
+ only = state[:only].split(",").collect(&:to_sym) rescue []
20
+
21
+ if defined?(UTOPIA_ENV) && only.include?(UTOPIA_ENV)
22
+ transaction.parse_xml(state.content)
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'utopia/tags'
17
+
18
+ Utopia::Tags.create("fortune") do |transaction, state|
19
+ "<pre>#{`fortune`.to_html}</pre>"
20
+ end
@@ -0,0 +1,175 @@
1
+ # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'utopia/tags'
17
+
18
+ require 'RMagick'
19
+ require 'fileutils'
20
+
21
+ class Utopia::Tags::Gallery
22
+ PROCESSES = {
23
+ :photo_thumbnail => lambda do |img|
24
+ img = img.resize_to_fit(300, 300)
25
+
26
+ shadow = img.flop
27
+ shadow = shadow.colorize(1, 1, 1, "gray50")
28
+ shadow.background_color = "white"
29
+ shadow.border!(10, 10, "white")
30
+ shadow = shadow.blur_image(0, 5)
31
+
32
+ shadow.composite(img, 5, 5, Magick::OverCompositeOp)
33
+ end,
34
+ :thumbnail => lambda do |img|
35
+ img = img.resize_to_fit(300, 300)
36
+ end,
37
+ :large => lambda{|img| img.resize_to_fit(768, 768)}
38
+ }
39
+
40
+ CACHE_DIR = "_cache"
41
+
42
+ class ImagePath
43
+ def initialize(original_path)
44
+ @original_path = original_path
45
+ @cache_root = @original_path.dirname + CACHE_DIR
46
+ end
47
+
48
+ attr :cache_root
49
+
50
+ def original
51
+ @original_path
52
+ end
53
+
54
+ def self.append_suffix(name, suffix)
55
+ name.split(".").insert(-2, suffix).join(".")
56
+ end
57
+
58
+ def processed(process = nil)
59
+ if process
60
+ name = @original_path.basename
61
+ return cache_root + ImagePath.append_suffix(name, process.to_s)
62
+ else
63
+ return @original_path
64
+ end
65
+ end
66
+
67
+ def to_html(process = nil)
68
+ Tag.new("img", {"src" => path(process)}).to_html
69
+ end
70
+
71
+ def to_s
72
+ @original_path.to_s
73
+ end
74
+
75
+ def method_missing(name, *args)
76
+ return processed(name.to_s)
77
+ end
78
+ end
79
+
80
+ def initialize(node, path)
81
+ @node = node
82
+ @path = path
83
+
84
+ Utopia::LOG.debug("node: #{node.inspect} path: #{path}")
85
+ end
86
+
87
+ def metadata
88
+ metadata_path = @node.local_path(@path + "gallery.yaml")
89
+
90
+ if File.exist? metadata_path
91
+ return YAML::load(File.read(metadata_path))
92
+ else
93
+ return {}
94
+ end
95
+ end
96
+
97
+ def images(options = {})
98
+ options[:filter] ||= /(\.jpg|\.png)$/
99
+
100
+ paths = []
101
+ local_path = @node.local_path(@path)
102
+
103
+ Utopia::LOG.debug("Scanning #{local_path}")
104
+
105
+ Dir.entries(local_path).each do |filename|
106
+ next unless filename.match(options[:filter])
107
+
108
+ Utopia::LOG.debug("Filename #{filename} matched filter...")
109
+
110
+ fullpath = File.join(local_path, filename)
111
+
112
+ paths << ImagePath.new(@path + filename)
113
+ end
114
+
115
+ if options[:process]
116
+ paths.each do |path|
117
+ processed_image(path, options[:process])
118
+ end
119
+ end
120
+
121
+ return paths
122
+ end
123
+
124
+ def processed_image(image_path, processes)
125
+ # Create the local cache directory if it doesn't exist already
126
+ local_cache_path = @node.local_path(image_path.cache_root)
127
+
128
+ unless File.exist? local_cache_path
129
+ FileUtils.mkdir local_cache_path
130
+ end
131
+
132
+ # Calculate the new name for the processed image
133
+ local_original_path = @node.local_path(image_path.original)
134
+
135
+ if processes.kind_of? String
136
+ processes = processes.split(",")
137
+ end
138
+
139
+ processes.each do |process|
140
+ local_processed_path = @node.local_path(image_path.processed(process))
141
+
142
+ unless File.exists? local_processed_path
143
+ image = Magick::ImageList.new(local_original_path)
144
+
145
+ processed_image = PROCESSES[process.to_sym].call(image)
146
+ processed_image.write(local_processed_path)
147
+ end
148
+ end
149
+ end
150
+
151
+ def self.call(transaction, state)
152
+ gallery = new(transaction.end_tags[-2].node, Utopia::Path.create(state["path"] || "./"))
153
+ metadata = gallery.metadata
154
+ metadata.default = {}
155
+
156
+ tag_name = state["tag"] || "img"
157
+
158
+ options = {}
159
+ options[:process] = state["process"]
160
+
161
+ transaction.tag("div", "class" => "gallery") do |node|
162
+ images = gallery.images(options).sort_by do |path|
163
+ name = path.original.basename
164
+ metadata[name]["order"] || name
165
+ end
166
+
167
+ images.each do |path|
168
+ alt_text = metadata[path.original.basename]["caption"]
169
+ transaction.tag(tag_name, "src" => path, "alt" => alt_text)
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ Utopia::Tags.register("gallery", Utopia::Tags::Gallery)