rwdfoldeditor 0.01

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 (155) hide show
  1. data/Readme.txt +462 -0
  2. data/bin/rwdfoldeditor +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.foldeditor/0uninstallapplet.rb +10 -0
  24. data/code/superant.com.foldeditor/changehypernotename.rb +21 -0
  25. data/code/superant.com.foldeditor/chooselinkfile.rb +6 -0
  26. data/code/superant.com.foldeditor/choosenotefile.rb +6 -0
  27. data/code/superant.com.foldeditor/createnewnotehtml.rb +31 -0
  28. data/code/superant.com.foldeditor/helptexthashrwdhypernote.rb +38 -0
  29. data/code/superant.com.foldeditor/hyperlinkcreatelinkfile.rb +19 -0
  30. data/code/superant.com.foldeditor/listfoldeditorfiles.rb +7 -0
  31. data/code/superant.com.foldeditor/loadfolddocument.rb +21 -0
  32. data/code/superant.com.foldeditor/loadrwdfoldeditlinkfile.rb +19 -0
  33. data/code/superant.com.foldeditor/openhelpwindowrwdhyernote.rb +30 -0
  34. data/code/superant.com.foldeditor/runrwdapplet.rb +10 -0
  35. data/code/superant.com.foldeditor/rwddisplayfoldlinks.rb +33 -0
  36. data/code/superant.com.foldeditor/rwdtinkerversion.rb +10 -0
  37. data/code/superant.com.foldeditor/savefoldlinkfile.rb +20 -0
  38. data/code/superant.com.foldeditor/savehtmlhypernoterecord.rb +20 -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 +27 -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 +18 -0
  66. data/configuration/rwdwfoldeditor-0.01.dist +12 -0
  67. data/configuration/tinkerwin2variables.dist +17 -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.foldeditor/10appletbegin.rwd +4 -0
  84. data/gui/tinkerbackwindows/superant.com.foldeditor/10aviewnote.rwd +42 -0
  85. data/gui/tinkerbackwindows/superant.com.foldeditor/15htmlview.rwd +46 -0
  86. data/gui/tinkerbackwindows/superant.com.foldeditor/56viewfold.rwd +43 -0
  87. data/gui/tinkerbackwindows/superant.com.foldeditor/81jumplinkcommands.rwd +17 -0
  88. data/gui/tinkerbackwindows/superant.com.foldeditor/9end.rwd +6 -0
  89. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/1appname.rwd +5 -0
  90. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/40rwdlistzips.rwd +41 -0
  91. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/45installremotezip.rwd +44 -0
  92. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/50rwdlistapplets.rwd +44 -0
  93. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/60editconfiguration.rwd +30 -0
  94. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +29 -0
  95. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/81jumplinkcommands.rwd +17 -0
  96. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/9backend.rwd +6 -0
  97. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/1appname.rwd +31 -0
  98. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/9end.rwd +4 -0
  99. data/gui/tinkerbackwindows/superant.com.versionwindow/1appname.rwd +19 -0
  100. data/gui/tinkerbackwindows/superant.com.versionwindow/helpaboutwindow.rwd +17 -0
  101. data/gui/zzcoreguiend/yy9rwdend.rwd +4 -0
  102. data/init.rb +277 -0
  103. data/installed/rwdwfoldeditor-0.01.inf +13 -0
  104. data/installed/temp.rb +1 -0
  105. data/lang/en/rwdcore/languagefile.rb +58 -0
  106. data/lang/es/rwdcore/languagefile-es.rb +62 -0
  107. data/lang/fr/rwdcore/languagefile.rb +64 -0
  108. data/lang/jp/rwdcore/languagefile.rb +72 -0
  109. data/lang/nl/rwdcore/languagefile.rb +75 -0
  110. data/lib/rconftool.rb +380 -0
  111. data/lib/rwd/browser.rb +123 -0
  112. data/lib/rwd/ftools.rb +174 -0
  113. data/lib/rwd/mime.rb +328 -0
  114. data/lib/rwd/net.rb +866 -0
  115. data/lib/rwd/ruby.rb +889 -0
  116. data/lib/rwd/rwd.rb +1942 -0
  117. data/lib/rwd/sgml.rb +236 -0
  118. data/lib/rwd/thread.rb +63 -0
  119. data/lib/rwd/tree.rb +371 -0
  120. data/lib/rwd/xml.rb +101 -0
  121. data/lib/zip/ioextras.rb +114 -0
  122. data/lib/zip/stdrubyext.rb +111 -0
  123. data/lib/zip/tempfile_bugfixed.rb +195 -0
  124. data/lib/zip/zip.rb +1378 -0
  125. data/lib/zip/zipfilesystem.rb +558 -0
  126. data/lib/zip/ziprequire.rb +61 -0
  127. data/rwd_files/HowTo_FoldEditor.txt +105 -0
  128. data/rwd_files/HowTo_Tinker.txt +471 -0
  129. data/rwd_files/HowTo_TinkerWin2.txt +202 -0
  130. data/rwd_files/Readme.txt +57 -0
  131. data/rwd_files/RubyWebDialogs.html +6 -0
  132. data/rwd_files/default.fld +9 -0
  133. data/rwd_files/favicon.ico +0 -0
  134. data/rwd_files/rdoc-style.css +175 -0
  135. data/rwd_files/rwdapplications.html +54 -0
  136. data/rwd_files/rwdhypernote-0.13.fld +202 -0
  137. data/rwd_files/tinker.png +0 -0
  138. data/rwdconfig.dist +21 -0
  139. data/rwdfoldeditor.rb +1 -0
  140. data/tests/RubyGauge.rb +179 -0
  141. data/tests/checkdepends.sh +4 -0
  142. data/tests/cleancnf.sh +6 -0
  143. data/tests/makedist-rwdwfoldeditor.rb +56 -0
  144. data/tests/makedist.rb +66 -0
  145. data/tests/rdep.rb +354 -0
  146. data/tests/totranslate.lang +93 -0
  147. data/zips/rwdwaddresses-1.05.zip +0 -0
  148. data/zips/rwdwcalc-0.61.zip +0 -0
  149. data/zips/rwdwfoldeditor-0.01.zip +0 -0
  150. data/zips/rwdwgutenberg-0.09.zip +0 -0
  151. data/zips/rwdwschedule-1.04.zip +0 -0
  152. data/zips/rwdwshell-1.04.zip +0 -0
  153. data/zips/temp.rb +1 -0
  154. data/zips/wrubyslippers-1.06.zip +0 -0
  155. metadata +212 -0
data/lib/rwd/net.rb ADDED
@@ -0,0 +1,866 @@
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
+ class Request < Hash
566
+ attr_reader :peeraddr
567
+ attr_reader :request
568
+ attr_reader :cookies
569
+ attr_reader :vars
570
+ attr_reader :user
571
+ attr_writer :user
572
+
573
+ def initialize(io)
574
+ @io = io
575
+
576
+ firstline = @io.gets
577
+
578
+ return if firstline.nil?
579
+
580
+ @request = RequestRequest.new(firstline.strip)
581
+
582
+ line = @io.gets
583
+ line = line.strip unless line.nil?
584
+ while not line.nil? and not line.empty?
585
+ key, value = line.split(" ", 2)
586
+ self[key.sub(/:$/, "").downcase] = value
587
+
588
+ line = @io.gets
589
+ line = line.strip unless line.nil?
590
+ end
591
+
592
+ cookie = self["cookie"]
593
+ cookie = "" if cookie.nil?
594
+ @cookies = {}
595
+ cookie.split(/;/).each do |s|
596
+ k, v = s.strip.split(/=/, 2)
597
+ @cookies[k] = v
598
+ end
599
+
600
+ if not @request.method.nil?
601
+ case @request.method.upcase
602
+ when "HEAD"
603
+ when "GET"
604
+ @vars = RequestGet.new(@request.data.nil? ? "" : @request.data)
605
+ when "POST"
606
+ data = (@io.read(self["content-length"].to_i) or "")
607
+ @vars = RequestPost.new((self["content-type"] == "application/x-www-form-urlencoded") ? data : "")
608
+ else
609
+ $stderr.puts "Unknown request ('#{firstline}')."
610
+ end
611
+ end
612
+
613
+ @peeraddr = @io.peeraddr
614
+
615
+ @pda = false
616
+ @pda = true if (self.include?("user-agent") and self["user-agent"].downcase.include?("windows ce"))
617
+ @pda = true if (self.include?("user-agent") and self["user-agent"].downcase.include?("handhttp"))
618
+
619
+ @io.close_read
620
+ end
621
+
622
+ def pda?
623
+ @pda
624
+ end
625
+
626
+ def to_s
627
+ res = @request.to_s
628
+ self.each do |k, v|
629
+ res << "#{k}: #{v}\r\n"
630
+ end
631
+ res
632
+ end
633
+
634
+ def inspect
635
+ "(Request: %s)" % [@peeraddr, @request.inspect, @vars.inspect, @cookies.inspect, super].join(", ")
636
+ end
637
+ end
638
+
639
+ class Response < Hash
640
+ attr_writer :response
641
+ attr_writer :file
642
+ attr_reader :cookies
643
+ attr_reader :stop
644
+ attr_reader :at_stop
645
+
646
+ def initialize(io)
647
+ @io = io
648
+ @response = "HTTP/1.0 200 OK"
649
+ @cookies = {}
650
+ @data = ""
651
+ @syncd = false
652
+ @stop = false
653
+ @at_stop = lambda{}
654
+ @file = nil
655
+ end
656
+
657
+ def flush
658
+ sync
659
+
660
+ if @file
661
+ File.open(@file, "rb") do |f|
662
+ while data = f.read(10_000)
663
+ @io.write data
664
+ end
665
+ end
666
+ end
667
+
668
+ @io.close
669
+ end
670
+
671
+ def to_s
672
+ res = "#{@response}\r\n"
673
+ self.each do |k, v|
674
+ res << "#{k}: #{v}\r\n"
675
+ end
676
+
677
+ @cookies.each do |k, v|
678
+ res << "Set-Cookie: %s=%s;\r\n" % [k, v]
679
+ end
680
+
681
+ res
682
+ end
683
+
684
+ def sync
685
+ size = (@data or "").length
686
+
687
+ if @file
688
+ ext = @file.scan(/\.[^\.]*$/)
689
+ ext = ext.shift
690
+ ext = ext[1..-1] unless ext.nil?
691
+ mimetype = EVMime::MimeType[ext]
692
+
693
+ self["Content-Type"] = mimetype unless mimetype.nil?
694
+
695
+ size += File.size(@file) if File.file?(@file)
696
+ end
697
+
698
+ self["Content-Length"] = size
699
+
700
+ @io.write("#{to_s}\r\n") unless @syncd
701
+ @io.write(@data)
702
+ @data = ""
703
+ @syncd = true
704
+ end
705
+
706
+ def << (s)
707
+ @data << s
708
+ end
709
+
710
+ def clean
711
+ @data = ""
712
+ end
713
+
714
+ def inspect
715
+ "(Response: %s)" % [@response, @data].join(", ")
716
+ end
717
+
718
+ def stop(&block)
719
+ @stop = true
720
+ @at_stop = block unless block.nil?
721
+ end
722
+
723
+ def stop?
724
+ @stop
725
+ end
726
+ end
727
+
728
+ class HTTPServerException < Exception
729
+ end
730
+
731
+ class HTTPServer
732
+ def self.serve(portio=80, remote=false, auth=nil, realm="ev/net")
733
+ port, server = portio
734
+
735
+ begin
736
+ server = TCPServer.new(remote ? "0.0.0.0" : "localhost", port) if server.nil?
737
+
738
+ $stderr.puts "Just point your browser to http://localhost:#{port}/ ..."
739
+ rescue
740
+ server = nil
741
+
742
+ $stderr.puts "Port #{port} is in use."
743
+ end
744
+
745
+ if not server.nil?
746
+ count = 0
747
+
748
+ at_exit do
749
+ #$stderr.puts "Received #{count} requests"
750
+ end
751
+
752
+ serverthread =
753
+ Thread.new do
754
+ mutex = Mutex.new
755
+
756
+ Thread.current["threads"] = []
757
+
758
+ every(1, Thread.current) do |thread|
759
+ mutex.synchronize do
760
+ thread["threads"].delete_if{|t| (not t.alive?)}
761
+ end
762
+ end
763
+
764
+ loop do
765
+ io = server.accept
766
+ count += 1
767
+
768
+ thread =
769
+ Thread.new(Thread.current, count) do |parentthread, count2|
770
+ stop = false
771
+
772
+ begin
773
+ begin
774
+ req = Request.new(io)
775
+ resp = Response.new(io)
776
+ rescue
777
+ raise HTTPServerException
778
+ end
779
+
780
+ begin
781
+ ip = req.peeraddr[3]
782
+ rescue NameError
783
+ raise HTTPServerException
784
+ end
785
+
786
+ if (not remote) or (remote and (auth.nil? or auth.empty? or authenticate(auth, realm, req, resp)))
787
+ # $stderr.puts "#{count2} #{Time.new.strftime("%Y-%m-%d %H:%M:%S")} #{ip} #{req.user} #{req.request.to_s.strip}"
788
+ 1 == 1
789
+ begin
790
+ yield(req, resp)
791
+ rescue Exception => e
792
+ mutex.synchronize do
793
+ $stderr.puts e.class.to_s + ": " + e.message
794
+ $stderr.puts e.backtrace.collect{|s| "\t"+s}.join("\n")
795
+ end
796
+ resp["Content-Type"] = "text/plain"
797
+ resp.response = "HTTP/1.0 200 ???"
798
+ resp.clean
799
+ resp << e.class.to_s + ": " + e.message
800
+ resp << "\n"
801
+ resp << "\n"
802
+ resp << e.backtrace.collect{|s| "\t"+s}.join("\n")
803
+ resp << "\n"
804
+ resp << "\n"
805
+ resp << "(You can use the back button and stop the application properly, if appropriate.)"
806
+ end
807
+
808
+ stop = true if resp.stop?
809
+ end
810
+
811
+ begin
812
+ resp.flush
813
+ rescue
814
+ raise HTTPServerException
815
+ end
816
+ rescue HTTPServerException
817
+ end
818
+
819
+ parentthread["stop"] = resp if stop
820
+ end
821
+
822
+ mutex.synchronize do
823
+ Thread.current["threads"] << thread
824
+ end
825
+ end
826
+ end
827
+
828
+ sleep 0.1 while not serverthread["stop"]
829
+
830
+ serverthread["threads"].each {|t| t.join}
831
+
832
+ serverthread["stop"].at_stop.call
833
+
834
+ serverthread.kill
835
+ end
836
+ end
837
+
838
+ def self.authenticate(auth, realm, req, resp)
839
+ if auth.kind_of? String
840
+ file = "#{home}/#{auth}"
841
+ auths = {}
842
+ auths = Hash.file(file) if File.file?(file)
843
+ else
844
+ auths = auth
845
+ end
846
+
847
+ authuserpassword = req["authorization"]
848
+ if not authuserpassword.nil?
849
+ authtype, userpassword = authuserpassword.split(/ /)
850
+ if authtype == "Basic" and not userpassword.nil?
851
+ u, p = userpassword.unpack("m").shift.split(/:/)
852
+ end
853
+ end
854
+
855
+ ok = (auths.include?(u) and auths[u] == p)
856
+
857
+ unless ok
858
+ resp["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
859
+ resp.response = "HTTP/1.0 401 Unauthorized"
860
+ end
861
+
862
+ req.user = u
863
+
864
+ return ok
865
+ end
866
+ end