apphunkd 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +78 -0
  6. data/TODO +1 -0
  7. data/VERSION +1 -0
  8. data/apphunkd.gemspec +258 -0
  9. data/bin/apphunkd +4 -0
  10. data/config/arguments.rb +12 -0
  11. data/config/boot.rb +68 -0
  12. data/config/environment.rb +23 -0
  13. data/config/environments/development.rb +2 -0
  14. data/config/environments/production.rb +2 -0
  15. data/config/environments/test.rb +2 -0
  16. data/config/post-daemonize/readme +5 -0
  17. data/config/pre-daemonize/readme +12 -0
  18. data/config/pre-daemonize/requires.rb +2 -0
  19. data/lib/apphunkd.rb +25 -0
  20. data/lib/apphunkd/api.rb +5 -0
  21. data/lib/apphunkd/api/service.rb +27 -0
  22. data/lib/apphunkd/queue.rb +96 -0
  23. data/lib/apphunkd/remote.rb +29 -0
  24. data/lib/apphunkd/remote/result.rb +15 -0
  25. data/libexec/apphunkd-daemon.rb +13 -0
  26. data/script/console +3 -0
  27. data/script/destroy +14 -0
  28. data/script/generate +14 -0
  29. data/spec/lib/apphunkd/api/service_spec.rb +47 -0
  30. data/spec/lib/apphunkd/queue_spec.rb +129 -0
  31. data/spec/lib/apphunkd/remote_spec.rb +61 -0
  32. data/spec/lib/apphunkd_spec.rb +50 -0
  33. data/spec/spec.opts +1 -0
  34. data/spec/spec_helper.rb +13 -0
  35. data/support/apphunkd.initd +47 -0
  36. data/support/apphunkd.monitrc +3 -0
  37. data/tasks/rspec.rake +21 -0
  38. data/vendor/daemon-kit/Configuration.txt +102 -0
  39. data/vendor/daemon-kit/Deployment.txt +113 -0
  40. data/vendor/daemon-kit/History.txt +97 -0
  41. data/vendor/daemon-kit/Logging.txt +92 -0
  42. data/vendor/daemon-kit/Manifest.txt +166 -0
  43. data/vendor/daemon-kit/PostInstall.txt +6 -0
  44. data/vendor/daemon-kit/README.rdoc +130 -0
  45. data/vendor/daemon-kit/Rakefile +37 -0
  46. data/vendor/daemon-kit/RuoteParticipants.txt +113 -0
  47. data/vendor/daemon-kit/TODO.txt +37 -0
  48. data/vendor/daemon-kit/app_generators/daemon_kit/USAGE +7 -0
  49. data/vendor/daemon-kit/app_generators/daemon_kit/daemon_kit_generator.rb +161 -0
  50. data/vendor/daemon-kit/app_generators/daemon_kit/templates/README +48 -0
  51. data/vendor/daemon-kit/app_generators/daemon_kit/templates/Rakefile +6 -0
  52. data/vendor/daemon-kit/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
  53. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  54. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/boot.rb +68 -0
  55. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environment.rb +23 -0
  56. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
  57. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
  58. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
  59. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
  60. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/pre-daemonize/readme +12 -0
  61. data/vendor/daemon-kit/app_generators/daemon_kit/templates/lib/daemon.rb +2 -0
  62. data/vendor/daemon-kit/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
  63. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/console +3 -0
  64. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/destroy +14 -0
  65. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/generate +14 -0
  66. data/vendor/daemon-kit/bin/daemon_kit +18 -0
  67. data/vendor/daemon-kit/daemon_generators/amqp/USAGE +5 -0
  68. data/vendor/daemon-kit/daemon_generators/amqp/amqp_generator.rb +65 -0
  69. data/vendor/daemon-kit/daemon_generators/amqp/templates/config/amqp.yml +28 -0
  70. data/vendor/daemon-kit/daemon_generators/amqp/templates/config/initializers/amqp.rb +7 -0
  71. data/vendor/daemon-kit/daemon_generators/amqp/templates/libexec/daemon.rb +37 -0
  72. data/vendor/daemon-kit/daemon_generators/cron/USAGE +5 -0
  73. data/vendor/daemon-kit/daemon_generators/cron/cron_generator.rb +64 -0
  74. data/vendor/daemon-kit/daemon_generators/cron/templates/config/initializers/cron.rb +11 -0
  75. data/vendor/daemon-kit/daemon_generators/cron/templates/libexec/daemon.rb +43 -0
  76. data/vendor/daemon-kit/daemon_generators/cucumber/USAGE +11 -0
  77. data/vendor/daemon-kit/daemon_generators/cucumber/cucumber_generator.rb +38 -0
  78. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber +8 -0
  79. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber.rake +13 -0
  80. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
  81. data/vendor/daemon-kit/daemon_generators/cucumber/templates/env.rb +7 -0
  82. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
  83. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
  84. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  85. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy.rb +53 -0
  86. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
  87. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
  88. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
  89. data/vendor/daemon-kit/daemon_generators/jabber/USAGE +5 -0
  90. data/vendor/daemon-kit/daemon_generators/jabber/jabber_generator.rb +65 -0
  91. data/vendor/daemon-kit/daemon_generators/jabber/templates/config/initializers/jabber.rb +7 -0
  92. data/vendor/daemon-kit/daemon_generators/jabber/templates/config/jabber.yml +26 -0
  93. data/vendor/daemon-kit/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
  94. data/vendor/daemon-kit/daemon_generators/nanite_agent/USAGE +5 -0
  95. data/vendor/daemon-kit/daemon_generators/nanite_agent/nanite_agent_generator.rb +68 -0
  96. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb +6 -0
  97. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/nanite.yml +35 -0
  98. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/lib/actors/sample.rb +11 -0
  99. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/libexec/daemon.rb +31 -0
  100. data/vendor/daemon-kit/daemon_generators/rspec/USAGE +5 -0
  101. data/vendor/daemon-kit/daemon_generators/rspec/rspec_generator.rb +55 -0
  102. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec.rb +11 -0
  103. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec.opts +1 -0
  104. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec_helper.rb +21 -0
  105. data/vendor/daemon-kit/daemon_generators/rspec/templates/tasks/rspec.rake +21 -0
  106. data/vendor/daemon-kit/daemon_generators/ruote/USAGE +5 -0
  107. data/vendor/daemon-kit/daemon_generators/ruote/ruote_generator.rb +67 -0
  108. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/amqp.yml +30 -0
  109. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/initializers/ruote.rb +13 -0
  110. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/ruote.yml +23 -0
  111. data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/daemon.rb +4 -0
  112. data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/sample.rb +26 -0
  113. data/vendor/daemon-kit/daemon_generators/ruote/templates/libexec/daemon.rb +33 -0
  114. data/vendor/daemon-kit/lib/daemon_kit.rb +54 -0
  115. data/vendor/daemon-kit/lib/daemon_kit/abstract_logger.rb +235 -0
  116. data/vendor/daemon-kit/lib/daemon_kit/amqp.rb +38 -0
  117. data/vendor/daemon-kit/lib/daemon_kit/application.rb +187 -0
  118. data/vendor/daemon-kit/lib/daemon_kit/arguments.rb +165 -0
  119. data/vendor/daemon-kit/lib/daemon_kit/commands/console.rb +38 -0
  120. data/vendor/daemon-kit/lib/daemon_kit/config.rb +108 -0
  121. data/vendor/daemon-kit/lib/daemon_kit/console_daemon.rb +2 -0
  122. data/vendor/daemon-kit/lib/daemon_kit/core_ext.rb +1 -0
  123. data/vendor/daemon-kit/lib/daemon_kit/core_ext/configurable.rb +96 -0
  124. data/vendor/daemon-kit/lib/daemon_kit/core_ext/string.rb +22 -0
  125. data/vendor/daemon-kit/lib/daemon_kit/cron.rb +48 -0
  126. data/vendor/daemon-kit/lib/daemon_kit/cucumber/world.rb +38 -0
  127. data/vendor/daemon-kit/lib/daemon_kit/deployment/capistrano.rb +482 -0
  128. data/vendor/daemon-kit/lib/daemon_kit/em.rb +43 -0
  129. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/base.rb +32 -0
  130. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/hoptoad.rb +61 -0
  131. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/mail.rb +85 -0
  132. data/vendor/daemon-kit/lib/daemon_kit/exceptions.rb +8 -0
  133. data/vendor/daemon-kit/lib/daemon_kit/initializer.rb +438 -0
  134. data/vendor/daemon-kit/lib/daemon_kit/jabber.rb +170 -0
  135. data/vendor/daemon-kit/lib/daemon_kit/nanite.rb +7 -0
  136. data/vendor/daemon-kit/lib/daemon_kit/nanite/agent.rb +56 -0
  137. data/vendor/daemon-kit/lib/daemon_kit/pid_file.rb +61 -0
  138. data/vendor/daemon-kit/lib/daemon_kit/ruote_participants.rb +119 -0
  139. data/vendor/daemon-kit/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
  140. data/vendor/daemon-kit/lib/daemon_kit/ruote_workitem.rb +169 -0
  141. data/vendor/daemon-kit/lib/daemon_kit/safety.rb +85 -0
  142. data/vendor/daemon-kit/lib/daemon_kit/tasks.rb +2 -0
  143. data/vendor/daemon-kit/lib/daemon_kit/tasks/environment.rake +10 -0
  144. data/vendor/daemon-kit/lib/daemon_kit/tasks/framework.rake +120 -0
  145. data/vendor/daemon-kit/lib/daemon_kit/tasks/god.rake +62 -0
  146. data/vendor/daemon-kit/lib/daemon_kit/tasks/log.rake +8 -0
  147. data/vendor/daemon-kit/lib/daemon_kit/tasks/monit.rake +29 -0
  148. data/vendor/daemon-kit/script/console +10 -0
  149. data/vendor/daemon-kit/script/destroy +14 -0
  150. data/vendor/daemon-kit/script/generate +14 -0
  151. data/vendor/daemon-kit/script/txt2html +71 -0
  152. data/vendor/daemon-kit/spec/abstract_logger_spec.rb +126 -0
  153. data/vendor/daemon-kit/spec/argument_spec.rb +70 -0
  154. data/vendor/daemon-kit/spec/config_spec.rb +79 -0
  155. data/vendor/daemon-kit/spec/configurable_spec.rb +56 -0
  156. data/vendor/daemon-kit/spec/daemon_kit_spec.rb +7 -0
  157. data/vendor/daemon-kit/spec/error_handlers_spec.rb +23 -0
  158. data/vendor/daemon-kit/spec/fixtures/env.yml +15 -0
  159. data/vendor/daemon-kit/spec/fixtures/noenv.yml +4 -0
  160. data/vendor/daemon-kit/spec/initializer_spec.rb +26 -0
  161. data/vendor/daemon-kit/spec/spec.opts +1 -0
  162. data/vendor/daemon-kit/spec/spec_helper.rb +27 -0
  163. data/vendor/daemon-kit/tasks/rspec.rake +21 -0
  164. data/vendor/daemon-kit/templates/god/god.erb +69 -0
  165. data/vendor/daemon-kit/templates/monit/monit.erb +14 -0
  166. data/vendor/daemon-kit/test/test_amqp_generator.rb +48 -0
  167. data/vendor/daemon-kit/test/test_cron_generator.rb +45 -0
  168. data/vendor/daemon-kit/test/test_daemon-kit_generator.rb +84 -0
  169. data/vendor/daemon-kit/test/test_daemon_kit_config.rb +28 -0
  170. data/vendor/daemon-kit/test/test_deploy_capistrano_generator.rb +48 -0
  171. data/vendor/daemon-kit/test/test_generator_helper.rb +29 -0
  172. data/vendor/daemon-kit/test/test_helper.rb +7 -0
  173. data/vendor/daemon-kit/test/test_jabber_generator.rb +49 -0
  174. data/vendor/daemon-kit/test/test_nanite_agent_generator.rb +49 -0
  175. data/vendor/daemon-kit/test/test_ruote_generator.rb +45 -0
  176. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail.rb +5 -0
  177. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/address.rb +426 -0
  178. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
  179. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
  180. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
  181. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/config.rb +67 -0
  182. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
  183. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
  184. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/header.rb +960 -0
  185. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/index.rb +9 -0
  186. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
  187. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
  188. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
  189. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
  190. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/main.rb +6 -0
  191. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
  192. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/net.rb +248 -0
  193. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
  194. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
  195. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/port.rb +379 -0
  196. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
  197. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
  198. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
  199. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
  200. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
  201. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
  202. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/version.rb +39 -0
  203. data/vendor/daemon-kit/vendor/tmail.rb +13 -0
  204. metadata +281 -0
@@ -0,0 +1,960 @@
1
+ #--
2
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
24
+ # with permission of Minero Aoki.
25
+ #++
26
+
27
+ require 'tmail/encode'
28
+ require 'tmail/address'
29
+ require 'tmail/parser'
30
+ require 'tmail/config'
31
+ require 'tmail/utils'
32
+
33
+ #:startdoc:
34
+ module TMail
35
+
36
+ # Provides methods to handle and manipulate headers in the email
37
+ class HeaderField
38
+
39
+ include TextUtils
40
+
41
+ class << self
42
+
43
+ alias newobj new
44
+
45
+ def new( name, body, conf = DEFAULT_CONFIG )
46
+ klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader
47
+ klass.newobj body, conf
48
+ end
49
+
50
+ # Returns a HeaderField object matching the header you specify in the "name" param.
51
+ # Requires an initialized TMail::Port to be passed in.
52
+ #
53
+ # The method searches the header of the Port you pass into it to find a match on
54
+ # the header line you pass. Once a match is found, it will unwrap the matching line
55
+ # as needed to return an initialized HeaderField object.
56
+ #
57
+ # If you want to get the Envelope sender of the email object, pass in "EnvelopeSender",
58
+ # if you want the From address of the email itself, pass in 'From'.
59
+ #
60
+ # This is because a mailbox doesn't have the : after the From that designates the
61
+ # beginning of the envelope sender (which can be different to the from address of
62
+ # the email)
63
+ #
64
+ # Other fields can be passed as normal, "Reply-To", "Received" etc.
65
+ #
66
+ # Note: Change of behaviour in 1.2.1 => returns nil if it does not find the specified
67
+ # header field, otherwise returns an instantiated object of the correct header class
68
+ #
69
+ # For example:
70
+ # port = TMail::FilePort.new("/test/fixtures/raw_email_simple")
71
+ # h = TMail::HeaderField.new_from_port(port, "From")
72
+ # h.addrs.to_s #=> "Mikel Lindsaar <mikel@nowhere.com>"
73
+ # h = TMail::HeaderField.new_from_port(port, "EvelopeSender")
74
+ # h.addrs.to_s #=> "mike@anotherplace.com.au"
75
+ # h = TMail::HeaderField.new_from_port(port, "SomeWeirdHeaderField")
76
+ # h #=> nil
77
+ def new_from_port( port, name, conf = DEFAULT_CONFIG )
78
+ if name == "EnvelopeSender"
79
+ name = "From"
80
+ re = Regexp.new('\A(From) ', 'i')
81
+ else
82
+ re = Regexp.new('\A(' + Regexp.quote(name) + '):', 'i')
83
+ end
84
+ str = nil
85
+ port.ropen {|f|
86
+ f.each do |line|
87
+ if m = re.match(line) then str = m.post_match.strip
88
+ elsif str and /\A[\t ]/ === line then str << ' ' << line.strip
89
+ elsif /\A-*\s*\z/ === line then break
90
+ elsif str then break
91
+ end
92
+ end
93
+ }
94
+ new(name, str, Config.to_config(conf)) if str
95
+ end
96
+
97
+ def internal_new( name, conf )
98
+ FNAME_TO_CLASS[name].newobj('', conf, true)
99
+ end
100
+
101
+ end # class << self
102
+
103
+ def initialize( body, conf, intern = false )
104
+ @body = body
105
+ @config = conf
106
+
107
+ @illegal = false
108
+ @parsed = false
109
+
110
+ if intern
111
+ @parsed = true
112
+ parse_init
113
+ end
114
+ end
115
+
116
+ def inspect
117
+ "#<#{self.class} #{@body.inspect}>"
118
+ end
119
+
120
+ def illegal?
121
+ @illegal
122
+ end
123
+
124
+ def empty?
125
+ ensure_parsed
126
+ return true if @illegal
127
+ isempty?
128
+ end
129
+
130
+ private
131
+
132
+ def ensure_parsed
133
+ return if @parsed
134
+ @parsed = true
135
+ parse
136
+ end
137
+
138
+ # defabstract parse
139
+ # end
140
+
141
+ def clear_parse_status
142
+ @parsed = false
143
+ @illegal = false
144
+ end
145
+
146
+ public
147
+
148
+ def body
149
+ ensure_parsed
150
+ v = Decoder.new(s = '')
151
+ do_accept v
152
+ v.terminate
153
+ s
154
+ end
155
+
156
+ def body=( str )
157
+ @body = str
158
+ clear_parse_status
159
+ end
160
+
161
+ include StrategyInterface
162
+
163
+ def accept( strategy )
164
+ ensure_parsed
165
+ do_accept strategy
166
+ strategy.terminate
167
+ end
168
+
169
+ # abstract do_accept
170
+
171
+ end
172
+
173
+
174
+ class UnstructuredHeader < HeaderField
175
+
176
+ def body
177
+ ensure_parsed
178
+ @body
179
+ end
180
+
181
+ def body=( arg )
182
+ ensure_parsed
183
+ @body = arg
184
+ end
185
+
186
+ private
187
+
188
+ def parse_init
189
+ end
190
+
191
+ def parse
192
+ @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
193
+ end
194
+
195
+ def isempty?
196
+ not @body
197
+ end
198
+
199
+ def do_accept( strategy )
200
+ strategy.text @body
201
+ end
202
+
203
+ end
204
+
205
+
206
+ class StructuredHeader < HeaderField
207
+
208
+ def comments
209
+ ensure_parsed
210
+ if @comments[0]
211
+ [Decoder.decode(@comments[0])]
212
+ else
213
+ @comments
214
+ end
215
+ end
216
+
217
+ private
218
+
219
+ def parse
220
+ save = nil
221
+
222
+ begin
223
+ parse_init
224
+ do_parse
225
+ rescue SyntaxError
226
+ if not save and mime_encoded? @body
227
+ save = @body
228
+ @body = Decoder.decode(save)
229
+ retry
230
+ elsif save
231
+ @body = save
232
+ end
233
+
234
+ @illegal = true
235
+ raise if @config.strict_parse?
236
+ end
237
+ end
238
+
239
+ def parse_init
240
+ @comments = []
241
+ init
242
+ end
243
+
244
+ def do_parse
245
+ quote_boundary
246
+ obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
247
+ set obj if obj
248
+ end
249
+
250
+ end
251
+
252
+
253
+ class DateTimeHeader < StructuredHeader
254
+
255
+ PARSE_TYPE = :DATETIME
256
+
257
+ def date
258
+ ensure_parsed
259
+ @date
260
+ end
261
+
262
+ def date=( arg )
263
+ ensure_parsed
264
+ @date = arg
265
+ end
266
+
267
+ private
268
+
269
+ def init
270
+ @date = nil
271
+ end
272
+
273
+ def set( t )
274
+ @date = t
275
+ end
276
+
277
+ def isempty?
278
+ not @date
279
+ end
280
+
281
+ def do_accept( strategy )
282
+ strategy.meta time2str(@date)
283
+ end
284
+
285
+ end
286
+
287
+
288
+ class AddressHeader < StructuredHeader
289
+
290
+ PARSE_TYPE = :MADDRESS
291
+
292
+ def addrs
293
+ ensure_parsed
294
+ @addrs
295
+ end
296
+
297
+ private
298
+
299
+ def init
300
+ @addrs = []
301
+ end
302
+
303
+ def set( a )
304
+ @addrs = a
305
+ end
306
+
307
+ def isempty?
308
+ @addrs.empty?
309
+ end
310
+
311
+ def do_accept( strategy )
312
+ first = true
313
+ @addrs.each do |a|
314
+ if first
315
+ first = false
316
+ else
317
+ strategy.meta ','
318
+ strategy.space
319
+ end
320
+ a.accept strategy
321
+ end
322
+
323
+ @comments.each do |c|
324
+ strategy.space
325
+ strategy.meta '('
326
+ strategy.text c
327
+ strategy.meta ')'
328
+ end
329
+ end
330
+
331
+ end
332
+
333
+
334
+ class ReturnPathHeader < AddressHeader
335
+
336
+ PARSE_TYPE = :RETPATH
337
+
338
+ def addr
339
+ addrs()[0]
340
+ end
341
+
342
+ def spec
343
+ a = addr() or return nil
344
+ a.spec
345
+ end
346
+
347
+ def routes
348
+ a = addr() or return nil
349
+ a.routes
350
+ end
351
+
352
+ private
353
+
354
+ def do_accept( strategy )
355
+ a = addr()
356
+
357
+ strategy.meta '<'
358
+ unless a.routes.empty?
359
+ strategy.meta a.routes.map {|i| '@' + i }.join(',')
360
+ strategy.meta ':'
361
+ end
362
+ spec = a.spec
363
+ strategy.meta spec if spec
364
+ strategy.meta '>'
365
+ end
366
+
367
+ end
368
+
369
+
370
+ class SingleAddressHeader < AddressHeader
371
+
372
+ def addr
373
+ addrs()[0]
374
+ end
375
+
376
+ private
377
+
378
+ def do_accept( strategy )
379
+ a = addr()
380
+ a.accept strategy
381
+ @comments.each do |c|
382
+ strategy.space
383
+ strategy.meta '('
384
+ strategy.text c
385
+ strategy.meta ')'
386
+ end
387
+ end
388
+
389
+ end
390
+
391
+
392
+ class MessageIdHeader < StructuredHeader
393
+
394
+ def id
395
+ ensure_parsed
396
+ @id
397
+ end
398
+
399
+ def id=( arg )
400
+ ensure_parsed
401
+ @id = arg
402
+ end
403
+
404
+ private
405
+
406
+ def init
407
+ @id = nil
408
+ end
409
+
410
+ def isempty?
411
+ not @id
412
+ end
413
+
414
+ def do_parse
415
+ @id = @body.slice(MESSAGE_ID) or
416
+ raise SyntaxError, "wrong Message-ID format: #{@body}"
417
+ end
418
+
419
+ def do_accept( strategy )
420
+ strategy.meta @id
421
+ end
422
+
423
+ end
424
+
425
+
426
+ class ReferencesHeader < StructuredHeader
427
+
428
+ def refs
429
+ ensure_parsed
430
+ @refs
431
+ end
432
+
433
+ def each_id
434
+ self.refs.each do |i|
435
+ yield i if MESSAGE_ID === i
436
+ end
437
+ end
438
+
439
+ def ids
440
+ ensure_parsed
441
+ @ids
442
+ end
443
+
444
+ def each_phrase
445
+ self.refs.each do |i|
446
+ yield i unless MESSAGE_ID === i
447
+ end
448
+ end
449
+
450
+ def phrases
451
+ ret = []
452
+ each_phrase {|i| ret.push i }
453
+ ret
454
+ end
455
+
456
+ private
457
+
458
+ def init
459
+ @refs = []
460
+ @ids = []
461
+ end
462
+
463
+ def isempty?
464
+ @ids.empty?
465
+ end
466
+
467
+ def do_parse
468
+ str = @body
469
+ while m = MESSAGE_ID.match(str)
470
+ pre = m.pre_match.strip
471
+ @refs.push pre unless pre.empty?
472
+ @refs.push s = m[0]
473
+ @ids.push s
474
+ str = m.post_match
475
+ end
476
+ str = str.strip
477
+ @refs.push str unless str.empty?
478
+ end
479
+
480
+ def do_accept( strategy )
481
+ first = true
482
+ @ids.each do |i|
483
+ if first
484
+ first = false
485
+ else
486
+ strategy.space
487
+ end
488
+ strategy.meta i
489
+ end
490
+ end
491
+
492
+ end
493
+
494
+
495
+ class ReceivedHeader < StructuredHeader
496
+
497
+ PARSE_TYPE = :RECEIVED
498
+
499
+ def from
500
+ ensure_parsed
501
+ @from
502
+ end
503
+
504
+ def from=( arg )
505
+ ensure_parsed
506
+ @from = arg
507
+ end
508
+
509
+ def by
510
+ ensure_parsed
511
+ @by
512
+ end
513
+
514
+ def by=( arg )
515
+ ensure_parsed
516
+ @by = arg
517
+ end
518
+
519
+ def via
520
+ ensure_parsed
521
+ @via
522
+ end
523
+
524
+ def via=( arg )
525
+ ensure_parsed
526
+ @via = arg
527
+ end
528
+
529
+ def with
530
+ ensure_parsed
531
+ @with
532
+ end
533
+
534
+ def id
535
+ ensure_parsed
536
+ @id
537
+ end
538
+
539
+ def id=( arg )
540
+ ensure_parsed
541
+ @id = arg
542
+ end
543
+
544
+ def _for
545
+ ensure_parsed
546
+ @_for
547
+ end
548
+
549
+ def _for=( arg )
550
+ ensure_parsed
551
+ @_for = arg
552
+ end
553
+
554
+ def date
555
+ ensure_parsed
556
+ @date
557
+ end
558
+
559
+ def date=( arg )
560
+ ensure_parsed
561
+ @date = arg
562
+ end
563
+
564
+ private
565
+
566
+ def init
567
+ @from = @by = @via = @with = @id = @_for = nil
568
+ @with = []
569
+ @date = nil
570
+ end
571
+
572
+ def set( args )
573
+ @from, @by, @via, @with, @id, @_for, @date = *args
574
+ end
575
+
576
+ def isempty?
577
+ @with.empty? and not (@from or @by or @via or @id or @_for or @date)
578
+ end
579
+
580
+ def do_accept( strategy )
581
+ list = []
582
+ list.push 'from ' + @from if @from
583
+ list.push 'by ' + @by if @by
584
+ list.push 'via ' + @via if @via
585
+ @with.each do |i|
586
+ list.push 'with ' + i
587
+ end
588
+ list.push 'id ' + @id if @id
589
+ list.push 'for <' + @_for + '>' if @_for
590
+
591
+ first = true
592
+ list.each do |i|
593
+ strategy.space unless first
594
+ strategy.meta i
595
+ first = false
596
+ end
597
+ if @date
598
+ strategy.meta ';'
599
+ strategy.space
600
+ strategy.meta time2str(@date)
601
+ end
602
+ end
603
+
604
+ end
605
+
606
+
607
+ class KeywordsHeader < StructuredHeader
608
+
609
+ PARSE_TYPE = :KEYWORDS
610
+
611
+ def keys
612
+ ensure_parsed
613
+ @keys
614
+ end
615
+
616
+ private
617
+
618
+ def init
619
+ @keys = []
620
+ end
621
+
622
+ def set( a )
623
+ @keys = a
624
+ end
625
+
626
+ def isempty?
627
+ @keys.empty?
628
+ end
629
+
630
+ def do_accept( strategy )
631
+ first = true
632
+ @keys.each do |i|
633
+ if first
634
+ first = false
635
+ else
636
+ strategy.meta ','
637
+ end
638
+ strategy.meta i
639
+ end
640
+ end
641
+
642
+ end
643
+
644
+
645
+ class EncryptedHeader < StructuredHeader
646
+
647
+ PARSE_TYPE = :ENCRYPTED
648
+
649
+ def encrypter
650
+ ensure_parsed
651
+ @encrypter
652
+ end
653
+
654
+ def encrypter=( arg )
655
+ ensure_parsed
656
+ @encrypter = arg
657
+ end
658
+
659
+ def keyword
660
+ ensure_parsed
661
+ @keyword
662
+ end
663
+
664
+ def keyword=( arg )
665
+ ensure_parsed
666
+ @keyword = arg
667
+ end
668
+
669
+ private
670
+
671
+ def init
672
+ @encrypter = nil
673
+ @keyword = nil
674
+ end
675
+
676
+ def set( args )
677
+ @encrypter, @keyword = args
678
+ end
679
+
680
+ def isempty?
681
+ not (@encrypter or @keyword)
682
+ end
683
+
684
+ def do_accept( strategy )
685
+ if @key
686
+ strategy.meta @encrypter + ','
687
+ strategy.space
688
+ strategy.meta @keyword
689
+ else
690
+ strategy.meta @encrypter
691
+ end
692
+ end
693
+
694
+ end
695
+
696
+
697
+ class MimeVersionHeader < StructuredHeader
698
+
699
+ PARSE_TYPE = :MIMEVERSION
700
+
701
+ def major
702
+ ensure_parsed
703
+ @major
704
+ end
705
+
706
+ def major=( arg )
707
+ ensure_parsed
708
+ @major = arg
709
+ end
710
+
711
+ def minor
712
+ ensure_parsed
713
+ @minor
714
+ end
715
+
716
+ def minor=( arg )
717
+ ensure_parsed
718
+ @minor = arg
719
+ end
720
+
721
+ def version
722
+ sprintf('%d.%d', major, minor)
723
+ end
724
+
725
+ private
726
+
727
+ def init
728
+ @major = nil
729
+ @minor = nil
730
+ end
731
+
732
+ def set( args )
733
+ @major, @minor = *args
734
+ end
735
+
736
+ def isempty?
737
+ not (@major or @minor)
738
+ end
739
+
740
+ def do_accept( strategy )
741
+ strategy.meta sprintf('%d.%d', @major, @minor)
742
+ end
743
+
744
+ end
745
+
746
+
747
+ class ContentTypeHeader < StructuredHeader
748
+
749
+ PARSE_TYPE = :CTYPE
750
+
751
+ def main_type
752
+ ensure_parsed
753
+ @main
754
+ end
755
+
756
+ def main_type=( arg )
757
+ ensure_parsed
758
+ @main = arg.downcase
759
+ end
760
+
761
+ def sub_type
762
+ ensure_parsed
763
+ @sub
764
+ end
765
+
766
+ def sub_type=( arg )
767
+ ensure_parsed
768
+ @sub = arg.downcase
769
+ end
770
+
771
+ def content_type
772
+ ensure_parsed
773
+ @sub ? sprintf('%s/%s', @main, @sub) : @main
774
+ end
775
+
776
+ def params
777
+ ensure_parsed
778
+ unless @params.blank?
779
+ @params.each do |k, v|
780
+ @params[k] = unquote(v)
781
+ end
782
+ end
783
+ @params
784
+ end
785
+
786
+ def []( key )
787
+ ensure_parsed
788
+ @params and unquote(@params[key])
789
+ end
790
+
791
+ def []=( key, val )
792
+ ensure_parsed
793
+ (@params ||= {})[key] = val
794
+ end
795
+
796
+ private
797
+
798
+ def init
799
+ @main = @sub = @params = nil
800
+ end
801
+
802
+ def set( args )
803
+ @main, @sub, @params = *args
804
+ end
805
+
806
+ def isempty?
807
+ not (@main or @sub)
808
+ end
809
+
810
+ def do_accept( strategy )
811
+ if @sub
812
+ strategy.meta sprintf('%s/%s', @main, @sub)
813
+ else
814
+ strategy.meta @main
815
+ end
816
+ @params.each do |k,v|
817
+ if v
818
+ strategy.meta ';'
819
+ strategy.space
820
+ strategy.kv_pair k, v
821
+ end
822
+ end
823
+ end
824
+
825
+ end
826
+
827
+
828
+ class ContentTransferEncodingHeader < StructuredHeader
829
+
830
+ PARSE_TYPE = :CENCODING
831
+
832
+ def encoding
833
+ ensure_parsed
834
+ @encoding
835
+ end
836
+
837
+ def encoding=( arg )
838
+ ensure_parsed
839
+ @encoding = arg
840
+ end
841
+
842
+ private
843
+
844
+ def init
845
+ @encoding = nil
846
+ end
847
+
848
+ def set( s )
849
+ @encoding = s
850
+ end
851
+
852
+ def isempty?
853
+ not @encoding
854
+ end
855
+
856
+ def do_accept( strategy )
857
+ strategy.meta @encoding.capitalize
858
+ end
859
+
860
+ end
861
+
862
+
863
+ class ContentDispositionHeader < StructuredHeader
864
+
865
+ PARSE_TYPE = :CDISPOSITION
866
+
867
+ def disposition
868
+ ensure_parsed
869
+ @disposition
870
+ end
871
+
872
+ def disposition=( str )
873
+ ensure_parsed
874
+ @disposition = str.downcase
875
+ end
876
+
877
+ def params
878
+ ensure_parsed
879
+ unless @params.blank?
880
+ @params.each do |k, v|
881
+ @params[k] = unquote(v)
882
+ end
883
+ end
884
+ @params
885
+ end
886
+
887
+ def []( key )
888
+ ensure_parsed
889
+ @params and unquote(@params[key])
890
+ end
891
+
892
+ def []=( key, val )
893
+ ensure_parsed
894
+ (@params ||= {})[key] = val
895
+ end
896
+
897
+ private
898
+
899
+ def init
900
+ @disposition = @params = nil
901
+ end
902
+
903
+ def set( args )
904
+ @disposition, @params = *args
905
+ end
906
+
907
+ def isempty?
908
+ not @disposition and (not @params or @params.empty?)
909
+ end
910
+
911
+ def do_accept( strategy )
912
+ strategy.meta @disposition
913
+ @params.each do |k,v|
914
+ strategy.meta ';'
915
+ strategy.space
916
+ strategy.kv_pair k, unquote(v)
917
+ end
918
+ end
919
+
920
+ end
921
+
922
+
923
+ class HeaderField # redefine
924
+
925
+ FNAME_TO_CLASS = {
926
+ 'date' => DateTimeHeader,
927
+ 'resent-date' => DateTimeHeader,
928
+ 'to' => AddressHeader,
929
+ 'cc' => AddressHeader,
930
+ 'bcc' => AddressHeader,
931
+ 'from' => AddressHeader,
932
+ 'reply-to' => AddressHeader,
933
+ 'resent-to' => AddressHeader,
934
+ 'resent-cc' => AddressHeader,
935
+ 'resent-bcc' => AddressHeader,
936
+ 'resent-from' => AddressHeader,
937
+ 'resent-reply-to' => AddressHeader,
938
+ 'sender' => SingleAddressHeader,
939
+ 'resent-sender' => SingleAddressHeader,
940
+ 'return-path' => ReturnPathHeader,
941
+ 'message-id' => MessageIdHeader,
942
+ 'resent-message-id' => MessageIdHeader,
943
+ 'in-reply-to' => ReferencesHeader,
944
+ 'received' => ReceivedHeader,
945
+ 'references' => ReferencesHeader,
946
+ 'keywords' => KeywordsHeader,
947
+ 'encrypted' => EncryptedHeader,
948
+ 'mime-version' => MimeVersionHeader,
949
+ 'content-type' => ContentTypeHeader,
950
+ 'content-transfer-encoding' => ContentTransferEncodingHeader,
951
+ 'content-disposition' => ContentDispositionHeader,
952
+ 'content-id' => MessageIdHeader,
953
+ 'subject' => UnstructuredHeader,
954
+ 'comments' => UnstructuredHeader,
955
+ 'content-description' => UnstructuredHeader
956
+ }
957
+
958
+ end
959
+
960
+ end # module TMail