utopia 0.9.17

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