miketracy-wwmd 0.2.11

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 (70) hide show
  1. data/History.txt +3 -0
  2. data/README +62 -0
  3. data/README.txt +62 -0
  4. data/Rakefile +34 -0
  5. data/examples/config_example.yaml +24 -0
  6. data/examples/wwmd_example.rb +73 -0
  7. data/lib/wwmd.rb +78 -0
  8. data/lib/wwmd/encoding.rb +40 -0
  9. data/lib/wwmd/form.rb +110 -0
  10. data/lib/wwmd/form_array.rb +273 -0
  11. data/lib/wwmd/guid.rb +155 -0
  12. data/lib/wwmd/hpricot_html2text.rb +76 -0
  13. data/lib/wwmd/mixins.rb +318 -0
  14. data/lib/wwmd/mixins_extends.rb +188 -0
  15. data/lib/wwmd/mixins_external.rb +18 -0
  16. data/lib/wwmd/nokogiri_html2text.rb +41 -0
  17. data/lib/wwmd/page.rb +414 -0
  18. data/lib/wwmd/page/auth.rb +183 -0
  19. data/lib/wwmd/page/config.rb +44 -0
  20. data/lib/wwmd/page/constants.rb +60 -0
  21. data/lib/wwmd/page/headers.rb +107 -0
  22. data/lib/wwmd/page/inputs.rb +47 -0
  23. data/lib/wwmd/page/irb_helpers.rb +90 -0
  24. data/lib/wwmd/page/scrape.rb +202 -0
  25. data/lib/wwmd/page/spider.rb +127 -0
  26. data/lib/wwmd/page/urlparse.rb +79 -0
  27. data/lib/wwmd/page/utils.rb +30 -0
  28. data/lib/wwmd/viewstate.rb +118 -0
  29. data/lib/wwmd/viewstate/viewstate_class_helpers.rb +35 -0
  30. data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +213 -0
  31. data/lib/wwmd/viewstate/viewstate_from_xml.rb +126 -0
  32. data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
  33. data/lib/wwmd/viewstate/viewstate_utils.rb +157 -0
  34. data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
  35. data/lib/wwmd/viewstate/vs_array.rb +36 -0
  36. data/lib/wwmd/viewstate/vs_binary_serialized.rb +28 -0
  37. data/lib/wwmd/viewstate/vs_hashtable.rb +40 -0
  38. data/lib/wwmd/viewstate/vs_hybrid_dict.rb +40 -0
  39. data/lib/wwmd/viewstate/vs_indexed_string.rb +6 -0
  40. data/lib/wwmd/viewstate/vs_indexed_string_ref.rb +22 -0
  41. data/lib/wwmd/viewstate/vs_int_enum.rb +25 -0
  42. data/lib/wwmd/viewstate/vs_list.rb +32 -0
  43. data/lib/wwmd/viewstate/vs_pair.rb +27 -0
  44. data/lib/wwmd/viewstate/vs_read_types.rb +11 -0
  45. data/lib/wwmd/viewstate/vs_read_value.rb +33 -0
  46. data/lib/wwmd/viewstate/vs_sparse_array.rb +56 -0
  47. data/lib/wwmd/viewstate/vs_string.rb +29 -0
  48. data/lib/wwmd/viewstate/vs_string_array.rb +37 -0
  49. data/lib/wwmd/viewstate/vs_string_formatted.rb +30 -0
  50. data/lib/wwmd/viewstate/vs_triplet.rb +29 -0
  51. data/lib/wwmd/viewstate/vs_type.rb +21 -0
  52. data/lib/wwmd/viewstate/vs_unit.rb +28 -0
  53. data/lib/wwmd/viewstate/vs_value.rb +33 -0
  54. data/spec/README +3 -0
  55. data/spec/form_array.spec +49 -0
  56. data/spec/spider_csrf_test.spec +28 -0
  57. data/spec/urlparse_test.spec +89 -0
  58. data/tasks/ann.rake +80 -0
  59. data/tasks/bones.rake +20 -0
  60. data/tasks/gem.rake +201 -0
  61. data/tasks/git.rake +40 -0
  62. data/tasks/notes.rake +27 -0
  63. data/tasks/post_load.rake +34 -0
  64. data/tasks/rdoc.rake +51 -0
  65. data/tasks/rubyforge.rake +55 -0
  66. data/tasks/setup.rb +292 -0
  67. data/tasks/spec.rake +54 -0
  68. data/tasks/test.rake +40 -0
  69. data/tasks/zentest.rake +36 -0
  70. metadata +164 -0
@@ -0,0 +1,202 @@
1
+ module WWMD
2
+ LINKS_REGEXP = [
3
+ /window\.open\s*\(([^\)]+)/i,
4
+ /open_window\s*\(([^\)]+)/i,
5
+ /window\.location\s*=\s*(['"][^'"]+['"])/i,
6
+ /.*location.href\s*=\s*(['"][^'"]+['"])/i,
7
+ /document.forms.*action\s*=\s*(['"][^'"]+['"])/i,
8
+ /Ajax\.Request\s*\((['"][^'"]+['"])/i,
9
+ ]
10
+
11
+ AJAX_REGEXP = [
12
+ /Ajax\.Request\s*\((['"][^'"]+['"])/i,
13
+ ]
14
+
15
+ SRC_REGEXP = [
16
+ /src=\s*(['"][^'"]+['"])/i
17
+ ]
18
+
19
+ # NOT_URL_CHAR = "[^0-9a-zA-Z\:\/\+\\-\%\#]"
20
+
21
+ class Scrape
22
+
23
+ attr_accessor :debug
24
+ attr_accessor :warn
25
+ attr_accessor :links # links found on page
26
+ attr_accessor :jlinks # links to javascript includes
27
+
28
+ attr_reader :hdoc
29
+
30
+ @debug = false
31
+ @warn = true
32
+
33
+ # create a new scrape object using passed HTML
34
+ def initialize(page='<>')
35
+ @page = page
36
+ @hdoc = HDOC.parse(@page)
37
+ @links = Array.new
38
+ @debug = false
39
+ @warn = true
40
+ end
41
+
42
+ # reset this scrape object (called by WWMD::Page)
43
+ def reset(page)
44
+ @page = page
45
+ @hdoc = HDOC.parse(@page)
46
+ @links = Array.new
47
+ end
48
+
49
+ # scan the passed string for the configured regular expressions
50
+ # and return them as an array
51
+ def urls_from_regexp(content,re,split=0)
52
+ ret = []
53
+ scrape = content.scan(re)
54
+ scrape.each do |url|
55
+ # cheat and take split string(,)[split]
56
+ add = url.to_s.split(',')[split].gsub(/['"]/, '')
57
+ next if (add == '' || add.nil?)
58
+ ret << add
59
+ end
60
+ return ret
61
+ end
62
+
63
+ # xpath search for tags and return the passed attribute
64
+ # urls_from_xpath("//a","href")
65
+ def urls_from_xpath(xpath,attr)
66
+ ret = []
67
+ @hdoc.search(xpath).each do |elem|
68
+ url = elem[attr]
69
+ next if url.empty?
70
+ ret << url.strip
71
+ end
72
+ return ret
73
+ end
74
+
75
+ # <b>NEED</b> to move this to external configuration
76
+ #
77
+ # list of urls we don't care to store in our links list
78
+ def reject_links
79
+ putw "WARN: override reject_links in helper script" if @warn
80
+ default_reject_links
81
+ end
82
+
83
+ # default reject links (override using reject_links in helper script)
84
+ def default_reject_links
85
+ @links.reject! do |url|
86
+ url.nil? ||
87
+ url.extname == ".css" ||
88
+ url.extname == ".pdf" ||
89
+ url =~ /javascript:/i ||
90
+ url =~ /mailto:/i ||
91
+ url =~ /[\[\]]/ ||
92
+ url =~ /^#/
93
+ end
94
+ end
95
+
96
+ # define an urls_from_helper method in your task specific script
97
+ def urls_from_helper
98
+ putw "WARN: Please set an urls_from_helper override in your helper script" if @warn
99
+ return nil
100
+ end
101
+
102
+ # use xpath searches to get
103
+ # * //a href
104
+ # * //area href
105
+ # * //frame src
106
+ # * //iframe src
107
+ # * //form action
108
+ # * //meta refresh content urls
109
+ # then get //script tags and regexp out links in javascript function calls
110
+ # from elem.inner_html
111
+ def for_links(reject=true)
112
+ self.urls_from_xpath("//a","href").each { |url| @links << url }; # get <a href=""> elements
113
+ self.urls_from_xpath("//area","href").each { |url| @links << url }; # get <area href=""> elements
114
+ self.urls_from_xpath("//frame","src").each { |url| @links << url }; # get <frame src=""> elements
115
+ self.urls_from_xpath("//iframe","src").each { |url| @links << url }; # get <iframe src=""> elements
116
+ self.urls_from_xpath("//form","action").each { |url| @links << url }; # get <form action=""> elements
117
+
118
+ # <meta> refresh
119
+ @hdoc.search("//meta").each do |meta|
120
+ next if meta['http-equiv'] != "refresh"
121
+ next if not (content = meta['content'].split(/=/)[1])
122
+ @links << content.strip
123
+ end
124
+
125
+ # add urls from onclick handlers
126
+ @hdoc.search("*[@onclick]").each do |onclick|
127
+ LINKS_REGEXP.each do |re|
128
+ self.urls_from_regexp(onclick['onclick'],re).each do |url|
129
+ @links << url
130
+ end
131
+ end
132
+ end
133
+
134
+ # add urls_from_regexp (limit to <script> tags (elem.inner_html))
135
+ @hdoc.search("//script").each do |scr|
136
+ LINKS_REGEXP.each do |re|
137
+ self.urls_from_regexp(scr.inner_html,re).each { |url| @links << url }
138
+ end
139
+ end
140
+
141
+ # re-define urls_from_helper in what you mix in
142
+ begin
143
+ self.urls_from_helper
144
+ end
145
+
146
+ self.reject_links; # reject links we don't care about
147
+ return @links
148
+ end
149
+
150
+ # scrape the page for <script src=""> tags
151
+ def for_javascript_links
152
+ urls = []
153
+ @hdoc.search("//script[@src]").each { |tag| urls << tag['src'] }
154
+ urls.reject! { |url| File.extname(url).clip != ".js" }
155
+ return urls
156
+ end
157
+
158
+ # scan page for comment fields
159
+ def for_comments
160
+ @page.scan(/\<!\s*--(.*?)--\s*\>/m).map { |x| x.to_s }
161
+ end
162
+
163
+ # scrape the page for a meta refresh tag and return the url from the contents attribute or nil
164
+ def for_meta_refresh
165
+ has_mr = @hdoc.search("//meta").map { |x| x['http-equiv'] }.include?('Refresh')
166
+ if has_mr
167
+ urls = @hdoc.search("//meta[@content]").map { |x| x['content'].split(";",2)[1] }
168
+ if urls.size > 1
169
+ STDERR.puts "PARSE ERROR: more than one meta refresh tag"
170
+ return "ERR"
171
+ end
172
+ k,v = urls.first.split("=",2)
173
+ if k.upcase.strip != "URL"
174
+ STDERR.puts "PARSE ERROR: content attribute of meta refresh does not contain url"
175
+ return "ERR"
176
+ end
177
+ return v.strip
178
+ else
179
+ return nil
180
+ end
181
+ end
182
+
183
+ # scrape the page for a script tag that contains a bare location.href tag (to redirect the page)
184
+ def for_javascript_redirect
185
+ redirs = []
186
+ @hdoc.search("//script").each do |scr|
187
+ scr.inner_html.scan(/.*location.href\s*=\s*['"]([^'"]+)['"]/i).each { |x| redirs += x }
188
+ end
189
+ if redirs.size > 1
190
+ STDERR.puts "PARSE ERROR: more than one javascript redirect"
191
+ return "ERR"
192
+ end
193
+ return redirs.first if not redirs.empty?
194
+ return nil
195
+ end
196
+
197
+ # renamed class variable (for backward compat)
198
+ def warnings#:nodoc:
199
+ return @warn
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,127 @@
1
+ module WWMD
2
+ # when a WWMD::Page object is created, it created its own WWMD::Spider object
3
+ # which can be accessed using <tt>page.spider.method</tt>. The <tt>page.set_data</tt>
4
+ # method calls <tt>page.spider.add</tt> with the current url and a list of scraped
5
+ # links from the page. This class doesn't do any real heavy lifting.
6
+ #
7
+ # a simple spider can be written just by recursing through page.spider.next until
8
+ # it's empty.
9
+ class Spider
10
+
11
+ attr_accessor :queued
12
+ attr_accessor :visited
13
+ attr_accessor :bypass
14
+ attr_accessor :local_only
15
+ attr_reader :opts
16
+ attr_accessor :ignore
17
+ attr_accessor :csrf_token
18
+
19
+ DEFAULT_IGNORE = [
20
+ /logoff/i,
21
+ /logout/i,
22
+ ]
23
+
24
+ # pass me opts and an array of regexps to ignore
25
+ # we have a set of sane(ish) defaults here
26
+ def initialize(opts={},ignore=nil)
27
+ @opts = opts
28
+ @visited = []
29
+ @queued = []
30
+ @bypass = []
31
+ @local_only = true
32
+ @csrf_token = nil
33
+ if !opts[:spider_local_only].nil?
34
+ @local_only = opts[:spider_local_only]
35
+ end
36
+ @ignore = ignore || DEFAULT_IGNORE
37
+ end
38
+
39
+ # push an url onto the queue
40
+ def push_url(url)
41
+ return false if _check_ignore(url)
42
+ url = _de_csrf(url)
43
+ if @local_only
44
+ return false if !(url =~ /#{@opts[:base_url]}/)
45
+ end
46
+ @bypass.each { |b| return true if (url =~ b) }
47
+ @queued.push(url) if (@visited.find { |v| v == url }.nil? and @queued.find { |q| q == url }.nil?)
48
+ return true
49
+ end
50
+
51
+ # skip items in the queue
52
+ def skip(tim=1)
53
+ tim.times { |i| @queued.shift }
54
+ return true
55
+ end
56
+
57
+ # get the next url in the queue
58
+ def get_next
59
+ return queued.shift
60
+ end
61
+
62
+ alias_method :next, :get_next
63
+
64
+ # more elements in the queue?
65
+ def next?
66
+ return !queued.empty?
67
+ end
68
+
69
+ # get the last ul we visited? this doesn't look right
70
+ def get_last(url)
71
+ tmp = @visited.reject { |v| v =~ /#{url}/ }
72
+ return tmp[-1]
73
+ end
74
+
75
+ # show the visited list (or the entry in the list at [id])
76
+ def show_visited(id=nil)
77
+ if id.nil?
78
+ @visited.each_index { |i| putx i.to_s + " :: " + @visited[i].to_s }
79
+ return nil
80
+ else
81
+ return @visited[id]
82
+ end
83
+ end
84
+
85
+ alias_method :v, :show_visited
86
+
87
+ # return the current queue (or the entry in the queue at [id]
88
+ def show_queue(id=nil)
89
+ if id.nil?
90
+ @queued.each_index { |i| putx i.to_s + " :: " + @queued[i].to_s }
91
+ return nil
92
+ else
93
+ return @queued[id]
94
+ end
95
+ end
96
+
97
+ alias_method :q, :show_queue
98
+
99
+ # add url to queue
100
+ def add(url='',links=[])
101
+ @visited.push(_de_csrf(url))
102
+ links.each { |l| self.push_url l }
103
+ return nil
104
+ end
105
+
106
+ # set up the ignore list
107
+ # ignore list is an array of regexp objects
108
+ # remember to set this up before calling any Page methods
109
+ def set_ignore(arr)
110
+ @ignore = arr
111
+ end
112
+
113
+ def _de_csrf(url)
114
+ return url if @csrf_token.nil?
115
+ act,params = url.clopa
116
+ form = params.to_form
117
+ return url if !form.has_key?(@csrf_token)
118
+ form[@csrf_token] = ''
119
+ url = act + form.to_get
120
+ end
121
+
122
+ def _check_ignore(url)
123
+ @ignore.each { |x| return true if (url =~ x) }
124
+ return false
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,79 @@
1
+ module WWMD
2
+ # yay for experiments in re-inventing the wheel
3
+ class URLParse
4
+ HANDLERS = [:https,:http,:ftp,:file]
5
+ attr_reader :proto,:location,:path,:script,:rpath,:params,:base_url,:fqpath
6
+
7
+ def initialize()
8
+ # nothing to see here, move along
9
+ end
10
+
11
+ def parse(*args)
12
+ if args.size == 1
13
+ base = ""
14
+ actual = args.shift
15
+ else
16
+ base = args.shift
17
+ actual = args.shift
18
+ end
19
+ @proto = @location = @path = @script = @rpath = nil
20
+ @base = base.to_s
21
+ @actual = actual
22
+ if self.has_proto?
23
+ @base = @actual
24
+ @actual = ""
25
+ end
26
+ # does this work for http://location/? probably not
27
+ @base += "/" if (!@base.has_ext? || @base.split("/").size == 3)
28
+ @rpath = make_me_path.join("/")
29
+ @params = @rpath.clop
30
+ @path = "/" + @rpath
31
+ if @rpath.has_ext?
32
+ @path = "/" + @rpath.dirname
33
+ @script = @rpath.basename.clip
34
+ end
35
+ @script = "" if @script.nil?
36
+ @base_url = @proto + "://" + @location
37
+ @fqpath = @path + @script
38
+ self
39
+ end
40
+
41
+ def make_me_path
42
+ @proto,tpath = @base.split(":",2)
43
+ tpath ||= ""
44
+ if @actual.empty?
45
+ a_path = tpath.split("/").reject { |x| x.empty? }
46
+ else
47
+ a_path = tpath.dirname.split("/").reject { |x| x.empty? }
48
+ end
49
+ @location = a_path.shift
50
+ a_path = [] if (@actual =~ (/^\//))
51
+ b_path = @actual.split("/").reject { |x| x.empty? }
52
+ a_path.pop if (a_path[-1] =~ /^\?/).kind_of?(Fixnum) && !b_path.empty?
53
+ c_path = (a_path + @actual.split("/").reject { |x| x.empty? }).flatten
54
+ d_path = []
55
+ c_path.each do |x|
56
+ (d_path.pop;next) if x == ".."
57
+ next if x == "."
58
+ d_path << x
59
+ end
60
+ return d_path
61
+ end
62
+
63
+ def has_proto?
64
+ return true if HANDLERS.include?(@actual.split(":").first.downcase.to_sym)
65
+ return false
66
+ end
67
+
68
+ def to_s
69
+ return "#{@proto}://#{@location}/#{rpath}"
70
+ end
71
+ end
72
+ end
73
+
74
+ class String
75
+ def has_ext? #:nodoc:
76
+ return false if self.basename.split(".",2)[1].empty?
77
+ return true
78
+ end
79
+ end
@@ -0,0 +1,30 @@
1
+ module WWMD
2
+ class WWMDUtils
3
+
4
+ def self.header_array_from_file(filename)
5
+ ret = Hash.new
6
+ File.readlines(filename).each do |line|
7
+ a = line.chomp.split(/\t/,2)
8
+ ret[a[0]] = a[1]
9
+ end
10
+ return ret
11
+ end
12
+
13
+ def self.ranstr(len=8,digits=false)
14
+ chars = ("a".."z").to_a
15
+ chars += ("0".."9").to_a if digits
16
+ ret = ""
17
+ 1.upto(len) { |i| ret << chars[rand(chars.size-1)] }
18
+ return ret
19
+ end
20
+
21
+ def self.rannum(len=8,hex=false)
22
+ chars = ("0".."9").to_a
23
+ chars += ("A".."F").to_a if hex
24
+ ret = ""
25
+ 1.upto(len) { |i| ret << chars[rand(chars.size-1)] }
26
+ return ret
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,118 @@
1
+ require 'wwmd/viewstate/viewstate_utils'
2
+ module WWMD
3
+ class ViewState < ViewStateUtils
4
+ end
5
+ end
6
+ require 'rubygems'
7
+ require 'nokogiri'
8
+ require 'htmlentities'
9
+ require 'rexml/document'
10
+ require 'wwmd/mixins'
11
+ require 'wwmd/mixins_extends'
12
+ require 'wwmd/viewstate/viewstate_types'
13
+ require 'wwmd/viewstate/viewstate_class_helpers'
14
+ require 'wwmd/viewstate/viewstate_yaml'
15
+ require 'wwmd/viewstate/viewstate_deserializer_methods'
16
+ require 'wwmd/viewstate/viewstate_from_xml'
17
+ require 'wwmd/viewstate/vs_read_value'
18
+ require 'wwmd/viewstate/vs_read_types'
19
+ require 'wwmd/viewstate/vs_value'
20
+ require 'wwmd/viewstate/vs_array'
21
+ require 'wwmd/viewstate/vs_binary_serialized'
22
+ require 'wwmd/viewstate/vs_int_enum'
23
+ require 'wwmd/viewstate/vs_hashtable'
24
+ require 'wwmd/viewstate/vs_hybrid_dict'
25
+ require 'wwmd/viewstate/vs_list'
26
+ require 'wwmd/viewstate/vs_pair'
27
+ require 'wwmd/viewstate/vs_sparse_array'
28
+ require 'wwmd/viewstate/vs_string'
29
+ require 'wwmd/viewstate/vs_string_array'
30
+ require 'wwmd/viewstate/vs_string_formatted'
31
+ require 'wwmd/viewstate/vs_triplet'
32
+ require 'wwmd/viewstate/vs_type'
33
+ require 'wwmd/viewstate/vs_unit'
34
+ require 'wwmd/viewstate/vs_indexed_string'
35
+ require 'wwmd/viewstate/vs_indexed_string_ref'
36
+ module WWMD
37
+ class ViewState
38
+ attr_accessor :b64
39
+ attr_accessor :obj_queue
40
+ attr_accessor :mac
41
+ attr_accessor :debug
42
+ attr_reader :raw
43
+ attr_reader :stack
44
+ attr_reader :bufarr
45
+ attr_reader :magic
46
+ attr_reader :size
47
+ attr_reader :indexed_strings
48
+ attr_reader :last_offset
49
+ attr_reader :xml
50
+
51
+ def initialize(b64=nil)
52
+ @b64 = b64
53
+ @raw = ""
54
+ @stack = ""
55
+ @obj_queue = []
56
+ @bufarr = []
57
+ @size = 0
58
+ @indexed_strings = []
59
+ @mac = nil
60
+ @debug = false
61
+ end
62
+
63
+ # mac_enabled?
64
+ def mac_enabled?
65
+ return !@mac.nil?
66
+ end
67
+
68
+ # deserialize
69
+ def deserialize(b64=nil)
70
+ @obj_queue = []
71
+ @b64 = b64 if b64
72
+ @raw = @b64.b64d
73
+ @bufarr = @raw.scan(/./m)
74
+ @size = @bufarr.size
75
+ raise "Invalid ViewState" if not self.magic?
76
+ @obj_queue << self.deserialize_value
77
+ if @bufarr.size == 20 then
78
+ @mac = bufarr.slice!(0..19).join("")
79
+ dlog(0x00,"MAC = #{@mac.hexify}")
80
+ end
81
+ raise "Error Parsing Viewstate (left: #{@buffarr.size})" if not @bufarr.size == 0
82
+ return !self.raw.nil?
83
+ end
84
+
85
+ def serialize(objs=nil,version=2)
86
+ @obj_queue = objs if objs
87
+ @stack << "\xFF\x01"
88
+ @stack << @obj_queue.first.serialize
89
+ @stack << @mac if @mac
90
+ return !self.stack.nil?
91
+ end
92
+
93
+ def to_xml
94
+ @xml = REXML::Document.new()
95
+ header = REXML::Element.new("ViewState")
96
+ header.add_attribute("version", @magic.b64e)
97
+ header.add_attribute("version_string", @magic.hexify)
98
+ header.add_element(@obj_queue.first.to_xml)
99
+ if self.mac_enabled?
100
+ max = REXML::Element.new("Mac")
101
+ max.add_attribute("encoding","hexify")
102
+ max.add_text(@mac.hexify)
103
+ header.add_element(max)
104
+ end
105
+ @xml.add_element(header)
106
+ @xml
107
+ end
108
+
109
+ def from_yaml(yaml)
110
+ @obj_queue = YAML.load(yaml)
111
+ end
112
+
113
+ def to_yaml
114
+ @obj_queue.to_yaml
115
+ end
116
+
117
+ end
118
+ end