romanbsd-tarantula 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/CHANGELOG +47 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +162 -0
  4. data/Rakefile +69 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/example_helper.rb +48 -0
  7. data/examples/relevance/core_extensions/ellipsize_example.rb +19 -0
  8. data/examples/relevance/core_extensions/file_example.rb +8 -0
  9. data/examples/relevance/core_extensions/response_example.rb +29 -0
  10. data/examples/relevance/core_extensions/test_case_example.rb +20 -0
  11. data/examples/relevance/tarantula/attack_form_submission_example.rb +79 -0
  12. data/examples/relevance/tarantula/attack_handler_example.rb +29 -0
  13. data/examples/relevance/tarantula/crawler_example.rb +386 -0
  14. data/examples/relevance/tarantula/form_example.rb +50 -0
  15. data/examples/relevance/tarantula/form_submission_example.rb +71 -0
  16. data/examples/relevance/tarantula/html_document_handler_example.rb +43 -0
  17. data/examples/relevance/tarantula/html_report_helper_example.rb +46 -0
  18. data/examples/relevance/tarantula/html_reporter_example.rb +82 -0
  19. data/examples/relevance/tarantula/invalid_html_handler_example.rb +33 -0
  20. data/examples/relevance/tarantula/io_reporter_example.rb +11 -0
  21. data/examples/relevance/tarantula/link_example.rb +67 -0
  22. data/examples/relevance/tarantula/log_grabber_example.rb +26 -0
  23. data/examples/relevance/tarantula/rails_integration_proxy_example.rb +88 -0
  24. data/examples/relevance/tarantula/result_example.rb +85 -0
  25. data/examples/relevance/tarantula/tidy_handler_example.rb +58 -0
  26. data/examples/relevance/tarantula/transform_example.rb +20 -0
  27. data/examples/relevance/tarantula/w3c_validator_example.rb +71 -0
  28. data/examples/relevance/tarantula_example.rb +23 -0
  29. data/laf/images/button_active.png +0 -0
  30. data/laf/images/button_hover.png +0 -0
  31. data/laf/images/button_inactive.png +0 -0
  32. data/laf/images/header_bg.jpg +0 -0
  33. data/laf/images/logo.png +0 -0
  34. data/laf/images/tagline.png +0 -0
  35. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  36. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  37. data/laf/javascripts/jquery.tablesorter.js +861 -0
  38. data/laf/javascripts/niftyLayout.js +11 -0
  39. data/laf/javascripts/niftycube-details.js +298 -0
  40. data/laf/javascripts/niftycube.js +298 -0
  41. data/laf/javascripts/tarantula.js +10 -0
  42. data/laf/stylesheets/tarantula.css +345 -0
  43. data/laf/v2/detail.html +59 -0
  44. data/laf/v2/images/button_active.png +0 -0
  45. data/laf/v2/images/button_hover.png +0 -0
  46. data/laf/v2/images/button_inactive.png +0 -0
  47. data/laf/v2/images/header_bg.jpg +0 -0
  48. data/laf/v2/images/logo.png +0 -0
  49. data/laf/v2/images/tagline.png +0 -0
  50. data/laf/v2/index.html +77 -0
  51. data/laf/v2/stylesheets/tarantula.v2.css +324 -0
  52. data/lib/relevance/core_extensions/ellipsize.rb +34 -0
  53. data/lib/relevance/core_extensions/file.rb +9 -0
  54. data/lib/relevance/core_extensions/metaclass.rb +78 -0
  55. data/lib/relevance/core_extensions/response.rb +9 -0
  56. data/lib/relevance/core_extensions/string_chars_fix.rb +11 -0
  57. data/lib/relevance/core_extensions/test_case.rb +19 -0
  58. data/lib/relevance/tarantula/attack.rb +15 -0
  59. data/lib/relevance/tarantula/attack_form_submission.rb +75 -0
  60. data/lib/relevance/tarantula/attack_handler.rb +37 -0
  61. data/lib/relevance/tarantula/crawler.rb +264 -0
  62. data/lib/relevance/tarantula/detail.html.erb +82 -0
  63. data/lib/relevance/tarantula/form.rb +21 -0
  64. data/lib/relevance/tarantula/form_submission.rb +70 -0
  65. data/lib/relevance/tarantula/html_document_handler.rb +36 -0
  66. data/lib/relevance/tarantula/html_report_helper.rb +39 -0
  67. data/lib/relevance/tarantula/html_reporter.rb +105 -0
  68. data/lib/relevance/tarantula/index.html.erb +37 -0
  69. data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
  70. data/lib/relevance/tarantula/io_reporter.rb +34 -0
  71. data/lib/relevance/tarantula/link.rb +56 -0
  72. data/lib/relevance/tarantula/log_grabber.rb +16 -0
  73. data/lib/relevance/tarantula/rails_integration_proxy.rb +68 -0
  74. data/lib/relevance/tarantula/recording.rb +12 -0
  75. data/lib/relevance/tarantula/response.rb +13 -0
  76. data/lib/relevance/tarantula/result.rb +66 -0
  77. data/lib/relevance/tarantula/test_report.html.erb +32 -0
  78. data/lib/relevance/tarantula/tidy_handler.rb +32 -0
  79. data/lib/relevance/tarantula/transform.rb +17 -0
  80. data/lib/relevance/tarantula/w3c_validator.rb +33 -0
  81. data/lib/relevance/tarantula.rb +59 -0
  82. data/tasks/tarantula_tasks.rake +36 -0
  83. data/template/tarantula_test.rb +22 -0
  84. data/vendor/w3c_validators/CHANGELOG +14 -0
  85. data/vendor/w3c_validators/LICENSE +60 -0
  86. data/vendor/w3c_validators/README +120 -0
  87. data/vendor/w3c_validators/README.svn +4 -0
  88. data/vendor/w3c_validators/lib/w3c_validators/constants.rb +80 -0
  89. data/vendor/w3c_validators/lib/w3c_validators/css_validator.rb +149 -0
  90. data/vendor/w3c_validators/lib/w3c_validators/exceptions.rb +4 -0
  91. data/vendor/w3c_validators/lib/w3c_validators/feed_validator.rb +110 -0
  92. data/vendor/w3c_validators/lib/w3c_validators/markup_validator.rb +227 -0
  93. data/vendor/w3c_validators/lib/w3c_validators/message.rb +82 -0
  94. data/vendor/w3c_validators/lib/w3c_validators/results.rb +62 -0
  95. data/vendor/w3c_validators/lib/w3c_validators/validator.rb +157 -0
  96. data/vendor/w3c_validators/lib/w3c_validators.rb +5 -0
  97. data/vendor/w3c_validators/rakefile.rb +53 -0
  98. data/vendor/w3c_validators/test/fixtures/invalid_css.css +2 -0
  99. data/vendor/w3c_validators/test/fixtures/invalid_encoding.html +10 -0
  100. data/vendor/w3c_validators/test/fixtures/invalid_feed.xml +19 -0
  101. data/vendor/w3c_validators/test/fixtures/invalid_html5.html +16 -0
  102. data/vendor/w3c_validators/test/fixtures/invalid_markup.html +11 -0
  103. data/vendor/w3c_validators/test/fixtures/valid_css.css +2 -0
  104. data/vendor/w3c_validators/test/fixtures/valid_feed.xml +20 -0
  105. data/vendor/w3c_validators/test/fixtures/valid_html5.html +16 -0
  106. data/vendor/w3c_validators/test/fixtures/valid_markup.html +11 -0
  107. data/vendor/w3c_validators/test/test_css_validator.rb +51 -0
  108. data/vendor/w3c_validators/test/test_exceptions.rb +35 -0
  109. data/vendor/w3c_validators/test/test_feed_validator.rb +61 -0
  110. data/vendor/w3c_validators/test/test_helper.rb +6 -0
  111. data/vendor/w3c_validators/test/test_html5_validator.rb +64 -0
  112. data/vendor/w3c_validators/test/test_markup_validator.rb +94 -0
  113. data/vendor/xss-shield/MIT-LICENSE +20 -0
  114. data/vendor/xss-shield/README +76 -0
  115. data/vendor/xss-shield/init.rb +16 -0
  116. data/vendor/xss-shield/lib/xss_shield/erb_hacks.rb +111 -0
  117. data/vendor/xss-shield/lib/xss_shield/haml_hacks.rb +42 -0
  118. data/vendor/xss-shield/lib/xss_shield/safe_string.rb +47 -0
  119. data/vendor/xss-shield/lib/xss_shield/secure_helpers.rb +40 -0
  120. data/vendor/xss-shield/lib/xss_shield.rb +6 -0
  121. data/vendor/xss-shield/test/test_actionview_integration.rb +40 -0
  122. data/vendor/xss-shield/test/test_erb.rb +44 -0
  123. data/vendor/xss-shield/test/test_haml.rb +43 -0
  124. data/vendor/xss-shield/test/test_helpers.rb +25 -0
  125. data/vendor/xss-shield/test/test_safe_string.rb +55 -0
  126. metadata +218 -0
@@ -0,0 +1,120 @@
1
+ = W3C Validators Gem README
2
+
3
+ W3C Validators is a Ruby wrapper for the World Wide Web Consortium's online
4
+ validation services.
5
+
6
+ It supports the markup validator, the feed validator and the CSS validator.
7
+
8
+ === Installation
9
+
10
+ gem install w3c_validators
11
+
12
+ === Usage
13
+
14
+ There are three main validator classes available, the W3CValidators::MarkupValidator
15
+ (used for HTML), the W3CValidators::FeedValidator and the
16
+ W3CValidators::CSSValidator.
17
+
18
+ Each validator has offers three different validation methods.
19
+
20
+ * +validate_text+ methods take a string
21
+ * +validate_file+ methods take a path to a file or an IO object
22
+ * +validate_uri+ methods take a published URL
23
+
24
+ In addition, the W3CValidators::MarkupValidator has a validate_uri_quickly method, which
25
+ performs a HEAD request against the markup validation service. The Results
26
+ of this call give an error count but no error details.
27
+
28
+ ==== Using a local validator
29
+
30
+ Each of the three validators allows you to specify a custom path to the
31
+ validator. You can set your own validator like this:
32
+
33
+ validator = MarkupValidator.new(:validator_uri => 'http://localhost/check')
34
+
35
+ === Examples
36
+
37
+ ==== Example #1: Markup validator, local file
38
+
39
+ require 'w3c_validators'
40
+
41
+ include W3CValidators
42
+
43
+ @validator = MarkupValidator.new
44
+
45
+ # override the DOCTYPE
46
+ @validator.set_doctype!(:html32)
47
+
48
+ # turn on debugging messages
49
+ @validator.set_debug!(true)
50
+
51
+ file = File.dirname(__FILE__) + '/fixtures/markup.html'
52
+ results = @validator.validate_file(fp)
53
+
54
+ if results.errors.length > 0
55
+ results.errors.each do |err|
56
+ puts err.to_s
57
+ end
58
+ else
59
+ puts 'Valid!'
60
+ end
61
+
62
+ puts 'Debugging messages'
63
+
64
+ results.debug_messages.each do |key, value|
65
+ puts "#{key}: #{value}"
66
+ end
67
+
68
+
69
+ ==== Example #2: Feed validator, remote file
70
+
71
+ require 'w3c_validators'
72
+
73
+ include W3CValidators
74
+
75
+ @validator = FeedValidator.new
76
+
77
+ results = @validator.validate_uri('http://example.com/feed.xml')
78
+
79
+ if results.errors.length > 0
80
+ results.errors.each do |err|
81
+ puts err.to_s
82
+ end
83
+ else
84
+ puts 'Valid!'
85
+ end
86
+
87
+ ==== Example #3: CSS validator, text fragment
88
+
89
+ require 'w3c_validators'
90
+
91
+ include W3CValidators
92
+
93
+ @validator = CSSValidator.new
94
+
95
+ results = @validator.validate_text('body { margin: 0px; }')
96
+
97
+ if results.errors.length > 0
98
+ results.errors.each do |err|
99
+ puts err.to_s
100
+ end
101
+ else
102
+ puts 'Valid!'
103
+ end
104
+
105
+ === Tests
106
+
107
+ Run unit tests using <tt>rake test</tt>. Note that there is a one second delay
108
+ between each call to the W3C's validators per their request.
109
+
110
+
111
+ === Credits and code
112
+
113
+ Documentation and the source code are available at http://code.dunae.ca/w3c_validators.
114
+
115
+ Written by Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2007.
116
+
117
+ Thanks to Ryan King (http://theryanking.com/) for creating the 0.9.2 update.
118
+
119
+ Thanks to Ryan King (http://theryanking.com/), Jonathan Julian (http://jonathanjulian.org/)
120
+ and Sylvain LaFleur for creating the 0.9.3 update.
@@ -0,0 +1,4 @@
1
+ Based on rev 26, patched by Roman Shterenzon <romanbsd@yahoo.com>
2
+ in order to use POST instead of GET in order to avoid forming URIs that
3
+ are too long. The read_local_file method was changed so the file doesn't have
4
+ to be writeable (it was a bug).
@@ -0,0 +1,80 @@
1
+ module W3CValidators
2
+ CSS_PROFILES = { :css1 => 'CSS 1',
3
+ :css2 => 'CSS 2.0',
4
+ :css21 => 'CSS 1.0',
5
+ :css3 => 'CSS 3.0',
6
+ :svg => 'SVG',
7
+ :svgbasic => 'SVG Basic',
8
+ :svgtiny => 'SVG Tiny',
9
+ :mobile => 'Mobile',
10
+ :atsc_tv => 'ATSC TV',
11
+ :tv => 'TV'
12
+ }
13
+
14
+ DOCTYPES = { :xhtml10_strict => 'XHTML 1.0 Strict',
15
+ :xhtml10_transitional => 'XHTML 1.0 Transitional',
16
+ :xhtml10_frameset => 'XHTML 1.0 Frameset',
17
+ :xhtml401_strict => 'HTML 4.01 Strict',
18
+ :xhtml401_transitional => 'HTML 4.01 Transitional',
19
+ :xhtml401_framest => 'HTML 4.01 Frameset',
20
+ :html5 => 'HTML 5',
21
+ :html32 => 'HTML 3.2',
22
+ :html20 => 'HTML 2.0',
23
+ :iso_html => 'ISO/IEC 15445:2000 (&quot;ISO HTML&quot;)',
24
+ :xhtml11 => 'XHTML 1.1',
25
+ :xhtml_basic10 => 'XHTML Basic 1.0',
26
+ :xhtml_print10 => 'XHTML-Print 1.0',
27
+ :xhtml11_plus_mathml20 => 'XHTML 1.1 plus MathML 2.0',
28
+ :xhtml11_plus_mathml20_plus_svg11 => 'XHTML 1.1 plus MathML 2.0 plus SVG 1.1',
29
+ :mathml20=> 'MathML 2.0',
30
+ :svg10 => 'SVG 1.0',
31
+ :svg11 => 'SVG 1.1',
32
+ :svg11tiny => 'SVG 1.1 Tiny',
33
+ :svg11_basic => 'SVG 1.1 Basic',
34
+ :smil10 => 'SMIL 1.0',
35
+ :smil20 => 'SMIL 2.0'
36
+ }
37
+
38
+ CHARSETS = { :utf_8 => 'utf-8',
39
+ :utf_16 => 'utf-16',
40
+ :iso_8859_1 => 'iso-8859-1',
41
+ :iso_8859_2 => 'iso-8859-2',
42
+ :iso_8859_3 => 'iso-8859-3',
43
+ :iso_8859_4 => 'iso-8859-4',
44
+ :iso_8859_5 => 'iso-8859-5',
45
+ :iso_8859_6i => 'iso-8859-6-i',
46
+ :iso_8859_7 => 'iso-8859-7',
47
+ :iso_8859_8 => 'iso-8859-8',
48
+ :iso_8859_8i => 'iso-8859-8-i',
49
+ :iso_8859_9 => 'iso-8859-9',
50
+ :iso_8859_10 => 'iso-8859-10',
51
+ :iso_8859_11 => 'iso-8859-11',
52
+ :iso_8859_13 => 'iso-8859-13',
53
+ :iso_8859_14 => 'iso-8859-14',
54
+ :iso_8859_15 => 'iso-8859-15',
55
+ :iso_8859_16 => 'iso-8859-16',
56
+ :us_ascci => 'us-ascii',
57
+ :euc_jp => 'euc-jp',
58
+ :shift_jis => 'shift_jis',
59
+ :iso_2022_hp => 'iso-2022-jp',
60
+ :euc_jr => 'euc-kr',
61
+ :ksk_5601 => 'ksc_5601',
62
+ :gb_2312 => 'gb2312',
63
+ :gb_18030 => 'gb18030',
64
+ :big5 => 'big5',
65
+ :big5_hkscs => 'big5-HKSCS',
66
+ :tis_620 => 'tis-620',
67
+ :koi8_r => 'koi8-r',
68
+ :koi8_u => 'koi8-u',
69
+ :iso_ir_111 => 'iso-ir-111',
70
+ :macintosh => 'macintosh',
71
+ :windows_1250 => 'windows-1250',
72
+ :windows_1251 => 'windows-1251',
73
+ :windows_1252 => 'windows-1252',
74
+ :windows_1253 => 'windows-1253',
75
+ :windows_1254 => 'windows-1254',
76
+ :windows_1255 => 'windows-1255',
77
+ :windows_1256 => 'windows-1256',
78
+ :windows_1257 => 'windows-1257'
79
+ }
80
+ end
@@ -0,0 +1,149 @@
1
+ module W3CValidators
2
+ class CSSValidator < Validator
3
+ CSS_VALIDATOR_URI = 'http://jigsaw.w3.org/css-validator/validator'
4
+
5
+ # Create a new instance of the CSSValidator.
6
+ #
7
+ # ==== Options
8
+ # You can pass in your own validator's URI (i.e.
9
+ # <tt>CSSValidator.new(:validator_uri => 'http://localhost/check')</tt>).
10
+ def initialize(options = {})
11
+ if options[:validator_uri]
12
+ @validator_uri = URI.parse(options[:validator_uri])
13
+ options.delete(options[:validator_uri])
14
+ else
15
+ @validator_uri = URI.parse(CSS_VALIDATOR_URI)
16
+ end
17
+ super(options)
18
+ end
19
+
20
+ # The CSS profile used for the validation.
21
+ #
22
+ # +charset+ can be a string or a symbl from the W3CValidators::CSS_PROFILES hash.
23
+ #
24
+ # ==== Example
25
+ # set_profile!('css1')
26
+ # set_profile!(:css1)
27
+ def set_profile!(profile)
28
+ if profile.kind_of?(Symbol)
29
+ if CSS_PROFILES.has_key?(profile)
30
+ profile = profile.to_s
31
+ else
32
+ return
33
+ end
34
+ end
35
+ @options[:profile] = profile
36
+ end
37
+
38
+ # The warning level, no for no warnings, 0 for less warnings, 1or 2 for more warnings
39
+ def set_warn_level!(level = 2)
40
+ warn_levels = ['0','1','2','no']
41
+ return unless warn_levels.include?(level.to_s.downcase)
42
+
43
+ @options[:warning] = level
44
+ end
45
+
46
+ # The language used for the response.
47
+ def set_language!(lang = 'en')
48
+ @options[:lang] = lang
49
+ end
50
+
51
+ # Validate the CSS of an URI.
52
+ #
53
+ # Returns W3CValidators::Results.
54
+ def validate_uri(uri)
55
+ return validate({:uri => uri})
56
+ end
57
+
58
+ # Validate the CSS of a string.
59
+ #
60
+ # Returns W3CValidators::Results.
61
+ def validate_text(text)
62
+ return validate({:text => text})
63
+ end
64
+
65
+ # Validate the CSS of a local file.
66
+ #
67
+ # +file_path+ may be either the fully-expanded path to the file or
68
+ # an IO object (like File).
69
+ #
70
+ # Returns W3CValidators::Results.
71
+ def validate_file(file_path)
72
+ if file_path.respond_to? :read
73
+ src = file_path.read
74
+ else
75
+ src = read_local_file(file_path)
76
+ end
77
+ return validate_text(src)
78
+ end
79
+
80
+
81
+ protected
82
+ def validate(options) # :nodoc:
83
+ options = get_request_options(options)
84
+ response = send_request(options, :get)
85
+ @results = parse_soap_response(response.body)
86
+ @results
87
+ end
88
+
89
+ # Perform sanity checks on request params
90
+ def get_request_options(options) # :nodoc:
91
+ options = @options.merge(options)
92
+
93
+ options[:output] = SOAP_OUTPUT_PARAM
94
+
95
+ unless options[:uri] or options[:text]
96
+ raise ArgumentError, "an uri or text is required."
97
+ end
98
+
99
+ # URI should be a string. If it is a URI object, .to_s will
100
+ # be seamless; if it is not an exception will be raised.
101
+ if options[:uri] and not options[:uri].kind_of?(String)
102
+ options[:uri] = options[:uri].to_s
103
+ end
104
+
105
+ options
106
+ end
107
+
108
+
109
+ def parse_soap_response(response) # :nodoc:
110
+ doc = REXML::Document.new(response)
111
+
112
+ result_params = {}
113
+
114
+ {:uri => 'uri', :checked_by => 'checkedby', :validity => 'validity', :css_level => 'csslevel'}.each do |local_key, remote_key|
115
+ if val = doc.elements["//*[local-name()='cssvalidationresponse']/*[local-name()='#{remote_key.to_s}']"]
116
+ result_params[local_key] = val.text
117
+ end
118
+ end
119
+
120
+ results = Results.new(result_params)
121
+
122
+ ['warninglist', 'errorlist'].each do |list_type|
123
+ doc.elements.each("//*[local-name()='#{list_type.to_s}']") do |message_list|
124
+
125
+ if uri_node = message_list.elements["*[local-name()='uri']"]
126
+ uri = uri_node.text
127
+ end
128
+
129
+ [:warning, :error].each do |msg_type|
130
+ message_list.elements.each("*[local-name()='#{msg_type.to_s}']") do |message|
131
+ message_params = {}
132
+ message.each_element_with_text do |el|
133
+ message_params[el.name.to_sym] = el.text
134
+ end
135
+ message_params[:uri] = uri
136
+ results.add_message(msg_type, message_params)
137
+ end
138
+ end
139
+ end
140
+ end
141
+ return results
142
+
143
+ rescue Exception => e
144
+ handle_exception e
145
+ end
146
+
147
+
148
+ end
149
+ end
@@ -0,0 +1,4 @@
1
+ module W3CValidators
2
+ class ValidatorUnavailable < StandardError; end
3
+ class ParsingError < StandardError; end
4
+ end
@@ -0,0 +1,110 @@
1
+ module W3CValidators
2
+ class FeedValidator < Validator
3
+ FEED_VALIDATOR_URI = 'http://validator.w3.org/feed/check.cgi'
4
+
5
+ # Create a new instance of the FeedValidator.
6
+ #
7
+ # ==== Options
8
+ # You can pass in your own validator's URI (i.e.
9
+ # <tt>FeedValidator.new(:validator_uri => 'http://localhost/check')</tt>).
10
+ def initialize(options = {})
11
+ if options[:validator_uri]
12
+ @validator_uri = URI.parse(options[:validator_uri])
13
+ options.delete(options[:validator_uri])
14
+ else
15
+ @validator_uri = URI.parse(FEED_VALIDATOR_URI)
16
+ end
17
+ super(options)
18
+ end
19
+
20
+ # Validate a feed URI using a +SOAP+ request.
21
+ #
22
+ # Returns W3CValidators::Results.
23
+ def validate_uri(url)
24
+ return validate({:url => url})
25
+ end
26
+
27
+ # Validate a feed from a string.
28
+ #
29
+ # Returns W3CValidators::Results.
30
+ def validate_text(text)
31
+ return validate({:rawdata => text})
32
+ end
33
+
34
+ # Validate a local feed file.
35
+ #
36
+ # +file_path+ may be either the fully-expanded path to the file or
37
+ # an IO object (like File).
38
+ #
39
+ # Returns W3CValidators::Results.
40
+ def validate_file(file_path)
41
+ if file_path.respond_to? :read
42
+ src = file_path.read
43
+ else
44
+ src = read_local_file(file_path)
45
+ end
46
+ return validate_text(src)
47
+ end
48
+
49
+ protected
50
+ def validate(options) # :nodoc:
51
+ options = get_request_options(options)
52
+ response = send_request(options, :get)
53
+ @results = parse_soap_response(response.body)
54
+ @results
55
+ end
56
+
57
+ # Perform sanity checks on request params
58
+ def get_request_options(options) # :nodoc:
59
+ options = @options.merge(options)
60
+
61
+ options[:output] = SOAP_OUTPUT_PARAM
62
+
63
+ unless options[:url] or options[:rawdata]
64
+ raise ArgumentError, "an url or rawdata is required."
65
+ end
66
+
67
+ # URL should be a string. If it is a URL object, .to_s will
68
+ # be seamless; if it is not an exception will be raised.
69
+ if options[:url] and not options[:url].kind_of?(String)
70
+ options[:url] = options[:url].to_s
71
+ end
72
+
73
+ options
74
+ end
75
+
76
+ # Parse the SOAP XML response.
77
+ #
78
+ # +response+ must be a Net::HTTPResponse.
79
+ #
80
+ # Returns W3CValidators::Results.
81
+ def parse_soap_response(response) # :nodoc:
82
+ doc = REXML::Document.new(response)
83
+
84
+ result_params = {}
85
+
86
+ {:uri => 'uri', :checked_by => 'checkedby', :validity => 'validity'}.each do |local_key, remote_key|
87
+ if val = doc.elements["//*[local-name()='feedvalidationresponse']/*[local-name()='#{remote_key.to_s}']"]
88
+ result_params[local_key] = val.text
89
+ end
90
+ end
91
+
92
+ results = Results.new(result_params)
93
+
94
+ [:warning, :error].each do |msg_type|
95
+ doc.elements.each("//*[local-name()='#{msg_type.to_s}']") do |message|
96
+ message_params = {}
97
+ message.each_element_with_text do |el|
98
+ message_params[el.name.to_sym] = el.text
99
+ end
100
+ results.add_message(msg_type, message_params)
101
+ end
102
+ end
103
+
104
+ return results
105
+
106
+ rescue Exception => e
107
+ handle_exception e
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,227 @@
1
+ module W3CValidators
2
+ class MarkupValidator < Validator
3
+ MARKUP_VALIDATOR_URI = 'http://validator.w3.org/check'
4
+
5
+ # Create a new instance of the MarkupValidator.
6
+ #
7
+ # ==== Options
8
+ # The +options+ hash allows you to set request parameters (see
9
+ # http://validator.w3.org/docs/api.html#requestformat) quickly. Request
10
+ # parameters can also be set using set_charset!, set_debug! and set_doctype!.
11
+ #
12
+ # You can pass in your own validator's URI (i.e.
13
+ # <tt>MarkupValidator.new(:validator_uri => 'http://localhost/check')</tt>).
14
+ def initialize(options = {})
15
+ if options[:validator_uri]
16
+ @validator_uri = URI.parse(options[:validator_uri])
17
+ options.delete(options[:validator_uri])
18
+ else
19
+ @validator_uri = URI.parse(MARKUP_VALIDATOR_URI)
20
+ end
21
+ super(options)
22
+ end
23
+
24
+ # Specify the character encoding to use when parsing the document.
25
+ #
26
+ # When +only_as_fallback+ is +true+, the given encoding will only be
27
+ # used as a fallback value, in case the +charset+ is absent or unrecognized.
28
+ #
29
+ # +charset+ can be a string (e.g. <tt>set_charset!('utf-8')</tt>) or
30
+ # a symbol (e.g. <tt>set_charset!(:utf_8)</tt>) from the
31
+ # W3CValidators::CHARSETS hash.
32
+ #
33
+ # Has no effect when using validate_uri_quickly.
34
+ def set_charset!(charset, only_as_fallback = false)
35
+ if charset.kind_of?(Symbol)
36
+ if CHARSETS.has_key?(charset)
37
+ charset = CHARSETS[charset]
38
+ else
39
+ return
40
+ end
41
+ end
42
+ @options[:charset] = charset
43
+ @options[:fbc] = only_as_fallback
44
+ end
45
+
46
+ # Specify the Document Type (+DOCTYPE+) to use when parsing the document.
47
+ #
48
+ # When +only_as_fallback+ is +true+, the given document type will only be
49
+ # used as a fallback value, in case the document's +DOCTYPE+ declaration
50
+ # is missing or unrecognized.
51
+ #
52
+ # +doctype+ can be a string (e.g. <tt>set_doctype!('HTML 3.2')</tt>) or
53
+ # a symbol (e.g. <tt>set_doctype!(:html32)</tt>) from the
54
+ # W3CValidators::DOCTYPES hash.
55
+ #
56
+ # Has no effect when using validate_uri_quickly.
57
+ def set_doctype!(doctype, only_as_fallback = false)
58
+ if doctype.kind_of?(Symbol)
59
+ if DOCTYPES.has_key?(doctype)
60
+ doctype = DOCTYPES[doctype]
61
+ else
62
+ return
63
+ end
64
+ end
65
+ @options[:doctype] = doctype
66
+ @options[:fbd] = only_as_fallback
67
+ end
68
+
69
+ # When set the validator will output some extra debugging information on
70
+ # the validated resource (such as HTTP headers) and validation process
71
+ # (such as parser used, parse mode, etc.).
72
+ #
73
+ # Debugging information is stored in the Results +debug_messages+ hash.
74
+ # Custom debugging messages can be set with Results#add_debug_message.
75
+ #
76
+ # Has no effect when using validate_uri_quickly.
77
+ def set_debug!(debug = true)
78
+ @options[:debug] = debug
79
+ end
80
+
81
+ # Validate the markup of an URI using a +SOAP+ request.
82
+ #
83
+ # Returns W3CValidators::Results.
84
+ def validate_uri(uri)
85
+ return validate({:uri => uri}, false)
86
+ end
87
+
88
+ # Validate the markup of an URI using a +HEAD+ request.
89
+ #
90
+ # Returns W3CValidators::Results with an error count, not full error messages.
91
+ def validate_uri_quickly(uri)
92
+ return validate({:uri => uri}, true)
93
+ end
94
+
95
+ # Validate the markup of a string.
96
+ #
97
+ # Returns W3CValidators::Results.
98
+ def validate_text(text)
99
+ return validate({:fragment => text}, false)
100
+ end
101
+
102
+ # Validate the markup of a local file.
103
+ #
104
+ # +file_path+ may be either the fully-expanded path to the file or
105
+ # an IO object (like File).
106
+ #
107
+ # Returns W3CValidators::Results.
108
+ def validate_file(file_path)
109
+ if file_path.respond_to? :read
110
+ src = file_path.read
111
+ else
112
+ src = read_local_file(file_path)
113
+ end
114
+
115
+ return validate({:uploaded_file => src, :file_path => file_path}, false)
116
+ end
117
+
118
+ protected
119
+ def validate(options, quick = false) # :nodoc:
120
+ options = get_request_options(options)
121
+
122
+ if quick
123
+ response = send_request(options, :head)
124
+ @results = parse_head_response(response, options[:uri])
125
+ else
126
+ if options.has_key?(:uri)# or options.has_key?(:fragment)
127
+ response = send_request(options, :get)
128
+ else
129
+ response = send_request(options, :post)
130
+ end
131
+
132
+ @results = parse_soap_response(response.body)
133
+ end
134
+ @results
135
+ end
136
+
137
+ # Perform sanity checks on request params
138
+ def get_request_options(options) # :nodoc:
139
+ options = @options.merge(options)
140
+
141
+ options[:output] = SOAP_OUTPUT_PARAM
142
+
143
+ unless options[:uri] or options[:uploaded_file] or options[:fragment]
144
+ raise ArgumentError, "an uri, uploaded file or fragment is required."
145
+ end
146
+
147
+ # URI should be a string. If it is a URI object, .to_s will
148
+ # be seamless; if it is not an exception will be raised.
149
+ if options[:uri] and not options[:uri].kind_of?(String)
150
+ options[:uri] = options[:uri].to_s
151
+ end
152
+
153
+ # Convert booleans to integers
154
+ [:fbc, :fbd, :verbose, :debug, :ss, :outline].each do |k|
155
+ if options.has_key?(k) and not options[k].kind_of?(Fixnum)
156
+ options[k] = options[k] ? 1 : 0
157
+ end
158
+ end
159
+
160
+ options
161
+ end
162
+
163
+
164
+ # Parse the SOAP XML response.
165
+ #
166
+ # +response+ must be a Net::HTTPResponse.
167
+ #
168
+ # Returns W3CValidators::Results.
169
+ def parse_soap_response(response) # :nodoc:
170
+ doc = REXML::Document.new(response)
171
+
172
+ result_params = {}
173
+
174
+ {:doctype => 'm:doctype', :uri => 'm:uri', :charset => 'm:charset',
175
+ :checked_by => 'm:checkedby', :validity => 'm:validity'}.each do |local_key, remote_key|
176
+ if val = doc.elements["env:Envelope/env:Body/m:markupvalidationresponse/#{remote_key}"]
177
+ result_params[local_key] = val.text
178
+ end
179
+ end
180
+
181
+ results = Results.new(result_params)
182
+
183
+ {:warning => 'm:warnings/m:warninglist/m:warning', :error => 'm:errors/m:errorlist/m:error'}.each do |local_type, remote_type|
184
+ doc.elements.each("env:Envelope/env:Body/m:markupvalidationresponse/#{remote_type}") do |message|
185
+ message_params = {}
186
+ message.each_element_with_text do |el|
187
+ message_params[el.name.to_sym] = el.text
188
+ end
189
+ results.add_message(local_type, message_params)
190
+ end
191
+ end
192
+
193
+ doc.elements.each("env:Envelope/env:Body/env:Fault/env:Reason") do |message|
194
+ message.elements.each("env:Text") do |m|
195
+ results.add_message(:error, {:mesage => m.text})
196
+ end
197
+ end
198
+
199
+ doc.elements.each("env:Envelope/env:Body/m:markupvalidationresponse/m:debug") do |debug|
200
+ results.add_debug_message(debug.attribute('name').value, debug.text)
201
+ end
202
+ return results
203
+
204
+ rescue Exception => e
205
+ handle_exception e
206
+ end
207
+
208
+ # Parse the HEAD response into HTMLValidator::Results.
209
+ #
210
+ # +response+ must be a Net::HTTPResponse.
211
+ #
212
+ # Returns Results.
213
+ def parse_head_response(response, validated_uri = nil) # :nodoc:
214
+ validity = (response[HEAD_STATUS_HEADER].downcase == 'valid')
215
+
216
+ results = Results.new(:uri => validated_uri, :validity => validity)
217
+
218
+ # Fill the results with empty error messages so we can count them
219
+ errors = response[HEAD_ERROR_COUNT_HEADER].to_i
220
+ errors.times { results.add_error }
221
+
222
+ results
223
+ end
224
+
225
+
226
+ end
227
+ end