watobo 0.9.21 → 0.9.23

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 (283) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +46 -1
  3. data/bin/nfq_server.rb +0 -9
  4. data/bin/watobo_gui.rb +3 -13
  5. data/custom-views/prettify-json.rb +9 -18
  6. data/icons/watobo.ico +0 -0
  7. data/icons/watobo.ico.old +0 -0
  8. data/lib/watobo.rb +10 -19
  9. data/lib/watobo/adapters.rb +5 -14
  10. data/lib/watobo/adapters/data_store.rb +50 -59
  11. data/lib/watobo/adapters/file/file_store.rb +287 -296
  12. data/lib/watobo/adapters/file/marshal_store.rb +293 -296
  13. data/lib/watobo/adapters/session_store.rb +5 -14
  14. data/lib/watobo/ca.rb +1 -10
  15. data/lib/watobo/config.rb +197 -206
  16. data/lib/watobo/constants.rb +0 -9
  17. data/lib/watobo/core.rb +3 -12
  18. data/lib/watobo/core/active_check.rb +72 -135
  19. data/lib/watobo/core/active_checks.rb +49 -58
  20. data/lib/watobo/core/ca.rb +369 -389
  21. data/lib/watobo/core/cert_store.rb +34 -43
  22. data/lib/watobo/core/chat.rb +92 -101
  23. data/lib/watobo/core/chats.rb +271 -280
  24. data/lib/watobo/core/client_cert_store.rb +106 -35
  25. data/lib/watobo/core/conversation.rb +48 -57
  26. data/lib/watobo/core/cookie.rb +23 -32
  27. data/lib/watobo/core/egress_handlers.rb +98 -0
  28. data/lib/watobo/core/finding.rb +66 -75
  29. data/lib/watobo/core/findings.rb +107 -114
  30. data/lib/watobo/core/forwarding_proxy.rb +13 -22
  31. data/lib/watobo/core/fuzz_gen.rb +0 -9
  32. data/lib/watobo/core/intercept_carver.rb +166 -177
  33. data/lib/watobo/core/intercept_filter.rb +235 -244
  34. data/lib/watobo/core/interceptor.rb +98 -107
  35. data/lib/watobo/core/min_class.rb +4 -13
  36. data/lib/watobo/core/netfilter_queue.rb +170 -179
  37. data/lib/watobo/core/ott_cache.rb +132 -141
  38. data/lib/watobo/core/parameter.rb +43 -52
  39. data/lib/watobo/core/passive_check.rb +103 -102
  40. data/lib/watobo/core/passive_checks.rb +48 -57
  41. data/lib/watobo/core/passive_scanner.rb +54 -55
  42. data/lib/watobo/core/plugin.rb +11 -20
  43. data/lib/watobo/core/project.rb +3 -9
  44. data/lib/watobo/core/proxy.rb +43 -52
  45. data/lib/watobo/core/request.rb +125 -123
  46. data/lib/watobo/core/response.rb +44 -53
  47. data/lib/watobo/core/scanner.rb +0 -9
  48. data/lib/watobo/core/scanner3.rb +405 -414
  49. data/lib/watobo/core/scope.rb +83 -92
  50. data/lib/watobo/core/session.rb +1043 -1026
  51. data/lib/watobo/core/sid_cache.rb +98 -107
  52. data/lib/watobo/core/subscriber.rb +25 -34
  53. data/lib/watobo/defaults.rb +21 -30
  54. data/lib/watobo/external/diff/lcs.rb +0 -9
  55. data/lib/watobo/external/diff/lcs/array.rb +0 -9
  56. data/lib/watobo/external/diff/lcs/block.rb +0 -9
  57. data/lib/watobo/external/diff/lcs/callbacks.rb +0 -9
  58. data/lib/watobo/external/diff/lcs/change.rb +0 -9
  59. data/lib/watobo/external/diff/lcs/hunk.rb +0 -9
  60. data/lib/watobo/external/diff/lcs/ldiff.rb +0 -9
  61. data/lib/watobo/external/diff/lcs/string.rb +0 -9
  62. data/lib/watobo/externals.rb +6 -15
  63. data/lib/watobo/framework.rb +4 -13
  64. data/lib/watobo/framework/create_project.rb +60 -69
  65. data/lib/watobo/framework/init.rb +0 -9
  66. data/lib/watobo/framework/init_modules.rb +0 -9
  67. data/lib/watobo/framework/license_text.rb +28 -37
  68. data/lib/watobo/framework/load_chat.rb +13 -22
  69. data/lib/watobo/gui.rb +132 -123
  70. data/lib/watobo/gui/about_watobo.rb +0 -9
  71. data/lib/watobo/gui/browser_preview.rb +0 -9
  72. data/lib/watobo/gui/certificate_dialog.rb +0 -9
  73. data/lib/watobo/gui/chat_diff.rb +0 -9
  74. data/lib/watobo/gui/chatviewer_frame.rb +73 -72
  75. data/lib/watobo/gui/checkboxtree.rb +0 -9
  76. data/lib/watobo/gui/checks_policy_frame.rb +0 -9
  77. data/lib/watobo/gui/client_cert_dialog.rb +96 -87
  78. data/lib/watobo/gui/confirm_scan_dialog.rb +0 -9
  79. data/lib/watobo/gui/conversation_table.rb +158 -164
  80. data/lib/watobo/gui/conversation_table_ctrl.rb +207 -216
  81. data/lib/watobo/gui/conversation_table_ctrl2.rb +373 -382
  82. data/lib/watobo/gui/csrf_token_dialog.rb +0 -9
  83. data/lib/watobo/gui/custom_viewer.rb +374 -383
  84. data/lib/watobo/gui/dashboard.rb +296 -303
  85. data/lib/watobo/gui/define_scope_frame.rb +0 -9
  86. data/lib/watobo/gui/differ_frame.rb +215 -224
  87. data/lib/watobo/gui/edit_comment.rb +0 -9
  88. data/lib/watobo/gui/edit_scope_dialog.rb +0 -9
  89. data/lib/watobo/gui/export_dialog.rb +104 -113
  90. data/lib/watobo/gui/finding_info.rb +0 -9
  91. data/lib/watobo/gui/findings_tree.rb +210 -217
  92. data/lib/watobo/gui/full_scan_dialog.rb +0 -9
  93. data/lib/watobo/gui/fuzzer_gui.rb +1295 -1313
  94. data/lib/watobo/gui/fxsave_thread.rb +14 -0
  95. data/lib/watobo/gui/goto_url_dialog.rb +70 -79
  96. data/lib/watobo/gui/hex_viewer.rb +0 -9
  97. data/lib/watobo/gui/html_viewer.rb +287 -296
  98. data/lib/watobo/gui/intercept_filter_dialog.rb +188 -197
  99. data/lib/watobo/gui/interceptor_gui.rb +1041 -1051
  100. data/lib/watobo/gui/interceptor_settings_dialog.rb +0 -9
  101. data/lib/watobo/gui/json_viewer.rb +287 -0
  102. data/lib/watobo/gui/list_box.rb +101 -110
  103. data/lib/watobo/gui/log_file_viewer.rb +32 -41
  104. data/lib/watobo/gui/log_viewer.rb +83 -88
  105. data/lib/watobo/gui/login_wizzard.rb +0 -9
  106. data/lib/watobo/gui/main_window.rb +587 -618
  107. data/lib/watobo/gui/manual_request_editor.rb +620 -565
  108. data/lib/watobo/gui/master_pw_dialog.rb +0 -9
  109. data/lib/watobo/gui/mixins/gui_settings.rb +29 -38
  110. data/lib/watobo/gui/page_tree.rb +217 -226
  111. data/lib/watobo/gui/password_policy_dialog.rb +0 -9
  112. data/lib/watobo/gui/plugin_board.rb +0 -9
  113. data/lib/watobo/gui/preferences_dialog.rb +0 -9
  114. data/lib/watobo/gui/progress_window.rb +17 -27
  115. data/lib/watobo/gui/project_wizzard.rb +0 -9
  116. data/lib/watobo/gui/proxy_dialog.rb +1 -10
  117. data/lib/watobo/gui/quick_scan_dialog.rb +0 -9
  118. data/lib/watobo/gui/request_builder_frame.rb +102 -111
  119. data/lib/watobo/gui/request_editor.rb +181 -137
  120. data/lib/watobo/gui/rewrite_filters_dialog.rb +394 -403
  121. data/lib/watobo/gui/rewrite_rules_dialog.rb +372 -381
  122. data/lib/watobo/gui/save_chat_dialog.rb +140 -149
  123. data/lib/watobo/gui/scanner_settings_dialog.rb +0 -9
  124. data/lib/watobo/gui/select_chat_dialog.rb +0 -9
  125. data/lib/watobo/gui/session_management_dialog.rb +0 -9
  126. data/lib/watobo/gui/sites_tree.rb +0 -9
  127. data/lib/watobo/gui/status_bar.rb +0 -9
  128. data/lib/watobo/gui/table_editor.rb +0 -9
  129. data/lib/watobo/gui/tagless_viewer.rb +0 -9
  130. data/lib/watobo/gui/templates/plugin.rb +0 -9
  131. data/lib/watobo/gui/templates/plugin2.rb +92 -100
  132. data/lib/watobo/gui/templates/plugin_base.rb +144 -153
  133. data/lib/watobo/gui/text_viewer.rb +0 -9
  134. data/lib/watobo/gui/transcoder_window.rb +0 -9
  135. data/lib/watobo/gui/utils/gui_utils.rb +0 -9
  136. data/lib/watobo/gui/utils/init_icons.rb +86 -95
  137. data/lib/watobo/gui/utils/load_icons.rb +33 -42
  138. data/lib/watobo/gui/utils/load_plugins.rb +116 -119
  139. data/lib/watobo/gui/utils/master_password.rb +68 -77
  140. data/lib/watobo/gui/utils/save_default_settings.rb +113 -122
  141. data/lib/watobo/gui/utils/save_project_settings.rb +0 -9
  142. data/lib/watobo/gui/utils/save_proxy_settings.rb +41 -50
  143. data/lib/watobo/gui/utils/save_scanner_settings.rb +18 -27
  144. data/lib/watobo/gui/utils/session_history.rb +112 -121
  145. data/lib/watobo/gui/workspace_dialog.rb +0 -9
  146. data/lib/watobo/gui/www_auth_dialog.rb +0 -9
  147. data/lib/watobo/gui/xml_viewer_frame.rb +0 -9
  148. data/lib/watobo/http.rb +4 -13
  149. data/lib/watobo/http/cookies/cookies.rb +26 -35
  150. data/lib/watobo/http/data/data.rb +45 -54
  151. data/lib/watobo/http/data/json.rb +47 -55
  152. data/lib/watobo/http/url/url.rb +38 -47
  153. data/lib/watobo/http/xml/xml.rb +124 -130
  154. data/lib/watobo/interceptor.rb +3 -12
  155. data/lib/watobo/interceptor/proxy.rb +742 -739
  156. data/lib/watobo/interceptor/transparent.rb +22 -24
  157. data/lib/watobo/mixins.rb +10 -19
  158. data/lib/watobo/mixins/check_info.rb +27 -36
  159. data/lib/watobo/mixins/httpparser.rb +613 -637
  160. data/lib/watobo/mixins/request_parser.rb +88 -97
  161. data/lib/watobo/mixins/shapers.rb +515 -529
  162. data/lib/watobo/mixins/transcoders.rb +3 -11
  163. data/lib/watobo/parser.rb +1 -10
  164. data/lib/watobo/parser/html.rb +83 -92
  165. data/lib/watobo/patch_fxruby_setfocus.rb +26 -0
  166. data/lib/watobo/sockets.rb +3 -12
  167. data/lib/watobo/sockets/agent.rb +828 -837
  168. data/lib/watobo/sockets/client_socket.rb +308 -312
  169. data/lib/watobo/sockets/connection.rb +401 -410
  170. data/lib/watobo/sockets/http_socket.rb +11 -13
  171. data/lib/watobo/sockets/ntlm_auth.rb +129 -138
  172. data/lib/watobo/utils.rb +10 -19
  173. data/lib/watobo/utils/check_regex.rb +0 -9
  174. data/lib/watobo/utils/copy_object.rb +0 -9
  175. data/lib/watobo/utils/crypto.rb +0 -9
  176. data/lib/watobo/utils/expand_range.rb +23 -32
  177. data/lib/watobo/utils/export_xml.rb +97 -106
  178. data/lib/watobo/utils/file_management.rb +9 -11
  179. data/lib/watobo/utils/hexprint.rb +9 -18
  180. data/lib/watobo/utils/load_chat.rb +0 -9
  181. data/lib/watobo/utils/load_icon.rb +0 -9
  182. data/lib/watobo/utils/ntlm.rb +866 -875
  183. data/lib/watobo/utils/print_debug.rb +12 -21
  184. data/lib/watobo/utils/response_builder.rb +90 -99
  185. data/lib/watobo/utils/response_hash.rb +0 -9
  186. data/lib/watobo/utils/secure_eval.rb +0 -9
  187. data/lib/watobo/utils/strings.rb +10 -19
  188. data/lib/watobo/utils/text2request.rb +0 -9
  189. data/lib/watobo/utils/url.rb +23 -32
  190. data/lib/watobo/utils/utf16.rb +11 -20
  191. data/modules/active/Apache/mod_status.rb +0 -9
  192. data/modules/active/Apache/multiview.rb +151 -160
  193. data/modules/active/Flash/crossdomain.rb +0 -9
  194. data/modules/active/JWT/jwt_oauth2_none.rb +111 -0
  195. data/modules/active/cq5/cq5_default_selectors.rb +106 -115
  196. data/modules/active/cq5/cqp_user_enumeration.rb +125 -134
  197. data/modules/active/directories/dirwalker.rb +0 -9
  198. data/modules/active/discovery/fileextensions.rb +0 -9
  199. data/modules/active/discovery/http_methods.rb +0 -9
  200. data/modules/active/discovery/jsmapfiles.rb +79 -0
  201. data/modules/active/domino/domino_db.rb +68 -76
  202. data/modules/active/dotNET/custom_errors.rb +102 -111
  203. data/modules/active/dotNET/dotnet_files.rb +90 -99
  204. data/modules/active/fileinclusion/lfi_simple.rb +0 -9
  205. data/modules/active/jboss/jboss_basic.rb +0 -9
  206. data/modules/active/sap/business_objects.rb +51 -60
  207. data/modules/active/sap/its_commands.rb +0 -9
  208. data/modules/active/sap/its_service_parameter.rb +0 -9
  209. data/modules/active/sap/its_services.rb +0 -9
  210. data/modules/active/sap/its_xss.rb +0 -9
  211. data/modules/active/shell_shock/shell_shock.rb +139 -148
  212. data/modules/active/siebel/siebel_apps.rb +160 -169
  213. data/modules/active/sqlinjection/sql_boolean.rb +0 -9
  214. data/modules/active/sqlinjection/sql_numerical.rb +198 -0
  215. data/modules/active/sqlinjection/sqli_error.rb +0 -9
  216. data/modules/active/sqlinjection/sqli_timing.rb +220 -229
  217. data/modules/active/struts2/default_handler_ognl.rb +106 -115
  218. data/modules/active/struts2/include_params_ognl.rb +105 -114
  219. data/modules/active/xml/xml_xxe.rb +112 -123
  220. data/modules/active/xss/xss_ng.rb +214 -223
  221. data/modules/active/xss/xss_simple.rb +0 -9
  222. data/modules/passive/ajax.rb +68 -77
  223. data/modules/passive/autocomplete.rb +56 -65
  224. data/modules/passive/cookie_options.rb +0 -9
  225. data/modules/passive/cookie_xss.rb +0 -9
  226. data/modules/passive/detect_code.rb +0 -9
  227. data/modules/passive/detect_fileupload.rb +0 -9
  228. data/modules/passive/detect_infrastructure.rb +0 -9
  229. data/modules/passive/detect_one_time_tokens.rb +0 -9
  230. data/modules/passive/dirindexing.rb +0 -9
  231. data/modules/passive/disclosure_domino.rb +55 -64
  232. data/modules/passive/disclosure_emails.rb +0 -9
  233. data/modules/passive/disclosure_ipaddr.rb +55 -53
  234. data/modules/passive/filename_as_parameter.rb +0 -9
  235. data/modules/passive/form_spotter.rb +0 -9
  236. data/modules/passive/hidden_fields.rb +50 -59
  237. data/modules/passive/hotspots.rb +0 -9
  238. data/modules/passive/in_script_parameter.rb +0 -9
  239. data/modules/passive/json_web_token.rb +93 -0
  240. data/modules/passive/multiple_server_headers.rb +0 -9
  241. data/modules/passive/possible_login.rb +0 -9
  242. data/modules/passive/redirect_url.rb +0 -9
  243. data/modules/passive/redirectionz.rb +0 -9
  244. data/modules/passive/sap-headers.rb +56 -65
  245. data/modules/passive/xss_dom.rb +0 -9
  246. data/plugins/aem/aem.rb +11 -20
  247. data/plugins/aem/gui/main.rb +118 -127
  248. data/plugins/aem/gui/tree_view.rb +171 -180
  249. data/plugins/aem/lib/agent.rb +130 -138
  250. data/plugins/aem/lib/dispatcher.rb +45 -51
  251. data/plugins/aem/lib/engine.rb +177 -186
  252. data/plugins/catalog/catalog.rb +345 -355
  253. data/plugins/crawler/crawler.rb +4 -13
  254. data/plugins/crawler/gui.rb +5 -14
  255. data/plugins/crawler/gui/auth_frame.rb +270 -279
  256. data/plugins/crawler/gui/crawler_gui.rb +271 -276
  257. data/plugins/crawler/gui/general_settings_frame.rb +96 -105
  258. data/plugins/crawler/gui/hooks_frame.rb +80 -89
  259. data/plugins/crawler/gui/scope_frame.rb +50 -59
  260. data/plugins/crawler/gui/settings_tabbook.rb +38 -47
  261. data/plugins/crawler/gui/status_frame.rb +59 -68
  262. data/plugins/crawler/lib/bags.rb +18 -27
  263. data/plugins/crawler/lib/constants.rb +11 -20
  264. data/plugins/crawler/lib/engine.rb +488 -497
  265. data/plugins/crawler/lib/grabber.rb +68 -77
  266. data/plugins/crawler/lib/status.rb +71 -80
  267. data/plugins/crawler/lib/uri_mp.rb +12 -21
  268. data/plugins/filefinder/filefinder.rb +326 -333
  269. data/plugins/sqlmap/bin/test.rb +78 -87
  270. data/plugins/sqlmap/gui.rb +4 -13
  271. data/plugins/sqlmap/gui/main.rb +218 -227
  272. data/plugins/sqlmap/gui/options_frame.rb +97 -106
  273. data/plugins/sqlmap/lib/sqlmap_ctrl.rb +90 -100
  274. data/plugins/sqlmap/sqlmap.rb +2 -11
  275. data/plugins/sslchecker/cli/sslchecker_cli.rb +0 -9
  276. data/plugins/sslchecker/gui/cipher_table.rb +246 -254
  277. data/plugins/sslchecker/gui/gui.rb +258 -264
  278. data/plugins/sslchecker/gui/sslchecker.rb +4 -13
  279. data/plugins/sslchecker/lib/check.rb +127 -133
  280. data/plugins/wshell/gui/main.rb +119 -117
  281. data/plugins/wshell/lib/core.rb +38 -88
  282. data/plugins/wshell/wshell.rb +11 -20
  283. metadata +170 -164
@@ -1,12 +1,3 @@
1
- #.
2
- # request_parser.rb
3
- #.
4
- # Copyright 2014 by siberas, http://www.siberas.de
5
- # This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
6
- # WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
7
- # WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
- # You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9
-
10
1
  # @private
11
2
  module Watobo#:nodoc: all
12
3
  module Mixins
@@ -19,7 +10,7 @@ module Watobo#:nodoc: all
19
10
  # Possible prefs:
20
11
  #
21
12
  # :code_dlmtr [String] - set ruby code delimiter
22
-
13
+
23
14
  def parse_code(prefs={})
24
15
  cprefs = { :code_dlmtr => '%%' } # default delimiter for ruby code
25
16
  cprefs.update(prefs)
@@ -32,81 +23,81 @@ module Watobo#:nodoc: all
32
23
  begin
33
24
  # puts new_request
34
25
  expr = ''
35
-
26
+
36
27
  pos = 0
37
28
  off = 0
38
29
  match = []
39
30
  code_marks = []
40
31
  while pos >= 0 and pos < request.length
41
- code_offset = request.index(pattern, pos)
42
-
43
- unless code_offset.nil?
44
- new_line_index = request.index("\n", pos)
45
- unless new_line_index.nil?
46
- if new_line_index < code_offset
32
+ code_offset = request.index(pattern, pos)
33
+
34
+ unless code_offset.nil?
35
+ new_line_index = request.index("\n", pos)
36
+ unless new_line_index.nil?
37
+ if new_line_index < code_offset
47
38
  # new_request << request[match[0]..code_offset-1] unless match.empty?
48
- match = []
39
+ match = []
49
40
  # pos = code_offset
50
- end
51
- end
52
- match << code_offset
53
-
54
- if match.length == 2
55
- code_marks << match.dup
56
- match = []
57
- end
58
- pos = code_offset + pattern.length
59
- else
60
- break
61
- end
62
- end
63
-
64
- new_request = ''
65
- unless code_marks.empty?
66
- code_marks.each_with_index do |cm,i|
67
- #puts cm.to_yaml
68
- last = i > 0 ? ( code_marks[i-1][1] + pattern.length ) : 0
69
- new_request << request[last..cm[0]-1] if cm[0] > 0
70
- exp_start = cm[0] + pattern.length
71
- exp_end = cm[1] - 1
72
-
73
- expression = request[exp_start..exp_end]
74
- expression.strip!
75
- next if expression.empty?
76
- puts "DEBUG: executing: #{expression}" if $DEBUG
77
- #result = expression.empty? ? "" : eval("#{expression}")
78
- result = eval(expression)
79
- puts "DEBUG: got #{result.class}" if $DEBUG
80
- if result.is_a? File
81
- data = result.read
82
- result.close
83
- elsif result.is_a? String
84
- data = result
85
- elsif result.is_a? Array
86
- data = result.join
87
- else
88
- puts "!!!WATOBO - expression must return String or File !!!"
89
- end
90
- new_request << data
91
- end
92
- new_request << request[code_marks.last[1]+pattern.length..-2] unless code_marks.last[1] >= request.length-1
93
-
41
+ end
42
+ end
43
+ match << code_offset
44
+
45
+ if match.length == 2
46
+ code_marks << match.dup
47
+ match = []
48
+ end
49
+ pos = code_offset + pattern.length
94
50
  else
95
- new_request = request
51
+ break
96
52
  end
97
-
53
+ end
54
+
55
+ new_request = ''
56
+ unless code_marks.empty?
57
+ code_marks.each_with_index do |cm,i|
58
+ #puts cm.to_yaml
59
+ last = i > 0 ? ( code_marks[i-1][1] + pattern.length ) : 0
60
+ new_request << request[last..cm[0]-1] if cm[0] > 0
61
+ exp_start = cm[0] + pattern.length
62
+ exp_end = cm[1] - 1
63
+
64
+ expression = request[exp_start..exp_end]
65
+ expression.strip!
66
+ next if expression.empty?
67
+ puts "DEBUG: executing: #{expression}" if $DEBUG
68
+ #result = expression.empty? ? "" : eval("#{expression}")
69
+ result = eval(expression)
70
+ puts "DEBUG: got #{result.class}" if $DEBUG
71
+ if result.is_a? File
72
+ data = result.read
73
+ result.close
74
+ elsif result.is_a? String
75
+ data = result
76
+ elsif result.is_a? Array
77
+ data = result.join
78
+ else
79
+ puts "!!!WATOBO - expression must return String or File !!!"
80
+ end
81
+ new_request << data
82
+ end
83
+ new_request << request[code_marks.last[1]+pattern.length..-1] unless code_marks.last[1] >= request.length-1
84
+
85
+ else
86
+ new_request = request
87
+ end
88
+
98
89
  return new_request
99
90
 
100
91
  rescue SyntaxError, LocalJumpError, NameError => e
101
- # raise SyntaxError, "SyntaxError in '#{expression}'"
102
- puts e
103
- puts e.backtrace
104
-
92
+ # raise SyntaxError, "SyntaxError in '#{expression}'"
93
+ puts e
94
+ puts e.backtrace
95
+
105
96
  end
106
97
  return nil
107
98
  end
108
99
 
109
-
100
+
110
101
  def to_request(opts={})
111
102
  options = { :update_content_length => false }
112
103
  options.update opts
@@ -114,25 +105,25 @@ module Watobo#:nodoc: all
114
105
  begin
115
106
  text = parse_code
116
107
  request = []
117
-
108
+
118
109
  eoh = nil
119
- eoh = text.index("\n\n") unless text.nil?
120
-
121
- unless eoh.nil?
122
- header = text.slice(0, eoh).split("\n").map{|h| "#{h}\r\n"}
123
- body = text.slice(eoh+2, text.length-1)
124
- else
110
+ eoh = text.index("\n\n") unless text.nil?
111
+
112
+ unless eoh.nil?
113
+ header = text.slice(0, eoh).split("\n").map{|h| "#{h}\r\n"}
114
+ body = text.slice(eoh+2, text.length-1)
115
+ else
125
116
  header = text.split(/\n/).map{|h| "#{h}\r\n"}
126
117
  body = nil
127
- end
128
-
129
- request.concat header
118
+ end
119
+
120
+ request.concat header
121
+
122
+ #Watobo::Request.create request
123
+ request = Watobo::Request.new(request)
130
124
 
131
- #Watobo::Request.create request
132
- request = Watobo::Request.new(request)
133
-
134
125
  ct = request.content_type_ex
135
- # puts ct
126
+ # puts ct
136
127
  # last line is without "\r\n" if text has a body
137
128
  if ct =~ /multipart/ and body then
138
129
  #Content-Type: multipart/form-data; boundary=---------------------------3035221901842
@@ -176,7 +167,7 @@ module Watobo#:nodoc: all
176
167
  request.push "\r\n"
177
168
  request.push body.strip
178
169
  end
179
-
170
+
180
171
  request.fixupContentLength() if options[:update_content_length] == true
181
172
  return request
182
173
  rescue => bang
@@ -186,7 +177,7 @@ module Watobo#:nodoc: all
186
177
  end
187
178
  #return nil
188
179
  end
189
-
180
+
190
181
  def to_response(opts={})
191
182
  options = { :update_content_length => false }
192
183
  options.update opts
@@ -208,14 +199,14 @@ module Watobo#:nodoc: all
208
199
  end
209
200
 
210
201
 
211
- #Watobo::Response.create result
212
- result = Watobo::Response.new(result)
213
-
202
+ #Watobo::Response.create result
203
+ result = Watobo::Response.new(result)
204
+
214
205
  if body then
215
206
  result.push "\r\n"
216
207
  result.push body.strip
217
208
  end
218
-
209
+
219
210
  result.fixupContentLength() if options[:update_content_length] == true
220
211
  puts ">>"
221
212
  puts result
@@ -249,11 +240,11 @@ module Watobo#:nodoc: all
249
240
  result.push "#{h}\r\n"
250
241
  end
251
242
 
252
- # result.extend Watobo::Mixin::Parser::Url
253
- # result.extend Watobo::Mixin::Parser::Web10
254
- # result.extend Watobo::Mixin::Shaper::Web10
255
- #Watobo::Request.create result
256
- result = Watobo::Request.new(result)
243
+ # result.extend Watobo::Mixin::Parser::Url
244
+ # result.extend Watobo::Mixin::Parser::Web10
245
+ # result.extend Watobo::Mixin::Shaper::Web10
246
+ #Watobo::Request.create result
247
+ result = Watobo::Request.new(result)
257
248
 
258
249
  ct = result.content_type
259
250
  # last line is without "\r\n" if text has a body
@@ -316,8 +307,8 @@ if $0 == __FILE__
316
307
  $: << inc_path
317
308
 
318
309
  require 'watobo'
319
-
320
- text =<<'EOF'
310
+
311
+ text =<<'EOF'
321
312
  %%"GET"%% http://www.siberas.de/ HTTP/1.1
322
313
  Content-Type: text/html
323
314
  %%"x"*10%%Vary: Accept-Encoding
@@ -339,4 +330,4 @@ puts
339
330
  text.extend Watobo::Mixins::RequestParser
340
331
  puts text.to_request
341
332
  Watobo::Utils.hexprint text
342
- end
333
+ end
@@ -1,529 +1,515 @@
1
- #.
2
- # shapers.rb
3
- #.
4
- # Copyright 2014 by siberas, http://www.siberas.de
5
- # This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
6
- # WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
7
- # WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
- # You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9
-
10
- # @private
11
- module Watobo#:nodoc: all
12
- module Mixin
13
- module Shaper
14
- module Web10
15
- include Watobo::Constants
16
- def replace_post_parm(parm,value)
17
- parm_quoted = Regexp.quote(parm)
18
- self.last.gsub!(/([?&]{1}|^)#{parm_quoted}=([^&]*)(&{0,1})/i, "\\1#{parm}=#{value}\\3")
19
- end
20
-
21
- def replace_get_parm(parm,value)
22
- parm_quoted = Regexp.quote(parm)
23
- self.first.gsub!(/([?&]{1})#{parm_quoted}=([^ &]*)(&{0,1})/i, "\\1#{parm}=#{value}\\3")
24
- end
25
-
26
- def replaceMethod(new_method)
27
- self.first.gsub!(/^[^[:space:]]{1,}/i, "#{new_method}")
28
- end
29
-
30
- def replaceFileExt(new_file)
31
- begin
32
- file = new_file.strip
33
- file.gsub!(/^\//, "")
34
- self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i,"\\1#{file} \\3")
35
- rescue => bang
36
- puts bang
37
- end
38
- end
39
-
40
- def replaceElement(new_element)
41
- new_element.gsub!(/^\//, "")
42
- self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i,"\\1#{new_element} \\3")
43
- end
44
-
45
- def replaceURL(new_url)
46
- self.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i,"\\1 #{new_url} \\3")
47
- end
48
-
49
- def replaceQuery(new_query)
50
- new_query.gsub!(/^\//, "")
51
- self.first.gsub!(/(.*\/)(.*) (HTTP.*)/i,"\\1#{new_query} \\3")
52
- end
53
-
54
- def strip_path()
55
- self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i,"\\1# \\3")
56
- end
57
-
58
- def setDir(dir)
59
- dir.strip!
60
- dir.gsub!(/^\/+/,"")
61
- dir.gsub!(/\/+$/,"")
62
- dir += "/" unless dir == ''
63
- self.first.gsub!(/(^[^[:space:]]{1,} https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)(.*)( HTTP\/.*)/, "\\1#{dir}\\3")
64
- end
65
-
66
- #
67
- # set a new file extension, e.g. mysite.html to mysite.php
68
- # if no extension nor a file is given, the new extension will only be appended
69
- # note: the first leading dot will be removed
70
- # possible preferences are:
71
- # :keep_query => keeps query parameters
72
- # default-set is empty
73
- def set_file_extension(nxt, *prefs)
74
- return self.first if nxt.nil?
75
- nxt.gsub!(/^\./,'')
76
- s = "#{self.first}"
77
- fend = nil
78
- pend = nil
79
-
80
- pstart = s.index('?')
81
- pend = s.rindex(/ HTTP\//)
82
-
83
- fend = (pstart - 1) unless pstart.nil?
84
- fend = ( pend - 1 ) if fend.nil?
85
-
86
- return self.first if fend.nil?
87
-
88
- fstart = s.rindex('/', fend)
89
- unless s[fstart-1] == '/'
90
- fstart += 1 unless fstart.nil?
91
- else
92
- fstart = fend
93
- end
94
-
95
- fname = s[fstart..fend]
96
- fname.gsub!(/\..*/,'')
97
- fname << ".#{nxt}"
98
-
99
- ns = s[0..fstart-1]
100
- ns << fname
101
-
102
- if prefs.include? :keep_query
103
- unless pstart.nil?
104
- ns << s[pstart..pend]
105
- end
106
- end
107
-
108
- ns << s[pend..-1]
109
-
110
- self.first.replace ns
111
- end
112
-
113
- def appendDir(dir)
114
- dir.strip!
115
- dir.gsub!(/^\//,"")
116
- dir << "/" unless dir =~ /\/$/
117
- self.first.gsub!(/(^[^[:space:]]{1,} https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}.*\/).*( HTTP\/.*)/, "\\1#{dir}\\2")
118
-
119
- end
120
-
121
- def add_post_parm(parm,value)
122
- line = self.last
123
- return false if line !~ /=/
124
- line += "&#{parm}=#{value}"
125
- self.pop
126
- self.push line
127
- end
128
-
129
- def add_get_parm(parm,value)
130
- line = self.shift
131
- new_p = "&"
132
- new_p = "?" if not self.element =~ /\?/
133
- new_p += parm
134
- line.gsub!(/( HTTP\/.*)/, "#{new_p}=#{value}\\1")
135
- self.unshift(line)
136
- end
137
-
138
- def addHeader(header, value)
139
- self_copy = []
140
- self_copy.concat(self.headers)
141
- self_copy.push "#{header}: #{value}\r\n"
142
-
143
- unless self.body.nil?
144
- self_copy.push "\r\n"
145
- #self_copy.concat(self.body)
146
- self_copy.push self.body
147
- end
148
-
149
- self.replace(self_copy)
150
-
151
- end
152
-
153
- alias_method :add_header, :addHeader
154
-
155
- def removeURI
156
- if self.first =~ /(^[^[:space:]]{1,}) (https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/ then
157
- uri = $2
158
- self.first.gsub!(/(^[^[:space:]]{1,}) (#{Regexp.quote(uri)})/,"\\1 /")
159
- # puts "* Removed URI: #{uri}"
160
- # puts self.first
161
- return uri
162
- else
163
- return nil
164
- end
165
- #self.first.gsub!(/^(.*)(https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/,"\\1/")
166
- end
167
-
168
- def removeBody
169
- self.pop if self[-2].strip.empty?
170
- end
171
-
172
- def set_header_UNUSED(header, value)
173
- self.each do |h|
174
- break if h.strip.empty?
175
- if h =~ /^#{header}:/
176
- h.replace "#{header}: #{value}\r\n"
177
- end
178
- end
179
- end
180
-
181
- def set_body(content)
182
- if self[-2].strip.empty?
183
- self.pop
184
- else
185
- self << "\r\n"
186
- end
187
- self << content
188
- end
189
-
190
- def rewrite_body(pattern, content)
191
- if self[-2].strip.empty?
192
- puts "rewrite_body ... #{pattern} - #{content}"
193
- b = self.pop
194
- b.gsub!(/#{pattern}/i, content)
195
- self << b
196
- end
197
- end
198
-
199
- def restoreURI(uri)
200
- if self.first =~ /(^[^[:space:]]{1,}) \/(.*) (HTTP\/.*)/ then
201
- method = $1
202
- rest = $2
203
- http = $3.strip
204
- #self.first.gsub!(/^\w*/, "#{method} #{uri}#{rest}")
205
- self.shift
206
- self.unshift "#{method} #{uri}#{rest} #{http}\r\n"
207
- return self.first
208
- else
209
- return nil
210
- end
211
- #self.first.gsub!(/^(.*)(https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/,"\\1/")
212
- end
213
-
214
- #
215
- # R E M O V E _ H E A D E R
216
- #
217
-
218
- def removeHeader(header)
219
- begin
220
-
221
- while i = headers.index{|h| h =~ /#{header}/i }
222
- self.delete_at i
223
- end
224
-
225
- rescue => bang
226
- puts bang
227
- puts bang.backtrace if $DEBUG
228
- puts self
229
- puts "====="
230
- end
231
- end
232
-
233
- alias_method :remove_header, :removeHeader
234
-
235
- # removeUrlParms
236
- # Function: Remove all parameter within the URL
237
- #
238
- def removeUrlParms
239
- line = self.shift
240
- new_line = "#{line}"
241
- # get end-of-path-index
242
- eop_index = line.rindex(/[^ HTTP]\//)
243
- # get start of parms
244
- sop_index = line.index(/(\?|&)/, eop_index)
245
- # find end-of-url
246
- eou_index = line.index(/ HTTP/)
247
-
248
- unless sop_index.nil?
249
- new_line = line[0..sop_index-1]
250
- new_line += line[eou_index..-1]
251
- end
252
-
253
- self.unshift new_line
254
- end
255
-
256
- def removeHeader_OLD(header)
257
- # p "REMOVE HEADER: #{header}"
258
- begin
259
- self_copy = []
260
- eoh = false
261
- self.each do |line|
262
- puts self if line.nil?
263
- if not eoh == true then
264
- if not line =~ /#{header}/i
265
- self_copy.push line unless line.nil?
266
- end
267
- else
268
- self_copy.push line unless line.nil?
269
- end
270
-
271
- if line and line.strip.empty? then
272
- eoh = true
273
- end
274
- end
275
- self.replace(self_copy)
276
-
277
- rescue => bang
278
- puts bang
279
- puts bang.backtrace if $DEBUG
280
- puts self
281
- puts "====="
282
- end
283
- end
284
-
285
- def replace_header(header, value)
286
-
287
- end
288
-
289
- def fix_session(pattern,value)
290
-
291
- end
292
-
293
- def fix_content_length
294
- return false if self.body.nil?
295
- # had trouble with length calculation of binary data in multipart request
296
- blen = self.body.force_encoding("ASCII-8BIT").length
297
- set_header("Content-Length" , blen)
298
- end
299
-
300
- def fixupContentLength_UNUSED
301
- te = self.transferEncoding
302
- if te == TE_CHUNKED then
303
- # puts "Transfer-Encoding = TE_CHUNKED"
304
- # puts self.body
305
- self.removeHeader("Transfer-Encoding")
306
- self.addHeader("Content-Length", "0")
307
- new_r = []
308
- new_r.concat self.headers
309
- new_r.push "\r\n"
310
-
311
- bytes_to_read = 0
312
- body = []
313
- is_new_chunk = false
314
-
315
- off = 0
316
- new_body = ''
317
-
318
- body_orig = self.body
319
- puts body_orig.class
320
- while body_orig[off..-1] =~ /^([0-9a-fA-F]{1,6})\r\n/
321
- len_raw = "#{$1}"
322
-
323
- len = len_raw.hex
324
-
325
- chunk_start = off + len_raw.length + 2
326
- chunk_end = chunk_start + len
327
-
328
- break if len == 0
329
-
330
- new_body.chomp!
331
- new_body += "#{body_orig[chunk_start..chunk_end]}"
332
-
333
- off = chunk_end + 2
334
- end
335
-
336
- new_r.push new_body
337
- self.replace(new_r)
338
- self.fix_content_length
339
- # puts "= FIXED ="
340
- # puts self.headers
341
- elsif te == TE_NONE then
342
- self.fix_content_length
343
- end
344
-
345
- end
346
-
347
- def fixupContentLength
348
- self.unchunk
349
- self.fix_content_length
350
- end
351
-
352
- def setRawQueryParms(parm_string)
353
- return nil if parm_string.nil?
354
- return nil if parm_string == ''
355
- new_r = ""
356
- path = Regexp.quote(self.path)
357
- #puts path
358
- if self.first =~ /(.*#{path})/ then
359
- new_r = $1 << "?" << parm_string
360
- end
361
- self.first.gsub!(/(.*) (HTTP\/.*)/, "#{new_r} \\2")
362
- end
363
-
364
- def appendQueryParms(parms)
365
- return if parms.nil?
366
- return if parms == ''
367
-
368
- puts self.first
369
- puts self.file_ext
370
-
371
- pref = (self.file_ext =~ /\?/) ? '&' : '?'
372
- puts "append query parms"
373
- self.first.gsub!(/(.*) (HTTP\/.*)/, "\\1#{pref}#{parms} \\2")
374
-
375
- end
376
-
377
- def set_content_length(length)
378
- set_header("Content-Length", length)
379
- end
380
-
381
- def set_content_type(ctype)
382
- set_header("Content-Type", ctype)
383
- end
384
-
385
- def set_header(header, value)
386
- begin
387
- new_header = "#{header}: #{value}\r\n"
388
- self.each_with_index do |h, i|
389
- if h =~ /^#{Regexp.quote(header)}:/i
390
- self[i] = new_header
391
- return true
392
- end
393
-
394
- if h.strip.empty? or i == self.length-1
395
- self.insert(i, new_header)
396
- return true
397
- end
398
- end
399
- rescue => bang
400
- puts bang
401
- end
402
- return false
403
- end
404
- alias :setHeader :set_header
405
-
406
- # sets post data
407
- def setData(data)
408
- return if data.nil?
409
- if self.has_body?
410
- self.pop
411
- self.push data
412
- else
413
- self.push("\r\n")
414
- self.push data
415
- end
416
- end
417
-
418
- def setMethod(method)
419
- m = method.is_a?(Symbol) ? method.to_s.upcase : method
420
- self.first.gsub!(/(^[^[:space:]]{1,}) /, "#{m} ")
421
- end
422
-
423
- alias_method :set_method, :setMethod
424
- alias :method= :setMethod
425
-
426
- def setHTTPVersion(version)
427
- self.first.gsub!(/HTTP\/(.*)$/, "HTTP\/#{version}")
428
- # puts "HTTPVersion fixed: #{self.first}"
429
- end
430
-
431
- end
432
-
433
- module HttpResponse
434
- include Watobo::Constants
435
- def unchunk!
436
- return false unless self.has_body?
437
-
438
- unchunked = self.unchunk
439
- self.replace(unchunked)
440
- self.fix_content_length
441
-
442
- end
443
-
444
- def unchunk
445
- return Response.new(self) unless self.has_body?
446
-
447
- if self.transfer_encoding == TE_CHUNKED then
448
- self.removeHeader("Transfer-Encoding")
449
- self.addHeader("Content-Length", "0")
450
- new_r = []
451
- new_r.concat self.headers
452
- new_r.push "\r\n"
453
-
454
- bytes_to_read = 20
455
- body = []
456
- is_new_chunk = false
457
-
458
- off = 0
459
- new_body = ''
460
-
461
- body_orig = self.body
462
- pattern = '[0-9a-fA-F]+\r?\n'
463
- while off >= 0 and off < body_orig.length
464
- chunk_pos = body_orig.index(/(#{pattern})/, off)
465
- len_raw = $1
466
- unless chunk_pos.nil?
467
- len = len_raw.strip.hex
468
-
469
- chunk_start = chunk_pos + len_raw.length
470
- chunk_end = chunk_start + len
471
-
472
- break if len == 0
473
- chunk = "#{body_orig[chunk_start..chunk_end]}"
474
- new_body += chunk.chomp
475
- off = chunk_end
476
- end
477
- end
478
- new_r.push new_body
479
- return Watobo::Response.new new_r
480
-
481
- end
482
- return Response.new(self)
483
- end
484
-
485
- def unzip!
486
- if self.content_encoding == TE_GZIP or self.transfer_encoding == TE_GZIP
487
- if self.has_body?
488
- unziped = self.unzip_body
489
-
490
- self[-1] = unziped
491
- self.removeHeader("Transfer-Encoding") if self.transfer_encoding == TE_GZIP
492
- self.removeHeader("Content-Encoding") if self.content_encoding == TE_GZIP
493
- self.fix_content_length
494
- end
495
- end
496
-
497
- end
498
-
499
- def unzip
500
- if self.content_encoding == TE_GZIP or self.transfer_encoding == TE_GZIP
501
- if self.has_body?
502
- unzipped = Response.new(self)
503
- unzipped.unzip!
504
- return unzipped
505
- end
506
- end
507
-
508
- return Response.new(self)
509
- end
510
-
511
- def unzip_body
512
- begin
513
- if self.has_body?
514
- gziped = self.last
515
- gz = Zlib::GzipReader.new( StringIO.new( gziped ) )
516
- data = gz.read
517
- return data
518
- end
519
-
520
- rescue => bang
521
- puts bang
522
- end
523
-
524
- end
525
-
526
- end
527
- end
528
- end
529
- end
1
+ # @private
2
+ module Watobo #:nodoc: all
3
+ module Mixin
4
+ module Shaper
5
+ module Web10
6
+ include Watobo::Constants
7
+
8
+ def replace_post_parm(parm, value)
9
+ parm_quoted = Regexp.quote(parm)
10
+ self.last.gsub!(/([?&]{1}|^)#{parm_quoted}=([^&]*)(&{0,1})/i, "\\1#{parm}=#{value}\\3")
11
+ end
12
+
13
+ def replace_get_parm(parm, value)
14
+ parm_quoted = Regexp.quote(parm)
15
+ self.first.gsub!(/([?&]{1})#{parm_quoted}=([^ &]*)(&{0,1})/i, "\\1#{parm}=#{value}\\3")
16
+ end
17
+
18
+ def replaceMethod(new_method)
19
+ self.first.gsub!(/^[^[:space:]]{1,}/i, "#{new_method}")
20
+ end
21
+
22
+ def replaceFileExt(new_file)
23
+ begin
24
+ file = new_file.strip
25
+ file.gsub!(/^\//, "")
26
+ self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i, "\\1#{file} \\3")
27
+ rescue => bang
28
+ puts bang
29
+ end
30
+ end
31
+
32
+ def replaceElement(new_element)
33
+ new_element.gsub!(/^\//, "")
34
+ self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i, "\\1#{new_element} \\3")
35
+ end
36
+
37
+ def replaceURL(new_url)
38
+ self.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i, "\\1 #{new_url} \\3")
39
+ end
40
+
41
+ def replaceQuery(new_query)
42
+ new_query.gsub!(/^\//, "")
43
+ self.first.gsub!(/(.*\/)(.*) (HTTP.*)/i, "\\1#{new_query} \\3")
44
+ end
45
+
46
+ def strip_path()
47
+ self.first.gsub!(/([^\?]*\/)(.*) (HTTP.*)/i, "\\1# \\3")
48
+ end
49
+
50
+ def setDir(dir)
51
+ dir.strip!
52
+ dir.gsub!(/^\/+/, "")
53
+ dir.gsub!(/\/+$/, "")
54
+ dir += "/" unless dir == ''
55
+ self.first.gsub!(/(^[^[:space:]]{1,} https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)(.*)( HTTP\/.*)/, "\\1#{dir}\\3")
56
+ end
57
+
58
+ #
59
+ # set a new file extension, e.g. mysite.html to mysite.php
60
+ # if no extension nor a file is given, the new extension will only be appended
61
+ # note: the first leading dot will be removed
62
+ # possible preferences are:
63
+ # :keep_query => keeps query parameters
64
+ # default-set is empty
65
+ def set_file_extension(nxt, *prefs)
66
+ return self.first if nxt.nil?
67
+ nxt.gsub!(/^\./, '')
68
+ s = "#{self.first}"
69
+ fend = nil
70
+ pend = nil
71
+
72
+ pstart = s.index('?')
73
+ pend = s.rindex(/ HTTP\//)
74
+
75
+ fend = (pstart - 1) unless pstart.nil?
76
+ fend = (pend - 1) if fend.nil?
77
+
78
+ return self.first if fend.nil?
79
+
80
+ fstart = s.rindex('/', fend)
81
+ unless s[fstart-1] == '/'
82
+ fstart += 1 unless fstart.nil?
83
+ else
84
+ fstart = fend
85
+ end
86
+
87
+ fname = s[fstart..fend]
88
+ fname.gsub!(/\..*/, '')
89
+ fname << ".#{nxt}"
90
+
91
+ ns = s[0..fstart-1]
92
+ ns << fname
93
+
94
+ if prefs.include? :keep_query
95
+ unless pstart.nil?
96
+ ns << s[pstart..pend]
97
+ end
98
+ end
99
+
100
+ ns << s[pend..-1]
101
+
102
+ self.first.replace ns
103
+ end
104
+
105
+ def appendDir(dir)
106
+ dir.strip!
107
+ dir.gsub!(/^\//, "")
108
+ dir << "/" unless dir =~ /\/$/
109
+ self.first.gsub!(/(^[^[:space:]]{1,} https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}.*\/).*( HTTP\/.*)/, "\\1#{dir}\\2")
110
+
111
+ end
112
+
113
+ def add_post_parm(parm, value)
114
+ line = self.last
115
+ return false if line !~ /=/
116
+ line += "&#{parm}=#{value}"
117
+ self.pop
118
+ self.push line
119
+ end
120
+
121
+ def add_get_parm(parm, value)
122
+ line = self.shift
123
+ new_p = "&"
124
+ new_p = "?" if not self.element =~ /\?/
125
+ new_p += parm
126
+ line.gsub!(/( HTTP\/.*)/, "#{new_p}=#{value}\\1")
127
+ self.unshift(line)
128
+ end
129
+
130
+ def addHeader(header, value)
131
+ self_copy = []
132
+ self_copy.concat(self.headers)
133
+ self_copy.push "#{header}: #{value}\r\n"
134
+
135
+ unless self.body.nil?
136
+ self_copy.push "\r\n"
137
+ #self_copy.concat(self.body)
138
+ self_copy.push self.body
139
+ end
140
+
141
+ self.replace(self_copy)
142
+
143
+ end
144
+
145
+ alias_method :add_header, :addHeader
146
+
147
+ def removeURI
148
+ if self.first =~ /(^[^[:space:]]{1,}) (https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/ then
149
+ uri = $2
150
+ self.first.gsub!(/(^[^[:space:]]{1,}) (#{Regexp.quote(uri)})/, "\\1 /")
151
+ # puts "* Removed URI: #{uri}"
152
+ # puts self.first
153
+ return uri
154
+ else
155
+ return nil
156
+ end
157
+ #self.first.gsub!(/^(.*)(https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/,"\\1/")
158
+ end
159
+
160
+ def removeBody
161
+ self.pop if self[-2].strip.empty?
162
+ end
163
+
164
+ def set_body(content)
165
+ if self[-2].strip.empty?
166
+ self.pop
167
+ else
168
+ self << "\r\n"
169
+ end
170
+ self << content
171
+ end
172
+
173
+ def rewrite_body(pattern, content)
174
+ if self.has_body?
175
+ #puts "rewrite_body ... #{pattern} - #{content}"
176
+ b = self.pop
177
+ b.gsub!(/#{pattern}/i, content)
178
+ self << b
179
+ end
180
+ end
181
+
182
+ def restoreURI(uri)
183
+ if self.first =~ /(^[^[:space:]]{1,}) \/(.*) (HTTP\/.*)/ then
184
+ method = $1
185
+ rest = $2
186
+ http = $3.strip
187
+ #self.first.gsub!(/^\w*/, "#{method} #{uri}#{rest}")
188
+ self.shift
189
+ self.unshift "#{method} #{uri}#{rest} #{http}\r\n"
190
+ return self.first
191
+ else
192
+ return nil
193
+ end
194
+ #self.first.gsub!(/^(.*)(https?:\/\/[\-0-9a-zA-Z.]*[:0-9]{0,6}\/)/,"\\1/")
195
+ end
196
+
197
+ #
198
+ # R E M O V E _ H E A D E R
199
+ #
200
+
201
+ def removeHeader(header)
202
+ begin
203
+
204
+ while i = headers.index { |h| h =~ /#{header}/i }
205
+ self.delete_at i
206
+ end
207
+
208
+ rescue => bang
209
+ puts bang
210
+ puts bang.backtrace if $DEBUG
211
+ puts self
212
+ puts "====="
213
+ end
214
+ end
215
+
216
+ alias_method :remove_header, :removeHeader
217
+
218
+ # removeUrlParms
219
+ # Function: Remove all parameter within the URL
220
+ #
221
+ def removeUrlParms
222
+ line = self.shift
223
+ return false if line.nil?
224
+ new_line = "#{line}"
225
+ # get end-of-path-index
226
+ eop_index = line.rindex(/[^ HTTP]\//)
227
+ # get start of parms
228
+ sop_index = line.index(/(\?|&)/, eop_index)
229
+ # find end-of-url
230
+ eou_index = line.index(/ HTTP/)
231
+
232
+ unless sop_index.nil? or eou_index.nil?
233
+ new_line = line[0..sop_index-1]
234
+ new_line += line[eou_index..-1]
235
+ end
236
+
237
+ self.unshift new_line
238
+ end
239
+
240
+ def removeHeader_OLD(header)
241
+ # p "REMOVE HEADER: #{header}"
242
+ begin
243
+ self_copy = []
244
+ eoh = false
245
+ self.each do |line|
246
+ puts self if line.nil?
247
+ if not eoh == true then
248
+ if not line =~ /#{header}/i
249
+ self_copy.push line unless line.nil?
250
+ end
251
+ else
252
+ self_copy.push line unless line.nil?
253
+ end
254
+
255
+ if line and line.strip.empty? then
256
+ eoh = true
257
+ end
258
+ end
259
+ self.replace(self_copy)
260
+
261
+ rescue => bang
262
+ puts bang
263
+ puts bang.backtrace if $DEBUG
264
+ puts self
265
+ puts "====="
266
+ end
267
+ end
268
+
269
+ def replace_header(header, value)
270
+
271
+ end
272
+
273
+ def fix_session(pattern, value)
274
+
275
+ end
276
+
277
+ def fix_content_length
278
+ return false if self.body.nil?
279
+ # had trouble with length calculation of binary data in multipart request
280
+ blen = self.body.force_encoding("ASCII-8BIT").length
281
+ set_header("Content-Length", blen)
282
+ end
283
+
284
+ def fixupContentLength_UNUSED
285
+ te = self.transferEncoding
286
+ if te == TE_CHUNKED then
287
+ # puts "Transfer-Encoding = TE_CHUNKED"
288
+ # puts self.body
289
+ self.removeHeader("Transfer-Encoding")
290
+ self.addHeader("Content-Length", "0")
291
+ new_r = []
292
+ new_r.concat self.headers
293
+ new_r.push "\r\n"
294
+
295
+ bytes_to_read = 0
296
+ body = []
297
+ is_new_chunk = false
298
+
299
+ off = 0
300
+ new_body = ''
301
+
302
+ body_orig = self.body
303
+ puts body_orig.class
304
+ while body_orig[off..-1] =~ /^([0-9a-fA-F]{1,6})\r\n/
305
+ len_raw = "#{$1}"
306
+
307
+ len = len_raw.hex
308
+
309
+ chunk_start = off + len_raw.length + 2
310
+ chunk_end = chunk_start + len
311
+
312
+ break if len == 0
313
+
314
+ new_body.chomp!
315
+ new_body += "#{body_orig[chunk_start..chunk_end]}"
316
+
317
+ off = chunk_end + 2
318
+ end
319
+
320
+ new_r.push new_body
321
+ self.replace(new_r)
322
+ self.fix_content_length
323
+ # puts "= FIXED ="
324
+ # puts self.headers
325
+ elsif te == TE_NONE then
326
+ self.fix_content_length
327
+ end
328
+
329
+ end
330
+
331
+ def fixupContentLength
332
+ self.unchunk
333
+ self.fix_content_length
334
+ end
335
+
336
+ def setRawQueryParms(parm_string)
337
+ return nil if parm_string.nil?
338
+ return nil if parm_string == ''
339
+ new_r = ""
340
+ path = Regexp.quote(self.path)
341
+ #puts path
342
+ if self.first =~ /(.*#{path})/ then
343
+ new_r = $1 << "?" << parm_string
344
+ end
345
+ self.first.gsub!(/(.*) (HTTP\/.*)/, "#{new_r} \\2")
346
+ end
347
+
348
+ def appendQueryParms(parms)
349
+ return if parms.nil?
350
+ return if parms == ''
351
+
352
+ puts self.first
353
+ puts self.file_ext
354
+
355
+ pref = (self.file_ext =~ /\?/) ? '&' : '?'
356
+ puts "append query parms"
357
+ self.first.gsub!(/(.*) (HTTP\/.*)/, "\\1#{pref}#{parms} \\2")
358
+
359
+ end
360
+
361
+ def set_content_length(length)
362
+ set_header("Content-Length", length)
363
+ end
364
+
365
+ def set_content_type(ctype)
366
+ set_header("Content-Type", ctype)
367
+ end
368
+
369
+ def set_header(header, value)
370
+ begin
371
+ new_header = "#{header}: #{value}\r\n"
372
+ self.each_with_index do |h, i|
373
+ if h =~ /^#{Regexp.quote(header)}:/i
374
+ self[i] = new_header
375
+ return true
376
+ end
377
+
378
+ if h.strip.empty? or i == self.length-1
379
+ self.insert(i, new_header)
380
+ return true
381
+ end
382
+ end
383
+ rescue => bang
384
+ puts bang
385
+ end
386
+ return false
387
+ end
388
+
389
+ alias :setHeader :set_header
390
+
391
+ # sets post data
392
+ def setData(data)
393
+ return if data.nil?
394
+ if self.has_body?
395
+ self.pop
396
+ self.push data
397
+ else
398
+ self.push("\r\n")
399
+ self.push data
400
+ end
401
+ end
402
+
403
+ def setMethod(method)
404
+ m = method.is_a?(Symbol) ? method.to_s.upcase : method
405
+ self.first.gsub!(/(^[^[:space:]]{1,}) /, "#{m} ")
406
+ end
407
+
408
+ alias_method :set_method, :setMethod
409
+ alias :method= :setMethod
410
+
411
+ def setHTTPVersion(version)
412
+ self.first.gsub!(/HTTP\/(.*)$/, "HTTP\/#{version}")
413
+ # puts "HTTPVersion fixed: #{self.first}"
414
+ end
415
+
416
+ end
417
+
418
+ module HttpResponse
419
+ include Watobo::Constants
420
+
421
+ def unchunk!
422
+ return false unless self.has_body?
423
+
424
+ unchunked = self.unchunk
425
+ self.replace(unchunked)
426
+ self.fix_content_length
427
+
428
+ end
429
+
430
+ def unchunk
431
+ return Response.new(self) unless self.has_body?
432
+
433
+ if self.transfer_encoding == TE_CHUNKED then
434
+ self.removeHeader("Transfer-Encoding")
435
+ self.addHeader("Content-Length", "0")
436
+ new_r = []
437
+ new_r.concat self.headers
438
+ new_r.push "\r\n"
439
+
440
+ bytes_to_read = 20
441
+ body = []
442
+ is_new_chunk = false
443
+
444
+ off = 0
445
+ new_body = ''
446
+
447
+ body_orig = self.body
448
+ pattern = '[0-9a-fA-F]+\r?\n'
449
+ while off >= 0 and off < body_orig.length
450
+ chunk_pos = body_orig.index(/(#{pattern})/, off)
451
+ len_raw = $1
452
+ unless chunk_pos.nil?
453
+ len = len_raw.strip.hex
454
+
455
+ chunk_start = chunk_pos + len_raw.length
456
+ chunk_end = chunk_start + len
457
+
458
+ break if len == 0
459
+ chunk = "#{body_orig[chunk_start..chunk_end]}"
460
+ new_body += chunk.chomp
461
+ off = chunk_end
462
+ end
463
+ end
464
+ new_r.push new_body
465
+ return Watobo::Response.new new_r
466
+
467
+ end
468
+ return Response.new(self)
469
+ end
470
+
471
+ def unzip!
472
+ if self.content_encoding == TE_GZIP or self.transfer_encoding == TE_GZIP
473
+ if self.has_body?
474
+ unziped = self.unzip_body
475
+
476
+ self[-1] = unziped
477
+ self.removeHeader("Transfer-Encoding") if self.transfer_encoding == TE_GZIP
478
+ self.removeHeader("Content-Encoding") if self.content_encoding == TE_GZIP
479
+ self.fix_content_length
480
+ end
481
+ end
482
+
483
+ end
484
+
485
+ def unzip
486
+ if self.content_encoding == TE_GZIP or self.transfer_encoding == TE_GZIP
487
+ if self.has_body?
488
+ unzipped = Response.new(self)
489
+ unzipped.unzip!
490
+ return unzipped
491
+ end
492
+ end
493
+
494
+ return Response.new(self)
495
+ end
496
+
497
+ def unzip_body
498
+ begin
499
+ if self.has_body?
500
+ gziped = self.last
501
+ gz = Zlib::GzipReader.new(StringIO.new(gziped))
502
+ data = gz.read
503
+ return data
504
+ end
505
+
506
+ rescue => bang
507
+ puts bang
508
+ end
509
+
510
+ end
511
+
512
+ end
513
+ end
514
+ end
515
+ end