rwdmpd 0.06

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/Readme.txt +475 -0
  2. data/bin/rwdmpd +19 -0
  3. data/code/01rwdcore/01rwdcore.rb +29 -0
  4. data/code/01rwdcore/02helptexthashbegin.rb +4 -0
  5. data/code/01rwdcore/03helptexthash.rb +23 -0
  6. data/code/01rwdcore/04helptextend.rb +6 -0
  7. data/code/01rwdcore/jumplinkcommand.rb +26 -0
  8. data/code/01rwdcore/openhelpwindow.rb +31 -0
  9. data/code/01rwdcore/returntomain.rb +10 -0
  10. data/code/01rwdcore/rundocuments.rb +10 -0
  11. data/code/01rwdcore/runeditconfiguration.rb +10 -0
  12. data/code/01rwdcore/runhelpabout.rb +10 -0
  13. data/code/01rwdcore/runopentinkerdocument.rb +7 -0
  14. data/code/01rwdcore/rwdtinkerversion.rb +22 -0
  15. data/code/01rwdcore/rwdwindowreturn.rb +9 -0
  16. data/code/01rwdcore/selectiontab.rb +9 -0
  17. data/code/01rwdcore/setuphelpaboutoptions.rb +13 -0
  18. data/code/01rwdcore/setuptinkerdocuments.rb +6 -0
  19. data/code/01rwdcore/test_cases.rb +109 -0
  20. data/code/01rwdcore/test_harness.rb +13 -0
  21. data/code/01rwdcore/uploadreturns.rb +62 -0
  22. data/code/dd0viewphoto/dd0viewphoto.rb +3 -0
  23. data/code/superant.com.rwdmp3/0uninstallapplet.rb +11 -0
  24. data/code/superant.com.rwdmp3/clearscreendisplay.rb +7 -0
  25. data/code/superant.com.rwdmp3/controlmpd.rb +139 -0
  26. data/code/superant.com.rwdmp3/helptexthashrwdmp3.rb +41 -0
  27. data/code/superant.com.rwdmp3/listplaylistfiles.rb +12 -0
  28. data/code/superant.com.rwdmp3/loadconfigurationrecord.rb +22 -0
  29. data/code/superant.com.rwdmp3/loadconfigurationvariables.rb +13 -0
  30. data/code/superant.com.rwdmp3/loadplaylistrecord.rb +19 -0
  31. data/code/superant.com.rwdmp3/mpd_client.rb +41 -0
  32. data/code/superant.com.rwdmp3/mpd_seek.rb +23 -0
  33. data/code/superant.com.rwdmp3/openhelpwindowrwdmp3.rb +25 -0
  34. data/code/superant.com.rwdmp3/runrwdmpdwindow.rb +10 -0
  35. data/code/superant.com.rwdmp3/rwdtinkerversion.rb +10 -0
  36. data/code/superant.com.rwdmp3/saveconfigurationrecord.rb +19 -0
  37. data/code/superant.com.rwdmp3/saveplaylistrecord.rb +18 -0
  38. data/code/superant.com.rwdmp3/startmp3server.rb +16 -0
  39. data/code/superant.com.rwdtinkerbackwindow/diagnostictab.rb +19 -0
  40. data/code/superant.com.rwdtinkerbackwindow/helptexthashtinkerwin2.rb +61 -0
  41. data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +240 -0
  42. data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +34 -0
  43. data/code/superant.com.rwdtinkerbackwindow/installremotegem.rb +20 -0
  44. data/code/superant.com.rwdtinkerbackwindow/listgemdirs.rb +12 -0
  45. data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +53 -0
  46. data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +12 -0
  47. data/code/superant.com.rwdtinkerbackwindow/listzips.rb +33 -0
  48. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +22 -0
  49. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationvariables.rb +14 -0
  50. data/code/superant.com.rwdtinkerbackwindow/network.rb +87 -0
  51. data/code/superant.com.rwdtinkerbackwindow/openappletname.rb +19 -0
  52. data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +38 -0
  53. data/code/superant.com.rwdtinkerbackwindow/remotegemlist.rb +24 -0
  54. data/code/superant.com.rwdtinkerbackwindow/removeapplet.rb +46 -0
  55. data/code/superant.com.rwdtinkerbackwindow/removeappletvariables.rb +52 -0
  56. data/code/superant.com.rwdtinkerbackwindow/runremoteinstall.rb +11 -0
  57. data/code/superant.com.rwdtinkerbackwindow/runrwdtinkerbackwindow.rb +15 -0
  58. data/code/superant.com.rwdtinkerbackwindow/rwdtinkerwin2version.rb +13 -0
  59. data/code/superant.com.rwdtinkerbackwindow/saveconfigurationrecord.rb +19 -0
  60. data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +22 -0
  61. data/code/superant.com.rwdtinkerbackwindow/viewgemappletcontents.rb +24 -0
  62. data/code/zz0applicationend/zz0end.rb +4 -0
  63. data/configuration/language.dist +8 -0
  64. data/configuration/rwdapplicationidentity.dist +3 -0
  65. data/configuration/rwdtinker.dist +15 -0
  66. data/configuration/rwdwmpd-0.06.dist +14 -0
  67. data/configuration/tinkerwin2variables.dist +18 -0
  68. data/gui/00coreguibegin/applicationguitop.rwd +4 -0
  69. data/gui/frontwindow0/cc0openphoto.rwd +22 -0
  70. data/gui/frontwindowselections/00selectiontabbegin.rwd +11 -0
  71. data/gui/frontwindowselections/jumplinkcommands.rwd +15 -0
  72. data/gui/frontwindowselections/wwselectionend.rwd +3 -0
  73. data/gui/frontwindowtdocuments/00documentbegin.rwd +6 -0
  74. data/gui/frontwindowtdocuments/tinkerdocuments.rwd +14 -0
  75. data/gui/frontwindowtdocuments/zzdocumentend.rwd +8 -0
  76. data/gui/helpaboutbegin/zzzrwdlasttab.rwd +6 -0
  77. data/gui/helpaboutbegin/zzzzhelpscreenstart.rwd +3 -0
  78. data/gui/helpaboutbegin/zzzzzzhelpabouttab.rwd +15 -0
  79. data/gui/helpaboutzend/helpscreenend.rwd +3 -0
  80. data/gui/helpaboutzend/zhelpscreenstart2.rwd +3 -0
  81. data/gui/helpaboutzend/zzzzhelpabout2.rwd +15 -0
  82. data/gui/helpaboutzend/zzzzhelpscreen2end.rwd +3 -0
  83. data/gui/tinkerbackwindows/superant.com.rwdmp3/10appletbegin.rwd +4 -0
  84. data/gui/tinkerbackwindows/superant.com.rwdmp3/20rwdmpd.rwd +37 -0
  85. data/gui/tinkerbackwindows/superant.com.rwdmp3/25rwdseek.rwd +23 -0
  86. data/gui/tinkerbackwindows/superant.com.rwdmp3/30editplaylist.rwd +27 -0
  87. data/gui/tinkerbackwindows/superant.com.rwdmp3/88viewconfiguration.rwd +32 -0
  88. data/gui/tinkerbackwindows/superant.com.rwdmp3/89rwddiagnostics.rwd +26 -0
  89. data/gui/tinkerbackwindows/superant.com.rwdmp3/90jumplinkcommands.rwd +17 -0
  90. data/gui/tinkerbackwindows/superant.com.rwdmp3/9end.rwd +6 -0
  91. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/1appname.rwd +5 -0
  92. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/40rwdlistzips.rwd +41 -0
  93. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/45installremotezip.rwd +44 -0
  94. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/50rwdlistapplets.rwd +44 -0
  95. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/60editconfiguration.rwd +30 -0
  96. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +29 -0
  97. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/81jumplinkcommands.rwd +17 -0
  98. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/9backend.rwd +6 -0
  99. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/1appname.rwd +31 -0
  100. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/9end.rwd +4 -0
  101. data/gui/tinkerbackwindows/superant.com.versionwindow/1appname.rwd +19 -0
  102. data/gui/tinkerbackwindows/superant.com.versionwindow/helpaboutwindow.rwd +17 -0
  103. data/gui/zzcoreguiend/yy9rwdend.rwd +4 -0
  104. data/init.rb +277 -0
  105. data/installed/mpdmusicdata2.inf +2 -0
  106. data/installed/rwdwmpd-0.06.inf +10 -0
  107. data/installed/temp.rb +1 -0
  108. data/lang/en/rwdcore/languagefile.rb +58 -0
  109. data/lang/es/rwdcore/languagefile-es.rb +62 -0
  110. data/lang/fr/rwdcore/languagefile.rb +64 -0
  111. data/lang/jp/rwdcore/languagefile.rb +72 -0
  112. data/lang/nl/rwdcore/languagefile.rb +75 -0
  113. data/lib/librmpd.rb +1152 -0
  114. data/lib/mpdserver.rb +1204 -0
  115. data/lib/rconftool.rb +387 -0
  116. data/lib/rwd/browser.rb +123 -0
  117. data/lib/rwd/ftools.rb +174 -0
  118. data/lib/rwd/mime.rb +328 -0
  119. data/lib/rwd/net.rb +876 -0
  120. data/lib/rwd/ruby.rb +889 -0
  121. data/lib/rwd/rwd.rb +1422 -0
  122. data/lib/rwd/sgml.rb +236 -0
  123. data/lib/rwd/thread.rb +63 -0
  124. data/lib/rwd/tree.rb +371 -0
  125. data/lib/rwd/xml.rb +101 -0
  126. data/lib/rwdthemes/default.rwd +317 -0
  127. data/lib/rwdthemes/pda.rwd +72 -0
  128. data/lib/rwdthemes/windowslike.rwd +171 -0
  129. data/lib/zip/ioextras.rb +114 -0
  130. data/lib/zip/stdrubyext.rb +111 -0
  131. data/lib/zip/tempfile_bugfixed.rb +195 -0
  132. data/lib/zip/zip.rb +1378 -0
  133. data/lib/zip/zipfilesystem.rb +558 -0
  134. data/lib/zip/ziprequire.rb +61 -0
  135. data/music/classicalmues.mp3 +0 -0
  136. data/rwd_files/HowTo_Mpd.txt +136 -0
  137. data/rwd_files/HowTo_Tinker.txt +482 -0
  138. data/rwd_files/HowTo_TinkerWin2.txt +202 -0
  139. data/rwd_files/Readme.txt +57 -0
  140. data/rwd_files/RubyWebDialogs.html +6 -0
  141. data/rwd_files/favicon.ico +0 -0
  142. data/rwd_files/rdoc-style.css +175 -0
  143. data/rwd_files/rwdapplications.html +54 -0
  144. data/rwd_files/tinker.png +0 -0
  145. data/rwdconfig.dist +22 -0
  146. data/rwdmpd.rb +1 -0
  147. data/tests/RubyGauge.rb +179 -0
  148. data/tests/checkdepends.sh +4 -0
  149. data/tests/cleancnf.sh +6 -0
  150. data/tests/makedist-rwdwmpd.rb +58 -0
  151. data/tests/makedist.rb +66 -0
  152. data/tests/rdep.rb +354 -0
  153. data/tests/totranslate.lang +93 -0
  154. data/zips/rwdwaddresses-1.06.zip +0 -0
  155. data/zips/rwdwcalc-0.62.zip +0 -0
  156. data/zips/rwdwfoldeditor-0.04.zip +0 -0
  157. data/zips/rwdwgutenberg-0.09.zip +0 -0
  158. data/zips/rwdwmpd-0.06.zip +0 -0
  159. data/zips/rwdwruby-1.07.zip +0 -0
  160. data/zips/temp.rb +1 -0
  161. data/zips/tinkerbellw-0.02.zip +0 -0
  162. data/zips/wrubyslippers-1.06.zip +0 -0
  163. metadata +220 -0
@@ -0,0 +1,876 @@
1
+ require "lib/rwd/ruby"
2
+ require "lib/rwd/ftools"
3
+ require "lib/rwd/mime"
4
+ require "net/http"
5
+ require "socket"
6
+ require "uri"
7
+ require "cgi"
8
+ require "md5"
9
+ require "thread"
10
+
11
+ $proxy = ENV["PROXY"] if $proxy.nil?
12
+
13
+ file = "#{home}/.evnet"
14
+ if File.file?(file)
15
+ Hash.file(file).each do |k, v|
16
+ eval "$#{k} = '#{v}'" unless k=~ /^\#/
17
+ end
18
+ end
19
+
20
+ def uri2txt(s)
21
+ # ??? Werkt niet goed
22
+ i = s.index(/%[[:digit:]]{2}/)
23
+ while not i.nil?
24
+ s = s[0..(i-1)] + s[(i+1)..(i+2)].unpack('H2').shift.to_i.chr + s[(i+3)..-1]
25
+ i = s.index(/%[[:digit:]]{2}/)
26
+ end
27
+ s
28
+ end
29
+
30
+ class TCPServer
31
+ def self.freeport(from, to, remote=false)
32
+ if windows? or cygwin?
33
+ TCPServer.freeport_windows(from, to, remote)
34
+ else
35
+ TCPServer.freeport_linux(from, to, remote)
36
+ end
37
+ end
38
+
39
+ def self.freeport_linux(from, to, remote)
40
+ ports = (from..to).to_a
41
+ port = nil
42
+ res = nil
43
+
44
+ while res.nil? and not ports.empty?
45
+ begin
46
+ port = ports[0]
47
+ ports.delete(port)
48
+
49
+ io = TCPServer.new(remote ? "0.0.0.0" : "localhost", port)
50
+
51
+ res = [port, io]
52
+ rescue
53
+ end
54
+ end
55
+
56
+ res = [nil, nil] if res.nil?
57
+
58
+ port, io = res
59
+
60
+ return port, io
61
+ end
62
+
63
+ def self.freeport_windows(from, to, remote)
64
+ ports = (from..to).to_a
65
+ port = nil
66
+ res = nil
67
+
68
+ while res.nil? and not ports.empty?
69
+ begin
70
+ port = ports.any
71
+ ports.delete(port)
72
+
73
+ io = TCPSocket.new("localhost", port)
74
+ io.close
75
+ rescue
76
+ res = port
77
+ end
78
+ end
79
+
80
+ port, io = res
81
+
82
+ return port, io
83
+ end
84
+
85
+ def self.freeport_windows2(from, to, remote)
86
+ res = nil
87
+ port = from
88
+
89
+ while res.nil? and port <= to
90
+ begin
91
+ io = TCPSocket.new("localhost", port)
92
+ io.close
93
+
94
+ port += 1
95
+ rescue
96
+ res = port
97
+ end
98
+ end
99
+
100
+ return res
101
+ end
102
+
103
+ def self.usedports(from, to)
104
+ threads = []
105
+ res = []
106
+
107
+ from.upto(to) do |port|
108
+ threads << Thread.new do
109
+ begin
110
+ io = TCPSocket.new("localhost", port)
111
+ io.close
112
+
113
+ port
114
+ rescue
115
+ nil
116
+ end
117
+ end
118
+ end
119
+
120
+ threads.each do |thread|
121
+ port = thread.value
122
+ res << port unless port.nil?
123
+ end
124
+
125
+ return res
126
+ end
127
+ end
128
+
129
+ class EVURI
130
+ attr_reader :protocol
131
+ attr_writer :protocol
132
+ attr_reader :userpass
133
+ attr_writer :userpass
134
+ attr_reader :host
135
+ attr_writer :host
136
+ attr_reader :port
137
+ attr_writer :port
138
+ attr_reader :path
139
+ attr_writer :path
140
+ attr_reader :vars
141
+ attr_writer :vars
142
+ attr_reader :anchor
143
+ attr_writer :anchor
144
+
145
+ def initialize(url)
146
+ begin
147
+ @protocol, @userpass, @host, @port, d1, @path, d2, @vars, @anchor = URI.split(url.to_s)
148
+ rescue
149
+ end
150
+
151
+ @path = "/" if (not @path.nil? and @path.empty? and @protocol == "http")
152
+
153
+ @protocol = "" if @protocol.nil?
154
+ @userpass = "" if @userpass.nil?
155
+ @host = "" if @host.nil?
156
+ @port = 0 if @port.nil?
157
+ @path = "" if @path.nil?
158
+ @vars = "" if @vars.nil?
159
+ @anchor = "" if @anchor.nil?
160
+
161
+ res = {}
162
+ @varsvolgorde = []
163
+ @vars.split(/&/).each{|var| k, v = var.split(/=/) ; res[k] = v ; @varsvolgorde << k}
164
+ @vars = res
165
+
166
+ @port = @port.to_i
167
+ end
168
+
169
+ def +(url2)
170
+ url1 = self.to_s
171
+ url2 = url2.to_s if url2.kind_of?(self.class)
172
+
173
+ return EVURI.new((URI::Generic.new(*URI.split(url1)) + URI::Generic.new(*URI.split(url2))).to_s) rescue nil
174
+ end
175
+
176
+ def to_s
177
+ protocol = @protocol
178
+ userpass = @userpass
179
+ host = @host
180
+ port = @port
181
+ path = @path
182
+ vars = varstring
183
+ anchor = @anchor
184
+
185
+ protocol = nil if @protocol.empty?
186
+ userpass = nil if @userpass.empty?
187
+ host = nil if @host.empty?
188
+ port = nil if @port.zero?
189
+ path = nil if @path.empty?
190
+ vars = nil if @vars.empty?
191
+ anchor = nil if @anchor.empty?
192
+
193
+ res = URI::HTTP.new(@protocol, @userpass, @host, port, nil, @path, nil, vars, @anchor).to_s.from_html
194
+
195
+ res.gsub!(/@/, "") if (@userpass.nil? or @userpass.empty?)
196
+
197
+ res.gsub!(/\#$/, "")
198
+
199
+ return res
200
+ end
201
+
202
+ def localname
203
+ protocol = @protocol
204
+ userpass = @userpass
205
+ host = @host
206
+ port = @port
207
+ path = @path
208
+ vars = varstring
209
+ anchor = @anchor
210
+
211
+ protocol = nil if @protocol.empty?
212
+ userpass = nil if @userpass.empty?
213
+ host = nil if @host.empty?
214
+ port = nil if @port.zero?
215
+ path = nil if @path.empty?
216
+ vars = nil if @vars.empty?
217
+ anchor = nil if @anchor.empty?
218
+
219
+ path = "#{path}." if path =~ /[\/\\]$/
220
+
221
+ f = MD5.new(protocol.to_s + userpass.to_s + host.to_s + port.to_s + File.dirname(path.to_s) + vars.to_s).to_s
222
+ e = File.basename(path.to_s).gsub(/[^\w\.\-]/, "_").gsub(/_+/, "_")
223
+ res = f + "." + e
224
+ res.gsub!(/[^\w]+$/, "")
225
+
226
+ return res
227
+ end
228
+
229
+ def varstring
230
+ res = []
231
+ vars = @vars.dup
232
+
233
+ @varsvolgorde.each do |k|
234
+ if vars.include?(k)
235
+ v = vars[k]
236
+ vars.delete(k)
237
+
238
+ res << (v.nil? ? k : "#{k}=#{v}")
239
+ end
240
+ end
241
+
242
+ res.concat(vars.collect{|k, v| v.nil? ? k : "#{k}=#{v}"})
243
+
244
+ return res.join("&")
245
+ end
246
+ end
247
+
248
+ class HTTPClient
249
+ @@versie = 1
250
+ @@mutex = Mutex.new
251
+ @@hosts = {}
252
+
253
+ class Header
254
+ attr_reader :header
255
+ attr_reader :protocol
256
+ attr_reader :code
257
+ attr_reader :text
258
+
259
+ def initialize(header)
260
+ @header = {}
261
+
262
+ if not header.nil?
263
+ firstline, rest = header.split(/\r*\n/, 2)
264
+
265
+ @protocol, @code, @text = firstline.split(/ */, 3)
266
+
267
+ @code = @code.to_i
268
+
269
+ if not rest.nil?
270
+ rest.split(/\r*\n/).each do |line|
271
+ key, value = line.split(/ /, 2)
272
+ @header[key.sub(/:$/, "").downcase] = value
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ def to_s
279
+ res = ""
280
+
281
+ res << "%s %s %s\n" % [@protocol, @code, @text]
282
+
283
+ @header.each do |k, v|
284
+ res << "%s=%s\n" % [k, v]
285
+ end
286
+
287
+ return res
288
+ end
289
+ end
290
+
291
+ class Chunk
292
+ def initialize(data)
293
+ @data = ""
294
+ line, data = data.split(/\r*\n/, 2)
295
+ size, ext = line.split(/;/, 2)
296
+ size = size.hex
297
+ while not size.zero? and not data.nil?
298
+ @data += data[0..(size-1)]
299
+ data = data[size..-1]
300
+ if not data.nil?
301
+ data.gsub!(/^\r*\n/, "")
302
+ line, data = data.split(/\r*\n/, 2)
303
+ size, ext = line.split(/;/, 2)
304
+ size = size.hex
305
+ end
306
+ end
307
+ end
308
+
309
+ def to_s
310
+ @data
311
+ end
312
+ end
313
+
314
+ class NoAddressException < StandardError
315
+ end
316
+
317
+ def self.getaddress(host)
318
+ if not @@hosts.include?(host)
319
+ @@hosts[host] = ""
320
+ evtimeout(5) do # ??? Doet 'ut niet?...
321
+ @@hosts[host] = IPSocket.getaddress(host)
322
+ end
323
+ end
324
+
325
+ raise NoAddressException, host if @@hosts[host].empty?
326
+
327
+ @@hosts[host]
328
+ end
329
+
330
+ def self.head(uri, form={}, recursive=true)
331
+ header = Header.new(nil)
332
+
333
+ begin
334
+ while not uri.nil?
335
+ uri = EVURI.new(uri) if uri.kind_of? String
336
+ host = uri.host
337
+ port = uri.port
338
+
339
+ if $proxy.nil? or $proxy.empty? or host == "localhost"
340
+ io = nil
341
+
342
+ @@mutex.synchronize do
343
+ io = TCPSocket.new(getaddress(host), port.zero? ? 80 : port)
344
+ end
345
+
346
+ io.write("HEAD #{uri.path or '/'}#{uri.varstring.empty? ? '' : '?' + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\n\r\n")
347
+ else
348
+ proxy = EVURI.new($proxy)
349
+ io = TCPSocket.new(proxy.host, proxy.port.zero? ? 8080 : proxy.port)
350
+
351
+ io.write("HEAD #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}\r\n\r\n")
352
+ end
353
+
354
+ io.close_write
355
+
356
+ res = io.read
357
+
358
+ io.close_read
359
+
360
+ header, data = nil, nil
361
+ header, data = res.split(/\r*\n\r*\n/, 2) if not res.nil?
362
+ header = Header.new(header)
363
+
364
+ if recursive and header.header["location"] != uri.to_s
365
+ uri = EVURI.new(uri) + header.header["location"]
366
+ else
367
+ uri = nil
368
+ end
369
+ end
370
+ rescue Errno::ECONNRESET, Errno::EHOSTUNREACH => e
371
+ $stderr.puts e.message
372
+ sleep 1
373
+ retry
374
+ rescue Errno::ECONNREFUSED => e
375
+ data = nil
376
+ rescue NoAddressException => e
377
+ $stderr.puts e.message
378
+ header = Header.new(nil)
379
+ end
380
+
381
+ GC.start
382
+
383
+ return header
384
+ end
385
+
386
+ def self.get(uri, httpheader={}, form={})
387
+ post = Array.new
388
+ form.each_pair do |var, value|
389
+ post << "#{var.to_html}=#{value.to_html}"
390
+ end
391
+ post = post.join("?")
392
+
393
+ data = nil
394
+
395
+ begin
396
+ while not uri.nil?
397
+ uri = EVURI.new(uri) if uri.kind_of? String
398
+ host = uri.host
399
+ port = uri.port
400
+
401
+ if $proxy.nil? or $proxy.empty? or host == "localhost"
402
+ io = nil
403
+ @@mutex.synchronize do
404
+ io = TCPSocket.new(getaddress(host), port.zero? ? 80 : port)
405
+ end
406
+
407
+ if post.empty?
408
+ io.write "GET %s%s HTTP/1.0\r\n" % [(uri.path or '/'), (uri.varstring.empty? ? '' : '?' + uri.varstring)]
409
+ else
410
+ io.write "POST %s%s HTTP/1.0\r\n" % [(uri.path or '/'), (uri.varstring.empty? ? '' : '?' + uri.varstring)]
411
+ end
412
+ else
413
+ proxy = EVURI.new($proxy)
414
+ io = TCPSocket.new(proxy.host, proxy.port.zero? ? 8080 : proxy.port)
415
+
416
+ if post.empty?
417
+ io.write "GET %s HTTP/1.0\r\n" % uri
418
+ else
419
+ io.write "POST %s HTTP/1.0\r\n" % uri
420
+ end
421
+ end
422
+
423
+ io.write "Host: %s\r\n" % host
424
+ io.write "User-Agent: xyz\r\n"
425
+ io.write "Proxy-Authorization: Basic %s\r\n" % $proxy_auth unless $proxy_auth.nil?
426
+ #io.write "Accept-Encoding: deflate\r\n"
427
+ #io.write "Accept-Charset: ISO-8859-1\r\n"
428
+ io.write "Connection: close\r\n"
429
+ io.write "Content-Type: application/x-www-form-urlencoded\r\n" unless post.empty?
430
+ io.write "Content-Length: %s\r\n" % post.length unless post.empty?
431
+ httpheader.each do |k, v|
432
+ $stderr.puts "%s: %s\r\n" % [k, v]
433
+ io.write "%s: %s\r\n" % [k, v]
434
+ end
435
+ io.write "\r\n"
436
+ io.write post unless post.empty?
437
+
438
+ io.close_write
439
+
440
+ res = io.read
441
+
442
+ io.close_read
443
+
444
+ header, data = nil, nil
445
+ header, data = res.split(/\r*\n\r*\n/, 2) if not res.nil?
446
+
447
+ header = Header.new(header)
448
+ length = header.header["content-length"]
449
+ data = "" if length == "0"
450
+
451
+ if header.header["location"] != uri.to_s
452
+ uri = EVURI.new(uri) + header.header["location"]
453
+ else
454
+ uri = nil
455
+ end
456
+
457
+ if header.header["transfer-encoding"] == "chunked"
458
+ data = Chunk.new(data).to_s if not data.nil?
459
+ end
460
+
461
+ #if header.header["content-encoding"] == "gzip"
462
+ #data = "gzip -d".exec(data) if not data.nil?
463
+ #end
464
+
465
+ data = nil unless header.code == 200
466
+ end
467
+ rescue Errno::ECONNRESET, Errno::EHOSTUNREACH => e
468
+ $stderr.puts e.message
469
+ sleep 1
470
+ retry
471
+ rescue Errno::ECONNREFUSED => e
472
+ data = nil
473
+ rescue NoAddressException, Errno::ECONNREFUSED => e
474
+ $stderr.puts e.message
475
+ data = nil
476
+ end
477
+
478
+ GC.start
479
+
480
+ return data
481
+ end
482
+
483
+ def self.head_from_cache(uri, form={})
484
+ from_cache("head", uri, form)
485
+ end
486
+
487
+ def self.get_from_cache(uri, form={})
488
+ from_cache("get", uri, form)
489
+ end
490
+
491
+ def self.from_cache(action, uri, form)
492
+ loc = uri.to_s + form.sort.inspect
493
+ hash = MD5.new("#{@@versie} #{loc}")
494
+
495
+ dir = "#{temp}/evcache.#{user}/httpclient.#{action}"
496
+ file = "#{dir}/#{hash}"
497
+ data = nil
498
+
499
+ File.mkpath(dir)
500
+
501
+ expire = 356*24*60*60
502
+
503
+ if File.file?(file) and (Time.new.to_f - File.stat(file).mtime.to_f < expire)
504
+ @@mutex.synchronize do
505
+ File.open(file, "rb") {|f| data = f.read}
506
+ end
507
+ else
508
+ data = method(action).call(uri, form)
509
+
510
+ if not data.nil?
511
+ @@mutex.synchronize do
512
+ File.open(file, "wb") {|f| f.write data}
513
+ end
514
+ end
515
+ end
516
+
517
+ return data
518
+ end
519
+ end
520
+
521
+ class RequestGet < Hash
522
+ def initialize(data)
523
+ CGI.parse(data).each do |k, v|
524
+ self[k] = v
525
+ end
526
+ end
527
+ end
528
+
529
+ class RequestPost < Hash
530
+ def initialize(data)
531
+ CGI.parse(data).each do |k, v|
532
+ self[k] = v
533
+ end
534
+ end
535
+ end
536
+
537
+ class RequestRequest
538
+ attr_reader :method
539
+ attr_reader :uri
540
+ attr_reader :path
541
+ attr_reader :data
542
+ attr_reader :protocol
543
+
544
+ def initialize(firstline)
545
+ @method, @uri, @protocol = firstline.split(/ /)
546
+ @path, @data = @uri.split(/\?/)
547
+ @data = "" if @data.nil? # TODO
548
+
549
+ # i = @path.index(/%[[:digit:]]{2}/)
550
+ # while not i.nil?
551
+ # @path = @path[0..(i-1)] + @path[(i+1)..(i+2)].unpack('H2').shift.to_i.chr + @path[(i+3)..-1]
552
+ # i = @path.index(/%[[:digit:]]{2}/)
553
+ # end
554
+ end
555
+
556
+ def to_s
557
+ "#{@method} #{@uri} #{@protocol}\r\n"
558
+ end
559
+
560
+ def inspect
561
+ "(RequestRequest: %s)" % [@method, @path, @data, @protocol].join(", ")
562
+ end
563
+ end
564
+
565
+ def url_unescape(string)
566
+ string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
567
+ [$1.delete('%')].pack('H*')
568
+ end
569
+ end
570
+
571
+ class Request < Hash
572
+ attr_reader :peeraddr
573
+ attr_reader :request
574
+ attr_reader :cookies
575
+ attr_reader :vars
576
+ attr_reader :user
577
+ attr_writer :user
578
+
579
+ def initialize(io)
580
+ @io = io
581
+
582
+ firstline = @io.gets
583
+
584
+ return if firstline.nil?
585
+
586
+ @request = RequestRequest.new(firstline.strip)
587
+
588
+ line = @io.gets
589
+ line = line.strip unless line.nil?
590
+ while not line.nil? and not line.empty?
591
+ key, value = line.split(" ", 2)
592
+ self[key.sub(/:$/, "").downcase] = value
593
+
594
+ line = @io.gets
595
+ line = line.strip unless line.nil?
596
+ end
597
+
598
+ cookie = self["cookie"]
599
+ cookie = "" if cookie.nil?
600
+ @cookies = {}
601
+ cookie.split(/;/).each do |s|
602
+ k, v = s.strip.split(/=/, 2)
603
+ @cookies[k] = v
604
+ end
605
+
606
+ if not @request.method.nil?
607
+ case @request.method.upcase
608
+ when "HEAD"
609
+ when "GET"
610
+ @vars = RequestGet.new(@request.data.nil? ? "" : @request.data)
611
+ when "POST"
612
+ data = (@io.read(self["content-length"].to_i) or "")
613
+ # data = url_unescape(data)
614
+ @vars = RequestPost.new((self["content-type"] == "application/x-www-form-urlencoded") ? data : "")
615
+ else
616
+ $stderr.puts "Unknown request ('#{firstline}')."
617
+ end
618
+ if $DEBUG
619
+ $stderr.puts data
620
+ end
621
+ end
622
+
623
+ @peeraddr = @io.peeraddr
624
+
625
+ @pda = false
626
+ @pda = true if (self.include?("user-agent") and self["user-agent"].downcase.include?("windows ce"))
627
+ @pda = true if (self.include?("user-agent") and self["user-agent"].downcase.include?("handhttp"))
628
+
629
+ @io.close_read
630
+ end
631
+
632
+ def pda?
633
+ @pda
634
+ end
635
+
636
+ def to_s
637
+ res = @request.to_s
638
+ self.each do |k, v|
639
+ res << "#{k}: #{v}\r\n"
640
+ end
641
+ res
642
+ end
643
+
644
+ def inspect
645
+ "(Request: %s)" % [@peeraddr, @request.inspect, @vars.inspect, @cookies.inspect, super].join(", ")
646
+ end
647
+ end
648
+
649
+ class Response < Hash
650
+ attr_writer :response
651
+ attr_writer :file
652
+ attr_reader :cookies
653
+ attr_reader :stop
654
+ attr_reader :at_stop
655
+
656
+ def initialize(io)
657
+ @io = io
658
+ @response = "HTTP/1.0 200 OK"
659
+ @cookies = {}
660
+ @data = ""
661
+ @syncd = false
662
+ @stop = false
663
+ @at_stop = lambda{}
664
+ @file = nil
665
+ end
666
+
667
+ def flush
668
+ sync
669
+
670
+ if @file
671
+ File.open(@file, "rb") do |f|
672
+ while data = f.read(10_000)
673
+ @io.write data
674
+ end
675
+ end
676
+ end
677
+
678
+ @io.close
679
+ end
680
+
681
+ def to_s
682
+ res = "#{@response}\r\n"
683
+ self.each do |k, v|
684
+ res << "#{k}: #{v}\r\n"
685
+ end
686
+
687
+ @cookies.each do |k, v|
688
+ res << "Set-Cookie: %s=%s;\r\n" % [k, v]
689
+ end
690
+
691
+ res
692
+ end
693
+
694
+ def sync
695
+ size = (@data or "").length
696
+
697
+ if @file
698
+ ext = @file.scan(/\.[^\.]*$/)
699
+ ext = ext.shift
700
+ ext = ext[1..-1] unless ext.nil?
701
+ mimetype = EVMime::MimeType[ext]
702
+
703
+ self["Content-Type"] = mimetype unless mimetype.nil?
704
+
705
+ size += File.size(@file) if File.file?(@file)
706
+ end
707
+
708
+ self["Content-Length"] = size
709
+
710
+ @io.write("#{to_s}\r\n") unless @syncd
711
+ @io.write(@data)
712
+ @data = ""
713
+ @syncd = true
714
+ end
715
+
716
+ def << (s)
717
+ @data << s
718
+ end
719
+
720
+ def clean
721
+ @data = ""
722
+ end
723
+
724
+ def inspect
725
+ "(Response: %s)" % [@response, @data].join(", ")
726
+ end
727
+
728
+ def stop(&block)
729
+ @stop = true
730
+ @at_stop = block unless block.nil?
731
+ end
732
+
733
+ def stop?
734
+ @stop
735
+ end
736
+ end
737
+
738
+ class HTTPServerException < Exception
739
+ end
740
+
741
+ class HTTPServer
742
+ def self.serve(portio=80, remote=false, auth=nil, realm="ev/net")
743
+ port, server = portio
744
+
745
+ begin
746
+ server = TCPServer.new(remote ? "0.0.0.0" : "localhost", port) if server.nil?
747
+
748
+ $stderr.puts "Just point your browser to http://localhost:#{port}/ ..."
749
+ rescue
750
+ server = nil
751
+
752
+ $stderr.puts "Port #{port} is in use."
753
+ end
754
+
755
+ if not server.nil?
756
+ count = 0
757
+
758
+ at_exit do
759
+ #$stderr.puts "Received #{count} requests"
760
+ end
761
+
762
+ serverthread =
763
+ Thread.new do
764
+ mutex = Mutex.new
765
+
766
+ Thread.current["threads"] = []
767
+
768
+ every(1, Thread.current) do |thread|
769
+ mutex.synchronize do
770
+ thread["threads"].delete_if{|t| (not t.alive?)}
771
+ end
772
+ end
773
+
774
+ loop do
775
+ io = server.accept
776
+ count += 1
777
+
778
+ thread =
779
+ Thread.new(Thread.current, count) do |parentthread, count2|
780
+ stop = false
781
+
782
+ begin
783
+ begin
784
+ req = Request.new(io)
785
+ resp = Response.new(io)
786
+ rescue
787
+ raise HTTPServerException
788
+ end
789
+
790
+ begin
791
+ ip = req.peeraddr[3]
792
+ rescue NameError
793
+ raise HTTPServerException
794
+ end
795
+
796
+ if (not remote) or (remote and (auth.nil? or auth.empty? or authenticate(auth, realm, req, resp)))
797
+ # $stderr.puts "#{count2} #{Time.new.strftime("%Y-%m-%d %H:%M:%S")} #{ip} #{req.user} #{req.request.to_s.strip}"
798
+ 1 == 1
799
+ begin
800
+ yield(req, resp)
801
+ rescue Exception => e
802
+ mutex.synchronize do
803
+ $stderr.puts e.class.to_s + ": " + e.message
804
+ $stderr.puts e.backtrace.collect{|s| "\t"+s}.join("\n")
805
+ end
806
+ resp["Content-Type"] = "text/plain"
807
+ resp.response = "HTTP/1.0 200 ???"
808
+ resp.clean
809
+ resp << e.class.to_s + ": " + e.message
810
+ resp << "\n"
811
+ resp << "\n"
812
+ resp << e.backtrace.collect{|s| "\t"+s}.join("\n")
813
+ resp << "\n"
814
+ resp << "\n"
815
+ resp << "(You can use the back button and stop the application properly, if appropriate.)"
816
+ end
817
+
818
+ stop = true if resp.stop?
819
+ end
820
+
821
+ begin
822
+ resp.flush
823
+ rescue
824
+ raise HTTPServerException
825
+ end
826
+ rescue HTTPServerException
827
+ end
828
+
829
+ parentthread["stop"] = resp if stop
830
+ end
831
+
832
+ mutex.synchronize do
833
+ Thread.current["threads"] << thread
834
+ end
835
+ end
836
+ end
837
+
838
+ sleep 0.1 while not serverthread["stop"]
839
+
840
+ serverthread["threads"].each {|t| t.join}
841
+
842
+ serverthread["stop"].at_stop.call
843
+
844
+ serverthread.kill
845
+ end
846
+ end
847
+
848
+ def self.authenticate(auth, realm, req, resp)
849
+ if auth.kind_of? String
850
+ file = "#{home}/#{auth}"
851
+ auths = {}
852
+ auths = Hash.file(file) if File.file?(file)
853
+ else
854
+ auths = auth
855
+ end
856
+
857
+ authuserpassword = req["authorization"]
858
+ if not authuserpassword.nil?
859
+ authtype, userpassword = authuserpassword.split(/ /)
860
+ if authtype == "Basic" and not userpassword.nil?
861
+ u, p = userpassword.unpack("m").shift.split(/:/)
862
+ end
863
+ end
864
+
865
+ ok = (auths.include?(u) and auths[u] == p)
866
+
867
+ unless ok
868
+ resp["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
869
+ resp.response = "HTTP/1.0 401 Unauthorized"
870
+ end
871
+
872
+ req.user = u
873
+
874
+ return ok
875
+ end
876
+ end