rwdlanguage 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 (187) hide show
  1. data/Readme.txt +475 -0
  2. data/bin/rwdlanguage +19 -0
  3. data/code/01rwdcore/01rwdcore.rb +29 -0
  4. data/code/01rwdcore/02helptexthashbegin.rb +16 -0
  5. data/code/01rwdcore/03helptexthash.rb +21 -0
  6. data/code/01rwdcore/jumplinkcommand.rb +36 -0
  7. data/code/01rwdcore/openhelpwindow.rb +38 -0
  8. data/code/01rwdcore/returntomain.rb +10 -0
  9. data/code/01rwdcore/rundocuments.rb +10 -0
  10. data/code/01rwdcore/runeditconfiguration.rb +10 -0
  11. data/code/01rwdcore/runhelpabout.rb +15 -0
  12. data/code/01rwdcore/runopentinkerdocument.rb +7 -0
  13. data/code/01rwdcore/runtab.rb +15 -0
  14. data/code/01rwdcore/rwdtinkerversion.rb +22 -0
  15. data/code/01rwdcore/rwdwindowreturn.rb +9 -0
  16. data/code/01rwdcore/selectiontab.rb +11 -0
  17. data/code/01rwdcore/setuphelpaboutoptions.rb +15 -0
  18. data/code/01rwdcore/setuptinkerdocuments.rb +7 -0
  19. data/code/01rwdcore/test_cases.rb +158 -0
  20. data/code/01rwdcore/test_harness.rb +20 -0
  21. data/code/01rwdcore/uploadreturns.rb +65 -0
  22. data/code/dd0viewphoto/dd0viewphoto.rb +5 -0
  23. data/code/superant.com.language/0uninstallapplet.rb +22 -0
  24. data/code/superant.com.language/googlelang.rb +25 -0
  25. data/code/superant.com.language/helptexthashload.rb +22 -0
  26. data/code/superant.com.language/loadconfigurationrecord.rb +22 -0
  27. data/code/superant.com.language/loadconfigurationvariables.rb +14 -0
  28. data/code/superant.com.language/openhelpwindow.rb +24 -0
  29. data/code/superant.com.language/rubySteak.rb +40 -0
  30. data/code/superant.com.language/runappletwindow.rb +12 -0
  31. data/code/superant.com.language/runrwdshellwindow.rb +12 -0
  32. data/code/superant.com.language/runrwdwordsbackwindow.rb +10 -0
  33. data/code/superant.com.language/rwdtinkerversion.rb +10 -0
  34. data/code/superant.com.language/saveconfigurationrecord.rb +20 -0
  35. data/code/superant.com.language/test_cases.rb +20 -0
  36. data/code/superant.com.rwdtinkerbackwindow/changelocale.rb +84 -0
  37. data/code/superant.com.rwdtinkerbackwindow/diagnostictab.rb +19 -0
  38. data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +169 -0
  39. data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +38 -0
  40. data/code/superant.com.rwdtinkerbackwindow/installremotegem.rb +20 -0
  41. data/code/superant.com.rwdtinkerbackwindow/listgemdirs.rb +12 -0
  42. data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +55 -0
  43. data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +14 -0
  44. data/code/superant.com.rwdtinkerbackwindow/listzips.rb +37 -0
  45. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +24 -0
  46. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationvariables.rb +14 -0
  47. data/code/superant.com.rwdtinkerbackwindow/network.rb +87 -0
  48. data/code/superant.com.rwdtinkerbackwindow/openappletname.rb +19 -0
  49. data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +40 -0
  50. data/code/superant.com.rwdtinkerbackwindow/remotegemlist.rb +24 -0
  51. data/code/superant.com.rwdtinkerbackwindow/removeapplet.rb +46 -0
  52. data/code/superant.com.rwdtinkerbackwindow/removeappletvariables.rb +52 -0
  53. data/code/superant.com.rwdtinkerbackwindow/runremoteinstall.rb +11 -0
  54. data/code/superant.com.rwdtinkerbackwindow/runrwdtinkerbackwindow.rb +15 -0
  55. data/code/superant.com.rwdtinkerbackwindow/rwdtinkerwin2version.rb +13 -0
  56. data/code/superant.com.rwdtinkerbackwindow/saveconfigurationrecord.rb +19 -0
  57. data/code/superant.com.rwdtinkerbackwindow/showlocaleoptions.rb +9 -0
  58. data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +23 -0
  59. data/code/superant.com.rwdtinkerbackwindow/viewgemappletcontents.rb +24 -0
  60. data/code/superant.com.rwdtinkerbackwindow/viewlogfile.rb +16 -0
  61. data/code/superant.com.thesaurus/clearhttpview3.rb +9 -0
  62. data/code/superant.com.thesaurus/listwordlookup.rb +37 -0
  63. data/code/superant.com.thesaurus/runappletwindow.rb +12 -0
  64. data/code/superant.com.words/dictlookup.rb +20 -0
  65. data/code/superant.com.words/runrwdwordsbackwindow.rb +10 -0
  66. data/code/superant.com.words/rwdtinkerversion.rb +10 -0
  67. data/code/zz0applicationend/zz0end.rb +5 -0
  68. data/configuration/rwdtinker.dist +15 -0
  69. data/configuration/rwdwlanguage.dist +21 -0
  70. data/configuration/tinkerwin2variables.dist +23 -0
  71. data/gui/00coreguibegin/applicationguitop.rwd +9 -0
  72. data/gui/frontwindow0/cc0openphoto.rwd +22 -0
  73. data/gui/frontwindowselections/00selectiontabbegin.rwd +11 -0
  74. data/gui/frontwindowselections/jumplinkcommands.rwd +15 -0
  75. data/gui/frontwindowselections/wwselectionend.rwd +3 -0
  76. data/gui/frontwindowtdocuments/00documentbegin.rwd +6 -0
  77. data/gui/frontwindowtdocuments/tinkerdocuments.rwd +14 -0
  78. data/gui/frontwindowtdocuments/zzdocumentend.rwd +8 -0
  79. data/gui/helpaboutbegin/zzzrwdlasttab.rwd +6 -0
  80. data/gui/helpaboutbegin/zzzzhelpscreenstart.rwd +3 -0
  81. data/gui/helpaboutbegin/zzzzzzhelpabouttab.rwd +15 -0
  82. data/gui/helpaboutzend/helpscreenend.rwd +3 -0
  83. data/gui/helpaboutzend/zhelpscreenstart2.rwd +3 -0
  84. data/gui/helpaboutzend/zzzzhelpabout2.rwd +15 -0
  85. data/gui/helpaboutzend/zzzzhelpscreen2end.rwd +3 -0
  86. data/gui/tinkerbackwindows/superant.com.language/1appname.rwd +4 -0
  87. data/gui/tinkerbackwindows/superant.com.language/22google.rwd +38 -0
  88. data/gui/tinkerbackwindows/superant.com.language/44germany.rwd +19 -0
  89. data/gui/tinkerbackwindows/superant.com.language/67viewconfiguration.rwd +27 -0
  90. data/gui/tinkerbackwindows/superant.com.language/77jumplinkcommands.rwd +17 -0
  91. data/gui/tinkerbackwindows/superant.com.language/z9end.rwd +6 -0
  92. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/1appname.rwd +5 -0
  93. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/40rwdlistzips.rwd +41 -0
  94. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/45installremotezip.rwd +44 -0
  95. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/50rwdlistapplets.rwd +44 -0
  96. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/60editconfiguration.rwd +30 -0
  97. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +29 -0
  98. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/75rwdlogfile.rwd +20 -0
  99. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/80localechanger.rwd +17 -0
  100. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/81jumplinkcommands.rwd +17 -0
  101. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/9backend.rwd +6 -0
  102. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/1appname.rwd +31 -0
  103. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/9end.rwd +4 -0
  104. data/gui/tinkerbackwindows/superant.com.versionwindow/1appname.rwd +19 -0
  105. data/gui/tinkerbackwindows/superant.com.versionwindow/helpaboutwindow.rwd +17 -0
  106. data/gui/tinkerbackwindows/superant.com.words/1appname.rwd +4 -0
  107. data/gui/tinkerbackwindows/superant.com.words/1dictionary.rwd +19 -0
  108. data/gui/tinkerbackwindows/superant.com.words/4thesaurus.rwd +36 -0
  109. data/gui/tinkerbackwindows/superant.com.words/77jumplinkcommands.rwd +17 -0
  110. data/gui/tinkerbackwindows/superant.com.words/z9end.rwd +6 -0
  111. data/gui/zzcoreguiend/yy9rwdend.rwd +4 -0
  112. data/init.rb +179 -0
  113. data/installed/rwdwlanguage.inf +24 -0
  114. data/installed/temp.rb +1 -0
  115. data/lang/en/rwdcore/en.po +197 -0
  116. data/lang/en/rwdlanguage/en.po +32 -0
  117. data/lang/es/rwdcore/es.po +184 -0
  118. data/lang/es/rwdlanguage/en.po +32 -0
  119. data/lang/fr/rwdcore/fr.po +169 -0
  120. data/lang/fr/rwdlanguage/en.po +32 -0
  121. data/lang/hi/rwdcore/hi.po +173 -0
  122. data/lang/hi/rwdlanguage/en.po +32 -0
  123. data/lang/ja/rwdcore/ja.po +171 -0
  124. data/lang/ja/rwdlanguage/en.po +32 -0
  125. data/lang/nl/rwdcore/nl.po +169 -0
  126. data/lang/nl/rwdlanguage/en.po +32 -0
  127. data/lib/dict.rb +438 -0
  128. data/lib/g_translate.rb +43 -0
  129. data/lib/g_translate/client.rb +84 -0
  130. data/lib/g_translate/translator.rb +57 -0
  131. data/lib/ger-eng.txt +111283 -0
  132. data/lib/oothesaurus.rb +76 -0
  133. data/lib/rconftool.rb +387 -0
  134. data/lib/rwd/browser.rb +123 -0
  135. data/lib/rwd/ftools.rb +174 -0
  136. data/lib/rwd/mime.rb +328 -0
  137. data/lib/rwd/net.rb +877 -0
  138. data/lib/rwd/ruby.rb +889 -0
  139. data/lib/rwd/rwd.rb +1425 -0
  140. data/lib/rwd/sgml.rb +236 -0
  141. data/lib/rwd/thread.rb +63 -0
  142. data/lib/rwd/tree.rb +371 -0
  143. data/lib/rwd/xml.rb +101 -0
  144. data/lib/rwdthemes/default.rwd +317 -0
  145. data/lib/rwdthemes/pda.rwd +72 -0
  146. data/lib/rwdthemes/windowslike.rwd +171 -0
  147. data/lib/rwdtinker/rwdcodedir.rb +56 -0
  148. data/lib/rwdtinker/rwdguidir.rb +57 -0
  149. data/lib/rwdtinker/rwdlangdir.rb +60 -0
  150. data/lib/rwdtinker/rwdtinkertools.rb +25 -0
  151. data/lib/zip/ioextras.rb +155 -0
  152. data/lib/zip/stdrubyext.rb +111 -0
  153. data/lib/zip/tempfile_bugfixed.rb +195 -0
  154. data/lib/zip/zip.rb +1847 -0
  155. data/lib/zip/zipfilesystem.rb +609 -0
  156. data/lib/zip/ziprequire.rb +90 -0
  157. data/rwd_files/HowTo_Language.txt +179 -0
  158. data/rwd_files/HowTo_Tinker.txt +515 -0
  159. data/rwd_files/HowTo_TinkerWin2.txt +202 -0
  160. data/rwd_files/Readme.txt +57 -0
  161. data/rwd_files/RubyWebDialogs.html +6 -0
  162. data/rwd_files/Tinkerhelptexthash.txt +84 -0
  163. data/rwd_files/favicon.ico +0 -0
  164. data/rwd_files/log/rwdtinker.log +726 -0
  165. data/rwd_files/rdoc-style.css +175 -0
  166. data/rwd_files/rwdapplications.html +76 -0
  167. data/rwd_files/rwdlanguagehelpfiles.txt +34 -0
  168. data/rwd_files/tinker.png +0 -0
  169. data/rwdconfig.dist +24 -0
  170. data/rwdlanguage.rb +1 -0
  171. data/tests/RubyGauge.rb +179 -0
  172. data/tests/checkdepends.sh +4 -0
  173. data/tests/cleancnf.sh +6 -0
  174. data/tests/makedist-rwdwlanguage.rb +56 -0
  175. data/tests/makedist.rb +66 -0
  176. data/tests/rdep.rb +354 -0
  177. data/tests/totranslate.lang +93 -0
  178. data/zips/rwdwcalc-0.63.zip +0 -0
  179. data/zips/rwdwfoldeditor-0.08.zip +0 -0
  180. data/zips/rwdwhypernote-0.16.zip +0 -0
  181. data/zips/rwdwlanguage-0.01.zip +0 -0
  182. data/zips/rwdwmovies-0.98.zip +0 -0
  183. data/zips/rwdwruby-1.08.zip +0 -0
  184. data/zips/temp.rb +1 -0
  185. data/zips/tinkerbellw-0.04.zip +0 -0
  186. data/zips/wrubyslippers-1.08.zip +0 -0
  187. metadata +246 -0
data/lib/rwd/net.rb ADDED
@@ -0,0 +1,877 @@
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
+
619
+ $rwdtinkerlog.debug data
620
+
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="rwd/net")
743
+ port, server = portio
744
+
745
+ begin
746
+ server = TCPServer.new(remote ? "0.0.0.0" : "localhost", port) if server.nil?
747
+ if $DEBUG
748
+ $stderr.puts "Just point your browser to http://localhost:#{port}/ ..."
749
+ end
750
+ rescue
751
+ server = nil
752
+
753
+ $stderr.puts "Port #{port} is in use."
754
+ end
755
+
756
+ if not server.nil?
757
+ count = 0
758
+
759
+ at_exit do
760
+ #$stderr.puts "Received #{count} requests"
761
+ end
762
+
763
+ serverthread =
764
+ Thread.new do
765
+ mutex = Mutex.new
766
+
767
+ Thread.current["threads"] = []
768
+
769
+ every(1, Thread.current) do |thread|
770
+ mutex.synchronize do
771
+ thread["threads"].delete_if{|t| (not t.alive?)}
772
+ end
773
+ end
774
+
775
+ loop do
776
+ io = server.accept
777
+ count += 1
778
+
779
+ thread =
780
+ Thread.new(Thread.current, count) do |parentthread, count2|
781
+ stop = false
782
+
783
+ begin
784
+ begin
785
+ req = Request.new(io)
786
+ resp = Response.new(io)
787
+ rescue
788
+ raise HTTPServerException
789
+ end
790
+
791
+ begin
792
+ ip = req.peeraddr[3]
793
+ rescue NameError
794
+ raise HTTPServerException
795
+ end
796
+
797
+ if (not remote) or (remote and (auth.nil? or auth.empty? or authenticate(auth, realm, req, resp)))
798
+ # $stderr.puts "#{count2} #{Time.new.strftime("%Y-%m-%d %H:%M:%S")} #{ip} #{req.user} #{req.request.to_s.strip}"
799
+ 1 == 1
800
+ begin
801
+ yield(req, resp)
802
+ rescue Exception => e
803
+ mutex.synchronize do
804
+ $stderr.puts e.class.to_s + ": " + e.message
805
+ $stderr.puts e.backtrace.collect{|s| "\t"+s}.join("\n")
806
+ end
807
+ resp["Content-Type"] = "text/plain"
808
+ resp.response = "HTTP/1.0 200 ???"
809
+ resp.clean
810
+ resp << e.class.to_s + ": " + e.message
811
+ resp << "\n"
812
+ resp << "\n"
813
+ resp << e.backtrace.collect{|s| "\t"+s}.join("\n")
814
+ resp << "\n"
815
+ resp << "\n"
816
+ resp << "(You can use the back button and stop the application properly, if appropriate.)"
817
+ end
818
+
819
+ stop = true if resp.stop?
820
+ end
821
+
822
+ begin
823
+ resp.flush
824
+ rescue
825
+ raise HTTPServerException
826
+ end
827
+ rescue HTTPServerException
828
+ end
829
+
830
+ parentthread["stop"] = resp if stop
831
+ end
832
+
833
+ mutex.synchronize do
834
+ Thread.current["threads"] << thread
835
+ end
836
+ end
837
+ end
838
+
839
+ sleep 0.1 while not serverthread["stop"]
840
+
841
+ serverthread["threads"].each {|t| t.join}
842
+
843
+ serverthread["stop"].at_stop.call
844
+
845
+ serverthread.kill
846
+ end
847
+ end
848
+
849
+ def self.authenticate(auth, realm, req, resp)
850
+ if auth.kind_of? String
851
+ file = "#{home}/#{auth}"
852
+ auths = {}
853
+ auths = Hash.file(file) if File.file?(file)
854
+ else
855
+ auths = auth
856
+ end
857
+
858
+ authuserpassword = req["authorization"]
859
+ if not authuserpassword.nil?
860
+ authtype, userpassword = authuserpassword.split(/ /)
861
+ if authtype == "Basic" and not userpassword.nil?
862
+ u, p = userpassword.unpack("m").shift.split(/:/)
863
+ end
864
+ end
865
+
866
+ ok = (auths.include?(u) and auths[u] == p)
867
+
868
+ unless ok
869
+ resp["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
870
+ resp.response = "HTTP/1.0 401 Unauthorized"
871
+ end
872
+
873
+ req.user = u
874
+
875
+ return ok
876
+ end
877
+ end