utopia 0.9.17
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/utopia/xnode/fast_scanner/extconf.rb +6 -0
- data/ext/utopia/xnode/fast_scanner/parser.c +289 -0
- data/lib/utopia.rb +2 -0
- data/lib/utopia/etanni.rb +96 -0
- data/lib/utopia/extensions.rb +87 -0
- data/lib/utopia/link.rb +243 -0
- data/lib/utopia/middleware.rb +33 -0
- data/lib/utopia/middleware/all.rb +24 -0
- data/lib/utopia/middleware/benchmark.rb +47 -0
- data/lib/utopia/middleware/content.rb +139 -0
- data/lib/utopia/middleware/content/node.rb +363 -0
- data/lib/utopia/middleware/controller.rb +198 -0
- data/lib/utopia/middleware/directory_index.rb +54 -0
- data/lib/utopia/middleware/localization.rb +94 -0
- data/lib/utopia/middleware/localization/name.rb +64 -0
- data/lib/utopia/middleware/logger.rb +68 -0
- data/lib/utopia/middleware/redirector.rb +171 -0
- data/lib/utopia/middleware/requester.rb +116 -0
- data/lib/utopia/middleware/static.rb +186 -0
- data/lib/utopia/path.rb +193 -0
- data/lib/utopia/response_helper.rb +22 -0
- data/lib/utopia/session/encrypted_cookie.rb +115 -0
- data/lib/utopia/tag.rb +84 -0
- data/lib/utopia/tags.rb +32 -0
- data/lib/utopia/tags/all.rb +25 -0
- data/lib/utopia/tags/env.rb +24 -0
- data/lib/utopia/tags/fortune.rb +20 -0
- data/lib/utopia/tags/gallery.rb +175 -0
- data/lib/utopia/tags/google_analytics.rb +37 -0
- data/lib/utopia/tags/node.rb +24 -0
- data/lib/utopia/tags/override.rb +28 -0
- data/lib/utopia/time_store.rb +102 -0
- data/lib/utopia/version.rb +24 -0
- data/lib/utopia/xnode.rb +17 -0
- data/lib/utopia/xnode/processor.rb +97 -0
- data/lib/utopia/xnode/scanner.rb +153 -0
- 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
|
data/lib/utopia/tags.rb
ADDED
@@ -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)
|