dryml 1.1.0.pre0

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.
@@ -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