44 |
]); |
]); |
45 |
|
|
46 |
my $input = get_input_document ($http, $dom); |
my $input = get_input_document ($http, $dom); |
47 |
|
|
48 |
$out->input ($input); |
$out->input ($input); |
49 |
$out->unset_flush; |
$out->unset_flush; |
50 |
|
|
51 |
my $char_length = 0; |
my $result = WebHACC::Result->new; |
52 |
|
$result->output ($out); |
53 |
$out->start_section (id => 'document-info', title => 'Information'); |
$result->{conforming_min} = 1; |
54 |
$out->html (qq[<dl> |
$result->{conforming_max} = 1; |
|
<dt>Request URL</dt> |
|
|
<dd>]); |
|
|
$out->url ($input->{request_uri}); |
|
|
$out->html (q[<dt>Document URL<!-- HTML5 document's address? --> |
|
|
<dd>]); |
|
|
$out->url ($input->{uri}, id => 'anchor-document-url'); |
|
|
$out->html (q[ |
|
|
<script> |
|
|
document.title = '<' |
|
|
+ document.getElementById ('anchor-document-url').href + '> \\u2014 ' |
|
|
+ document.title; |
|
|
</script>]); |
|
|
## NOTE: no </dl> yet |
|
|
|
|
|
if (defined $input->{s}) { |
|
|
$char_length = length $input->{s}; |
|
|
|
|
|
$out->html (qq[<dt>Base URI<dd>]); |
|
|
$out->url ($input->{base_uri}); |
|
|
$out->html (qq[<dt>Internet Media Type</dt> |
|
|
<dd><code class="MIME" lang="en">]); |
|
|
$out->text ($input->{media_type}); |
|
|
$out->html (qq[</code> ]); |
|
|
if ($input->{media_type_overridden}) { |
|
|
$out->html ('<em>(overridden)</em>'); |
|
|
} elsif (defined $input->{official_type}) { |
|
|
if ($input->{media_type} eq $input->{official_type}) { |
|
|
# |
|
|
} else { |
|
|
$out->html ('<em>(sniffed; official type is: <code class=MIME lang=en>'); |
|
|
$out->text ($input->{official_type}); |
|
|
$out->html ('</code>)'); |
|
|
} |
|
|
} else { |
|
|
$out->html ('<em>(sniffed)</em>'); |
|
|
} |
|
|
$out->html (q[<dt>Character Encoding<dd>]); |
|
|
if (defined $input->{charset}) { |
|
|
$out->html ('<code class="charset" lang="en">'); |
|
|
$out->text ($input->{charset}); |
|
|
$out->html ('</code>'); |
|
|
} else { |
|
|
$out->text ('(none)'); |
|
|
} |
|
|
$out->html (' <em>overridden</em>') if $input->{charset_overridden}; |
|
|
$out->html (qq[ |
|
|
<dt>Length</dt> |
|
|
<dd>$char_length byte@{[$char_length == 1 ? '' : 's']}</dd> |
|
|
</dl> |
|
55 |
|
|
56 |
<script src="../cc-script.js"></script> |
$out->html ('<script src="../cc-script.js"></script>'); |
|
]); |
|
|
$out->end_section; |
|
57 |
|
|
58 |
my $result = WebHACC::Result->new; |
check_and_print ($input => $result => $out); |
59 |
$result->{conforming_min} = 1; |
|
60 |
$result->{conforming_max} = 1; |
$result->generate_result_section; |
|
check_and_print ($input => $result => $out); |
|
|
print_result_section ($result); |
|
|
} else { |
|
|
$out->html ('</dl>'); |
|
|
$out->end_section; |
|
|
print_result_input_error_section ($input); |
|
|
} |
|
61 |
|
|
62 |
$out->nav_list; |
$out->nav_list; |
63 |
|
|
64 |
exit; |
exit; |
65 |
} |
} |
66 |
|
|
|
sub add_error ($$$) { |
|
|
my ($layer, $err, $result) = @_; |
|
|
if (defined $err->{level}) { |
|
|
if ($err->{level} eq 's') { |
|
|
$result->{$layer}->{should}++; |
|
|
$result->{$layer}->{score_min} -= 2; |
|
|
$result->{conforming_min} = 0; |
|
|
} elsif ($err->{level} eq 'w' or $err->{level} eq 'g') { |
|
|
$result->{$layer}->{warning}++; |
|
|
} elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') { |
|
|
$result->{$layer}->{unsupported}++; |
|
|
$result->{unsupported} = 1; |
|
|
} elsif ($err->{level} eq 'i') { |
|
|
# |
|
|
} else { |
|
|
$result->{$layer}->{must}++; |
|
|
$result->{$layer}->{score_max} -= 2; |
|
|
$result->{$layer}->{score_min} -= 2; |
|
|
$result->{conforming_min} = 0; |
|
|
$result->{conforming_max} = 0; |
|
|
} |
|
|
} else { |
|
|
$result->{$layer}->{must}++; |
|
|
$result->{$layer}->{score_max} -= 2; |
|
|
$result->{$layer}->{score_min} -= 2; |
|
|
$result->{conforming_min} = 0; |
|
|
$result->{conforming_max} = 0; |
|
|
} |
|
|
} # add_error |
|
|
|
|
67 |
sub check_and_print ($$$) { |
sub check_and_print ($$$) { |
68 |
my ($input, $result, $out) = @_; |
my ($input, $result, $out) = @_; |
69 |
my $original_input = $out->input; |
my $original_input = $out->input; |
70 |
$out->input ($input); |
$out->input ($input); |
71 |
|
|
72 |
print_http_header_section ($input, $result); |
$input->generate_info_section ($result); |
73 |
|
|
74 |
my @subdoc; |
$input->generate_transfer_sections ($result); |
75 |
|
|
76 |
|
unless (defined $input->{s}) { |
77 |
|
$result->{conforming_min} = 0; |
78 |
|
return; |
79 |
|
} |
80 |
|
|
81 |
my $checker_class = { |
my $checker_class = { |
82 |
'text/cache-manifest' => 'WebHACC::Language::CacheManifest', |
'text/cache-manifest' => 'WebHACC::Language::CacheManifest', |
109 |
$checker->generate_syntax_error_section; |
$checker->generate_syntax_error_section; |
110 |
$checker->generate_source_string_section; |
$checker->generate_source_string_section; |
111 |
|
|
112 |
|
my @subdoc; |
113 |
$checker->onsubdoc (sub { |
$checker->onsubdoc (sub { |
114 |
push @subdoc, shift; |
push @subdoc, shift; |
115 |
}); |
}); |
140 |
|
|
141 |
my $id_prefix = 0; |
my $id_prefix = 0; |
142 |
for my $_subinput (@subdoc) { |
for my $_subinput (@subdoc) { |
143 |
my $subinput = WebHACC::Input->new; |
my $subinput = WebHACC::Input::Subdocument->new (++$id_prefix); |
144 |
$subinput->{$_} = $_subinput->{$_} for keys %$_subinput; |
$subinput->{$_} = $_subinput->{$_} for keys %$_subinput; |
|
$subinput->id_prefix ('subdoc-' . ++$id_prefix); |
|
|
$subinput->nested (1); |
|
145 |
$subinput->{base_uri} = $subinput->{container_node}->base_uri |
$subinput->{base_uri} = $subinput->{container_node}->base_uri |
146 |
unless defined $subinput->{base_uri}; |
unless defined $subinput->{base_uri}; |
147 |
my $ebaseuri = htescape ($subinput->{base_uri}); |
$subinput->{parent_input} = $input; |
|
$out->start_section (id => $subinput->id_prefix, |
|
|
title => qq[Subdocument #$id_prefix]); |
|
|
print STDOUT qq[ |
|
|
<dl> |
|
|
<dt>Internet Media Type</dt> |
|
|
<dd><code class="MIME" lang="en">@{[htescape $subinput->{media_type}]}</code> |
|
|
<dt>Container Node</dt> |
|
|
<dd>@{[get_node_link ($input, $subinput->{container_node})]}</dd> |
|
|
<dt>Base <abbr title="Uniform Resource Identifiers">URI</abbr></dt> |
|
|
<dd><code class=URI><<a href="$ebaseuri">$ebaseuri</a>></code></dd> |
|
|
</dl>]; |
|
148 |
|
|
149 |
$subinput->{id_prefix} .= '-'; |
$subinput->start_section ($result); |
150 |
check_and_print ($subinput => $result => $out); |
check_and_print ($subinput => $result => $out); |
151 |
|
$subinput->end_section ($result); |
|
$out->end_section; |
|
152 |
} |
} |
153 |
|
|
154 |
$out->input ($original_input); |
$out->input ($original_input); |
155 |
} # check_and_print |
} # check_and_print |
156 |
|
|
|
sub print_http_header_section ($$) { |
|
|
my ($input, $result) = @_; |
|
|
return unless defined $input->{header_status_code} or |
|
|
defined $input->{header_status_text} or |
|
|
@{$input->{header_field} or []}; |
|
|
|
|
|
$out->start_section (id => 'source-header', title => 'HTTP Header'); |
|
|
print STDOUT qq[<p><strong>Note</strong>: Due to the limitation of the |
|
|
network library in use, the content of this section might |
|
|
not be the real header.</p> |
|
|
|
|
|
<table><tbody> |
|
|
]; |
|
|
|
|
|
if (defined $input->{header_status_code}) { |
|
|
print STDOUT qq[<tr><th scope="row">Status code</th>]; |
|
|
print STDOUT qq[<td>]; |
|
|
$out->code ($input->{header_status_code}); |
|
|
} |
|
|
if (defined $input->{header_status_text}) { |
|
|
print STDOUT qq[<tr><th scope="row">Status text</th>]; |
|
|
print STDOUT qq[<td>]; |
|
|
$out->code ($input->{header_status_text}); |
|
|
} |
|
|
|
|
|
for (@{$input->{header_field}}) { |
|
|
print STDOUT qq[<tr><th scope="row">]; |
|
|
$out->code ($_->[0]); |
|
|
print STDOUT qq[<td>]; |
|
|
$out->code ($_->[1]); |
|
|
} |
|
|
|
|
|
print STDOUT qq[</tbody></table>]; |
|
|
|
|
|
$out->end_section; |
|
|
} # print_http_header_section |
|
|
|
|
157 |
sub print_table_section ($$) { |
sub print_table_section ($$) { |
158 |
my ($input, $tables) = @_; |
my ($input, $tables) = @_; |
159 |
|
|
290 |
} |
} |
291 |
} # get_rdf_resource_html |
} # get_rdf_resource_html |
292 |
|
|
|
sub print_result_section ($) { |
|
|
my $result = shift; |
|
|
|
|
|
$out->start_section (id => 'result-summary', |
|
|
title => 'Result'); |
|
|
|
|
|
if ($result->{unsupported} and $result->{conforming_max}) { |
|
|
print STDOUT qq[<p class=uncertain id=result-para>The conformance |
|
|
checker cannot decide whether the document is conforming or |
|
|
not, since the document contains one or more unsupported |
|
|
features. The document might or might not be conforming.</p>]; |
|
|
} elsif ($result->{conforming_min}) { |
|
|
print STDOUT qq[<p class=PASS id=result-para>No conformance-error is |
|
|
found in this document.</p>]; |
|
|
} elsif ($result->{conforming_max}) { |
|
|
print STDOUT qq[<p class=SEE-RESULT id=result-para>This document |
|
|
is <strong>likely <em>non</em>-conforming</strong>, but in rare case |
|
|
it might be conforming.</p>]; |
|
|
} else { |
|
|
print STDOUT qq[<p class=FAIL id=result-para>This document is |
|
|
<strong><em>non</em>-conforming</strong>.</p>]; |
|
|
} |
|
|
|
|
|
print STDOUT qq[<table> |
|
|
<colgroup><col><colgroup><col><col><col><colgroup><col> |
|
|
<thead> |
|
|
<tr><th scope=col></th> |
|
|
<th scope=col><a href="../error-description#level-m"><em class=rfc2119>MUST</em>‐level |
|
|
Errors</a></th> |
|
|
<th scope=col><a href="../error-description#level-s"><em class=rfc2119>SHOULD</em>‐level |
|
|
Errors</a></th> |
|
|
<th scope=col><a href="../error-description#level-w">Warnings</a></th> |
|
|
<th scope=col>Score</th></tr></thead><tbody>]; |
|
|
|
|
|
my $must_error = 0; |
|
|
my $should_error = 0; |
|
|
my $warning = 0; |
|
|
my $score_min = 0; |
|
|
my $score_max = 0; |
|
|
my $score_base = 20; |
|
|
my $score_unit = $score_base / 100; |
|
|
for ( |
|
|
[Transfer => 'transfer', ''], |
|
|
[Character => 'char', ''], |
|
|
[Syntax => 'syntax', '#parse-errors'], |
|
|
[Structure => 'structure', '#document-errors'], |
|
|
) { |
|
|
$must_error += ($result->{$_->[1]}->{must} += 0); |
|
|
$should_error += ($result->{$_->[1]}->{should} += 0); |
|
|
$warning += ($result->{$_->[1]}->{warning} += 0); |
|
|
$score_min += (($result->{$_->[1]}->{score_min} *= $score_unit) += $score_base); |
|
|
$score_max += (($result->{$_->[1]}->{score_max} *= $score_unit) += $score_base); |
|
|
|
|
|
my $uncertain = $result->{$_->[1]}->{unsupported} ? '?' : ''; |
|
|
my $label = $_->[0]; |
|
|
if ($result->{$_->[1]}->{must} or |
|
|
$result->{$_->[1]}->{should} or |
|
|
$result->{$_->[1]}->{warning} or |
|
|
$result->{$_->[1]}->{unsupported}) { |
|
|
$label = qq[<a href="$_->[2]">$label</a>]; |
|
|
} |
|
|
|
|
|
print STDOUT qq[<tr class="@{[$uncertain ? 'uncertain' : '']}"><th scope=row>$label</th><td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{must}$uncertain</td><td class="@{[$result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">$result->{$_->[1]}->{should}$uncertain</td><td>$result->{$_->[1]}->{warning}$uncertain</td>]; |
|
|
if ($uncertain) { |
|
|
print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : $result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">−∞..$result->{$_->[1]}->{score_max}]; |
|
|
} elsif ($result->{$_->[1]}->{score_min} != $result->{$_->[1]}->{score_max}) { |
|
|
print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : 'SEE-RESULT']}">$result->{$_->[1]}->{score_min}..$result->{$_->[1]}->{score_max}]; |
|
|
} else { |
|
|
print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{score_min}]; |
|
|
} |
|
|
print qq[ / 20]; |
|
|
} |
|
|
|
|
|
$score_max += $score_base; |
|
|
|
|
|
print STDOUT qq[ |
|
|
<tr class=uncertain><th scope=row>Semantics</th><td>0?</td><td>0?</td><td>0?</td><td>−∞..$score_base / 20 |
|
|
</tbody> |
|
|
<tfoot><tr class=uncertain><th scope=row>Total</th> |
|
|
<td class="@{[$must_error ? 'FAIL' : '']}">$must_error?</td> |
|
|
<td class="@{[$should_error ? 'SEE-RESULT' : '']}">$should_error?</td> |
|
|
<td>$warning?</td> |
|
|
<td class="@{[$must_error ? 'FAIL' : $should_error ? 'SEE-RESULT' : '']}"><strong>−∞..$score_max</strong> / 100 |
|
|
</table> |
|
|
|
|
|
<p><strong>Important</strong>: This conformance checking service |
|
|
is <em>under development</em>. The result above might be <em>wrong</em>.</p>]; |
|
|
$out->end_section; |
|
|
} # print_result_section |
|
|
|
|
|
sub print_result_input_error_section ($) { |
|
|
my $input = shift; |
|
|
$out->start_section (id => 'result-summary', title => 'Result'); |
|
|
print STDOUT qq[ |
|
|
<p><em><strong>Input Error</strong>: @{[htescape ($input->{error_status_text})]}</em></p>]; |
|
|
$out->end_section; |
|
|
} # print_result_input_error_section |
|
|
|
|
293 |
{ |
{ |
294 |
my $Msg = {}; |
my $Msg = {}; |
295 |
|
|
351 |
sub get_input_document ($$) { |
sub get_input_document ($$) { |
352 |
my ($http, $dom) = @_; |
my ($http, $dom) = @_; |
353 |
|
|
354 |
my $request_uri = $http->get_parameter ('uri'); |
require Encode; |
355 |
|
my $request_uri = Encode::decode ('utf-8', $http->get_parameter ('uri')); |
356 |
my $r = WebHACC::Input->new; |
my $r = WebHACC::Input->new; |
357 |
if (defined $request_uri and length $request_uri) { |
if (defined $request_uri and length $request_uri) { |
358 |
my $uri = $dom->create_uri_reference ($request_uri); |
my $uri = $dom->create_uri_reference ($request_uri); |
359 |
unless ({ |
unless ({ |
360 |
http => 1, |
http => 1, |
361 |
}->{lc $uri->uri_scheme}) { |
}->{lc $uri->uri_scheme}) { |
362 |
return {uri => $request_uri, request_uri => $request_uri, |
$r = WebHACC::Input::Error->new; |
363 |
error_status_text => 'URI scheme not allowed'}; |
$r->{uri} = $request_uri; |
364 |
|
$r->{request_uri} = $request_uri; |
365 |
|
$r->{error_status_text} = 'URL scheme not allowed'; |
366 |
} |
} |
367 |
|
|
368 |
require Message::Util::HostPermit; |
require Message::Util::HostPermit; |
389 |
Allow host=* |
Allow host=* |
390 |
EOH |
EOH |
391 |
unless ($host_permit->check ($uri->uri_host, $uri->uri_port || 80)) { |
unless ($host_permit->check ($uri->uri_host, $uri->uri_port || 80)) { |
392 |
return {uri => $request_uri, request_uri => $request_uri, |
my $r = WebHACC::Input::Error->new; |
393 |
error_status_text => 'Connection to the host is forbidden'}; |
$r->{uri} = $request_uri; |
394 |
|
$r->{request_uri} = $request_uri; |
395 |
|
$r->{error_status_text} = 'Connection to the host is forbidden'; |
396 |
|
return $r; |
397 |
} |
} |
398 |
|
|
399 |
require LWP::UserAgent; |
require LWP::UserAgent; |