DEFINITIONS
This source file includes following functions.
1 #
2 # $Id: mailto.rb,v 1.1 2002/01/10 08:00:51 akira Exp $
3 #
4 # Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
5 # You can redistribute it and/or modify it under the same term as Ruby.
6 #
7
8 require 'uri/generic'
9
10 module URI
11
12 =begin
13
14 == URI::MailTo
15
16 === Super Class
17
18 ((<URI::Generic>))
19
20 =end
21
22 # RFC2368, The mailto URL scheme
23 class MailTo < Generic
24 include REGEXP
25
26 DEFAULT_PORT = nil
27
28 COMPONENT = [
29 :scheme,
30 :to, :headers
31 ].freeze
32
33 # "hname" and "hvalue" are encodings of an RFC 822 header name and
34 # value, respectively. As with "to", all URL reserved characters must
35 # be encoded.
36 #
37 # "#mailbox" is as specified in RFC 822 [RFC822]. This means that it
38 # consists of zero or more comma-separated mail addresses, possibly
39 # including "phrase" and "comment" components. Note that all URL
40 # reserved characters in "to" must be encoded: in particular,
41 # parentheses, commas, and the percent sign ("%"), which commonly occur
42 # in the "mailbox" syntax.
43 #
44 # Within mailto URLs, the characters "?", "=", "&" are reserved.
45
46 # hname = *urlc
47 # hvalue = *urlc
48 # header = hname "=" hvalue
49 HEADER_REGEXP = "(?:[^?=&]*=[^?=&]*)".freeze
50 # headers = "?" header *( "&" header )
51 # to = #mailbox
52 # mailtoURL = "mailto:" [ to ] [ headers ]
53 MAILBOX_REGEXP = "(?:[^(),%?=&]|#{PATTERN::ESCAPED})".freeze
54 MAILTO_REGEXP = Regexp.new("
55 \\A
56 (#{MAILBOX_REGEXP}*?) (?# 1: to)
57 (?:
58 \\?
59 (#{HEADER_REGEXP}(?:\\&#{HEADER_REGEXP})*) (?# 2: headers)
60 )?
61 \\z
62 ", Regexp::EXTENDED, 'N').freeze
63
64 =begin
65
66 === Class Methods
67
68 --- URI::MailTo::build
69 Create a new URI::MailTo object from components of URI::MailTo
70 with check. It is to and headers. It provided by an Array of a
71 Hash. You can provide headers as an String like
72 "subject=subscribe&cc=addr" or an Array like [["subject",
73 "subscribe"], ["cc", "addr"]]
74
75 --- URI::MailTo::new
76 Create a new URI::MailTo object from ``generic'' components with
77 no check. Because, this method is usually called from URI::parse
78 and the method checks validity of each components.
79
80 =end
81
82 def self.build(args)
83 tmp = Util::make_components_hash(self, args)
84
85 if tmp[:to]
86 tmp[:opaque] = tmp[:to]
87 else
88 tmp[:opaque] = ''
89 end
90
91 if tmp[:headers]
92 tmp[:opaque] << '?'
93
94 if tmp[:headers].kind_of?(Array)
95 tmp[:opaque] << tmp[:headers].collect { |x|
96 if x.kind_of?(Array)
97 x[0] + '=' + x[1..-1].to_s
98 else
99 x.to_s
100 end
101 }.join('&')
102
103 elsif tmp[:headers].kind_of?(Hash)
104 tmp[:opaque] << tmp[:headers].collect { |h,v|
105 h + '=' + v
106 }.join('&')
107
108 else
109 tmp[:opaque] << tmp[:headers].to_s
110 end
111 end
112
113 return super(tmp)
114 end
115
116 def initialize(*arg)
117 super(*arg)
118
119 @to = nil
120 @headers = []
121
122 if MAILTO_REGEXP =~ @opaque
123 if arg[-1]
124 self.to = $1
125 self.headers = $2
126 else
127 set_to($1)
128 set_headers($2)
129 end
130 elsif arg[-1]
131 raise InvalidComponentError,
132 "unrecognised opaque part for mailtoURL: #{@opaque}"
133 end
134 end
135 attr_reader :to
136 attr_reader :headers
137
138 =begin
139
140 === Instance Methods
141
142 --- URI::MailTo#to
143
144 --- URI::MailTo#to=(v)
145
146 =end
147
148 #
149 # methods for to
150 #
151
152 def check_to(v)
153 return true unless v
154 return true if v.size == 0
155
156 if OPAQUE !~ v || /\A#{MAILBOX_REGEXP}*\z/o !~ v
157 raise InvalidComponentError,
158 "bad component(expected opaque component): #{v}"
159 end
160
161 return true
162 end
163 private :check_to
164
165 def set_to(v)
166 @to = v
167 end
168 protected :set_to
169
170 def to=(v)
171 check_to(v)
172 set_to(v)
173 end
174
175 =begin
176
177 --- URI::MailTo#headers
178
179 --- URI::MailTo#headers=(v)
180
181 =end
182
183 #
184 # methods for headers
185 #
186
187 def check_headers(v)
188 return true unless v
189 return true if v.size == 0
190
191 if OPAQUE !~ v ||
192 /\A(#{HEADER_REGEXP}(?:\&#{HEADER_REGEXP})*)\z/o !~ v
193 raise InvalidComponentError,
194 "bad component(expected opaque component): #{v}"
195 end
196
197 return true
198 end
199 private :check_headers
200
201 def set_headers(v)
202 @headers = []
203 if v
204 v.scan(HEADER_REGEXP) do |x|
205 @headers << x.split(/=/o, 2)
206 end
207 end
208 end
209 protected :set_headers
210
211 def headers=(v)
212 check_headers(v)
213 set_headers(v)
214 end
215
216 def to_str
217 @scheme + ':' +
218 if @to
219 @to
220 else
221 ''
222 end +
223 if @headers.size > 0
224 '?' + @headers.collect{|x| x.join('=')}.join('&')
225 else
226 ''
227 end
228 end
229
230 =begin
231
232 --- URI::MailTo#to_mailtext
233
234 =end
235 def to_mailtext
236 to = URI::unescape(@to)
237 head = ''
238 body = ''
239 @headers.each do |x|
240 case x[0]
241 when 'body'
242 body = URI::unescape(x[1])
243 when 'to'
244 to << ', ' + URI::unescape(x[1])
245 else
246 head << URI::unescape(x[0]).capitalize + ': ' +
247 URI::unescape(x[1]) + "\n"
248 end
249 end
250
251 return "To: #{to}
252 #{head}
253 #{body}
254 "
255 end
256 alias to_rfc822text to_mailtext
257 end # MailTo
258
259 @@schemes['MAILTO'] = MailTo
260 end # URI