dryml 1.1.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,133 @@
1
+ module Dryml
2
+
3
+ # Raised when the part context fails its integrity check.
4
+ class PartContext
5
+
6
+ class TamperedWithPartContext < StandardError; end
7
+
8
+ class TypedId < String; end
9
+
10
+ class << self
11
+ attr_accessor :secret, :digest
12
+ end
13
+ self.digest = 'SHA1'
14
+
15
+
16
+ def self.client_side_storage(contexts, session)
17
+ return "" if contexts.empty?
18
+
19
+ contexts.map do |dom_id, context|
20
+ code = context.marshal(session).split("\n").map{|line| "'#{line}\\n'"}.join(" +\n ")
21
+ "hoboParts['#{dom_id}'] = (#{code});\n"
22
+ end.join
23
+ end
24
+
25
+
26
+ def self.pre_marshal(x)
27
+ if x.is_a?(ActiveRecord::Base) && x.respond_to?(:typed_id)
28
+ TypedId.new(x.typed_id)
29
+ else
30
+ x
31
+ end
32
+ end
33
+
34
+
35
+ def self.for_call(part_name, environment, locals)
36
+ new do |c|
37
+ c.part_name = part_name
38
+ c.locals = locals.map { |l| pre_marshal(l) }
39
+ c.this_id = environment.typed_id
40
+ c.form_field_path = environment.form_field_path
41
+ end
42
+ end
43
+
44
+
45
+ def self.for_refresh(encoded_context, page_this, session)
46
+ new do |c|
47
+ c.unmarshal(encoded_context, page_this, session)
48
+ end
49
+ end
50
+
51
+
52
+ def initialize
53
+ yield self
54
+ end
55
+
56
+ attr_accessor :part_name, :locals, :this, :this_field, :this_id, :form_field_path
57
+
58
+
59
+ def marshal(session)
60
+ context = [@part_name, @this_id, @locals]
61
+ context << form_field_path if form_field_path
62
+ data = Base64.encode64(Marshal.dump(context)).strip
63
+ digest = generate_digest(data, session)
64
+ "#{data}--#{digest}"
65
+ end
66
+
67
+
68
+ # Unmarshal part context to a hash and verify its integrity.
69
+ def unmarshal(client_store, page_this, session)
70
+ data, digest = CGI.unescape(client_store).strip.split('--')
71
+
72
+ raise TamperedWithPartContext unless digest == generate_digest(data, session)
73
+
74
+ context = Marshal.load(Base64.decode64(data))
75
+
76
+ part_name, this_id, locals, form_field_path = context
77
+
78
+ if RAILS_DEFAULT_LOGGER
79
+ RAILS_DEFAULT_LOGGER.info "Call part: #{part_name}. this-id = #{this_id}, locals = #{locals.inspect}"
80
+ RAILS_DEFAULT_LOGGER.info " : form_field_path = #{form_field_path.inspect}" if form_field_path
81
+ end
82
+
83
+ self.part_name = part_name
84
+ self.this_id = this_id
85
+ self.locals = restore_locals(locals)
86
+ self.form_field_path = form_field_path
87
+
88
+ parse_this_id(page_this)
89
+ end
90
+
91
+
92
+ # Generate the HMAC keyed message digest. Uses SHA1 by default.
93
+ def generate_digest(data, session)
94
+ secret = self.class.secret || ActionController::Base.session_options[:secret] || ActionController::Base.cached_session_options.first[:secret]
95
+ key = secret.respond_to?(:call) ? secret.call(session) : secret
96
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(self.class.digest), key, data)
97
+ end
98
+
99
+
100
+
101
+ def parse_this_id(page_this)
102
+ if this_id == "this"
103
+ self.this = page_this
104
+ elsif this_id =~ /^this:(.*)/
105
+ self.this = page_this
106
+ self.this_field = $1
107
+ elsif this_id == "nil"
108
+ nil
109
+ else
110
+ parts = this_id.split(':')
111
+ if parts.length == 3
112
+ self.this = Hobo::Model.find_by_typed_id("#{parts[0]}:#{parts[1]}")
113
+ self.this_field = parts[2]
114
+ else
115
+ self.this = Hobo::Model.find_by_typed_id(this_id)
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+ def restore_locals(locals)
122
+ locals.map do |l|
123
+ if l.is_a?(TypedId)
124
+ Hobo::Model.find_by_typed_id(this_id)
125
+ else
126
+ l
127
+ end
128
+ end
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -0,0 +1,42 @@
1
+ module Dryml
2
+
3
+ class ScopedVariables
4
+
5
+ def initialize(variables=nil)
6
+ @scopes = variables ? [variables] : []
7
+ end
8
+
9
+ def [](key)
10
+ s = scope_with_key(key) and s[key]
11
+ end
12
+
13
+ def []=(key, val)
14
+ s = scope_with_key(key) or raise ArgumentError, "no such scoped variable: #{key}"
15
+ s[key] = val
16
+ end
17
+
18
+ def new_scope(variables)
19
+ @scopes << variables.dup
20
+ res = yield
21
+ @scopes.pop
22
+ res
23
+ end
24
+
25
+ def scope_with_key(key)
26
+ @scopes.reverse_each do |s|
27
+ return s if s.has_key?(key)
28
+ end
29
+ nil
30
+ end
31
+
32
+ def method_missing(name, *args)
33
+ if name.to_s =~ /=$/
34
+ self[name.to_s[0..-2].to_sym] = args.first
35
+ else
36
+ self[name]
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,98 @@
1
+ abbr
2
+ acronym
3
+ address
4
+ applet
5
+ article
6
+ audio
7
+ b
8
+ basefont
9
+ bdo
10
+ big
11
+ blockquote
12
+ body
13
+ button
14
+ canvas
15
+ caption
16
+ center
17
+ cite
18
+ code
19
+ colgroup
20
+ command
21
+ datagrid
22
+ datalist
23
+ dd
24
+ del
25
+ details
26
+ dfn
27
+ dialog
28
+ dir
29
+ div
30
+ dl
31
+ dt
32
+ em
33
+ embed
34
+ fieldset
35
+ figure
36
+ font
37
+ frameset
38
+ h1
39
+ h2
40
+ h3
41
+ h4
42
+ h5
43
+ h6
44
+ head
45
+ hgroup
46
+ i
47
+ iframe
48
+ ins
49
+ isindex
50
+ kbd
51
+ label
52
+ legend
53
+ li
54
+ map
55
+ mark
56
+ menu
57
+ meter
58
+ nav
59
+ noframes
60
+ noscript
61
+ object
62
+ ol
63
+ optgroup
64
+ option
65
+ output
66
+ p
67
+ pre
68
+ progress
69
+ q
70
+ rp
71
+ rt
72
+ ruby
73
+ s
74
+ samp
75
+ script
76
+ select
77
+ small
78
+ source
79
+ span
80
+ strike
81
+ strong
82
+ style
83
+ sub
84
+ sup
85
+ tbody
86
+ td
87
+ textarea
88
+ tfoot
89
+ th
90
+ thead
91
+ time
92
+ title
93
+ tr
94
+ tt
95
+ u
96
+ ul
97
+ var
98
+ video
@@ -0,0 +1,32 @@
1
+ module Dryml
2
+
3
+ class NoParameterError < RuntimeError; end
4
+
5
+ class TagParameters < Hash
6
+
7
+ def initialize(parameters, exclude_names=nil)
8
+ if exclude_names.blank?
9
+ update(parameters)
10
+ else
11
+ parameters.each_pair { |k, v| self[k] = v unless k.in?(exclude_names) }
12
+ end
13
+ end
14
+
15
+ def method_missing(name, default_content="")
16
+ if name.to_s =~ /\?$/
17
+ has_key?(name.to_s[0..-2].to_sym)
18
+ else
19
+ self[name]._?.call(default_content) || ""
20
+ end
21
+ end
22
+
23
+ undef_method :default
24
+
25
+ # Question: does this do anything? -Tom
26
+ def [](param_name)
27
+ fetch(param_name, nil)
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,124 @@
1
+ module Dryml
2
+
3
+ class Taglib
4
+
5
+ @cache = {}
6
+
7
+ class << self
8
+
9
+ def get(options)
10
+ src_file = taglib_filename(options)
11
+ taglib = @cache[src_file]
12
+ if taglib
13
+ taglib.reload
14
+ else
15
+ taglib = Taglib.new(src_file)
16
+ @cache[src_file] = taglib
17
+ end
18
+ taglib
19
+ end
20
+
21
+ def clear_cache
22
+ @cache = {}
23
+ end
24
+
25
+ private
26
+
27
+ def taglib_filename(options)
28
+ plugin = options[:plugin]
29
+ rails_root = Object.const_defined?(:RAILS_ROOT) ? RAILS_ROOT : "."
30
+ base = if plugin == "dryml"
31
+ "#{DRYML_ROOT}/taglibs"
32
+ elsif plugin == "hobo"
33
+ "#{HOBO_ROOT}/taglibs"
34
+ elsif plugin
35
+ "#{rails_root}/vendor/plugins/#{plugin}/taglibs"
36
+ elsif options[:src] =~ /\//
37
+ "#{rails_root}/app/views"
38
+ elsif options[:template_dir] =~ /^#{HOBO_ROOT}/
39
+ options[:template_dir]
40
+ elsif options[:absolute_template_path]
41
+ options[:absolute_template_path]
42
+ else
43
+ "#{rails_root}/#{options[:template_dir].gsub(/^\//, '')}" # remove leading / if there is one
44
+ end
45
+
46
+ src = options[:src] || plugin
47
+ filename = "#{base}/#{src}.dryml"
48
+ raise DrymlException, "No such taglib: #{base} #{options.inspect} #{filename}" unless File.exists?(filename)
49
+ filename
50
+ end
51
+
52
+ end
53
+
54
+ def initialize(src_file)
55
+ @src_file = src_file
56
+ load
57
+ end
58
+
59
+ def reload
60
+ load if File.mtime(@src_file) > @last_load_time
61
+ end
62
+
63
+ def load
64
+ @module = Module.new do
65
+
66
+ @tag_attrs = {}
67
+ @tag_aliases = []
68
+
69
+ class << self
70
+
71
+ def included(base)
72
+ @tag_aliases.each do |tag, feature|
73
+ if base.respond_to? :alias_method_chain_on_include
74
+ base.alias_method_chain_on_include tag, feature
75
+ else
76
+ base.send(:alias_method_chain, tag, feature)
77
+ end
78
+ end
79
+ end
80
+
81
+ def _register_tag_attrs(tag, attrs)
82
+ @tag_attrs[tag] = attrs
83
+ end
84
+ attr_reader :tag_attrs
85
+
86
+ def alias_method_chain_on_include(tag, feature)
87
+ @tag_aliases << [tag, feature]
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+ template = Template.new(File.read(@src_file), @module, @src_file)
94
+ template.compile([], [])
95
+ @last_load_time = File.mtime(@src_file)
96
+ end
97
+
98
+ def import_into(class_or_module, as)
99
+ if as
100
+ # Define a method on class_or_module named whatever 'as'
101
+ # is. The first time the method is called it creates and
102
+ # returns an object that provides the taglib's tags as
103
+ # methods. On subsequent calls the object is cached in an
104
+ # instance variable "@_#{as}_taglib"
105
+
106
+ taglib_module = @module
107
+ ivar = "@_#{as}_taglib"
108
+ class_or_module.send(:define_method, as) do
109
+ instance_variable_get(ivar) or begin
110
+ as_class = Class.new(TemplateEnvironment) { include taglib_module }
111
+ as_object = as_class.new
112
+ as_object.copy_instance_variables_from(self)
113
+ instance_variable_set(ivar, as_object)
114
+ end
115
+ end
116
+ else
117
+ class_or_module.send(:include, @module)
118
+ class_or_module.tag_attrs.update(@module.tag_attrs) if @module.respond_to?(:tag_attrs)
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ end