/[suikacvs]/markup/html/whatpm/Whatpm/CacheManifest.pm
Suika

Contents of /markup/html/whatpm/Whatpm/CacheManifest.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download)
Sun Nov 4 11:49:44 2007 UTC (17 years ago) by wakaba
Branch: MAIN
++ ChangeLog	4 Nov 2007 11:48:54 -0000
2007-11-04  Wakaba  <wakaba@suika.fam.cx>

	* readme.en.html: Link to |Whatpm::CacheManifest|.

++ whatpm/Whatpm/ChangeLog	4 Nov 2007 11:49:27 -0000
	* Makefile: |CacheManifest.html| is added.

	* CacheManifest.pod: New file.

2007-11-04  Wakaba  <wakaba@suika.fam.cx>

1 package Whatpm::CacheManifest;
2 use strict;
3 our $VERSION=do{my @r=(q$Revision: 1.50 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4 require Message::URI::URIReference;
5
6 sub parse_byte_string ($$$$$) {
7 require Encode;
8 my $s = Encode::decode ('utf-8', $_[1]);
9 return $_[0]->_parse (\$s, $_[2], $_[3], $_[4] || sub {
10 my %err = @_;
11 warn $err{type}, "\n";
12 });
13 } # parse_byte_string
14
15 sub parse_char_string ($$$$$) {
16 return $_[0]->_parse (\($_[1]), $_[2], $_[3], $_[4] || sub {
17 my %err = @_;
18 warn $err{type}, "\n";
19 });
20 } # parse_char_string
21
22 sub _parse ($$$$$) {
23 #my (undef, $input, $manifest_uri, $base_uri, $onerror) = @_;
24
25 ## NOTE: A manifest MUST be labeled as text/cache-manifest. (This should
26 ## be checked in upper-level).
27 ## NOTE: No "MUST" for being UTF-8.
28 ## NOTE: A |text/cache-manifest| MUST be a cache manifest.
29 ## NOTE: Newlines MUST be CR/CRLF/LF. (We don't and can't check this.)
30
31 my $m_uri = Message::DOM::DOMImplementation->create_uri_reference ($_[2]);
32 my $m_scheme = $m_uri->uri_scheme;
33
34 my $onerror = $_[4];
35 my $must_level = 'm';
36 my $warn_level = 'w';
37 my $line_number = 1;
38
39 ## Same scheme/host/port
40 my $same_shp = sub {
41 ## TODO: implement this algorithm correctly!
42
43 my $u1 = shift;
44
45 unless (lc $u1->uri_scheme eq lc $m_scheme) {
46 return 0;
47 }
48
49 return 0 unless defined $u1->uri_authority;
50 return 0 unless defined $m_uri->uri_authority;
51
52 return 0 unless $u1->uri_host eq $m_uri->uri_host;
53 return 0 unless $u1->uri_port eq $m_uri->uri_port;
54
55 return 1;
56 }; # $same_shp
57
58 ## Step 5
59 my $input = $_[1];
60
61 ## Step 1: MUST bytes --UTF-8--> characters.
62 ## NOTE: illegal(s) -> U+FFFD, U+0000 -> U+FFFD
63 $$input =~ tr/\x00/\x{FFFD}/;
64
65 ## Step 2
66 my $explicit_uris = [];
67
68 ## Step 3
69 my $fallback_uris = {};
70
71 ## Step 4
72 my $online_whitelist_uris = [];
73
74 ## Step 6
75 pos ($$input) = 0;
76
77 ## Step 7
78 ## Skip BOM ## NOTE: MAY in syntax.
79
80 ## Step 8-10
81 unless ($$input =~ /^CACHE MANIFEST[\x20\x09]*(?![^\x0D\x0A])/gc) {
82 $onerror->(type => 'not manifest', level => $must_level,
83 line => $line_number, column => 1); ## NOTE: MUST in syntax.
84 return; ## Not a manifest.
85 }
86
87 ## Step 11
88 ## This is a cache manifest.
89
90 ## Step 12
91 my $mode = 'explicit';
92
93 ## NOTE: MUST be (blank line|comment|section head|data for the current
94 ## section)*.
95
96 ## Step 13
97 START_OF_LINE: while (pos $$input < length $$input) {
98 $$input =~ /([\x0A\x0D\x20\x09]+)/gc;
99 my $v = $1;
100 $line_number++ for $v =~ /\x0D\x0A?|\x0D/g;
101
102 ## Step 14
103 $$input =~ /([^\x0A\x0D]*)/gc;
104 my $line = $1;
105
106 ## Step 15
107 next START_OF_LINE if $line =~ /^#/;
108
109 ## Step 16
110 $line =~ s/[\x20\x09]+\z//;
111
112 if ($line eq 'CACHE:') {
113 ## Step 17
114 $mode = 'explicit';
115 next START_OF_LINE;
116 } elsif ($line eq 'FALLBACK:') {
117 ## Step 18
118 $mode = 'fallback';
119 next START_OF_LINE;
120 } elsif ($line eq 'NETWORK:') {
121 ## Step 19
122 $mode = 'online whitelist';
123 next START_OF_LINE;
124 }
125
126 ## NOTE: "URIs that are to be fallback pages associated with
127 ## opportunistic caching namespaces, and those namespaces themselves,
128 ## MUST be given in fallback sections, with the namespace being the
129 ## first URI of the data line, and the corresponding fallback page
130 ## being the second URI. All the other pages to be cached MUST be
131 ## listed in explicit sections." in writing section can't be tested.
132 ## NOTE: "URIs that the user agent is to put into the online whitelist
133 ## MUST all be specified in online whitelist sections." in writing
134 ## section can't be tested.
135
136 ## NOTE: "Relative URIs MUST be given relative to the manifest's own URI."
137 ## requirement in writing section can't be tested.
138
139 ## Step 20
140 if ($mode eq 'explicit') {
141 my $uri = Message::DOM::DOMImplementation->create_uri_reference ($line);
142
143 unless ($uri->is_iri_reference_3987) {
144 $onerror->(type => 'URI::syntax error:iriref3987',
145 level => $must_level, line => $line_number, column => 1,
146 value => $line);
147 next START_OF_LINE; ## NOTE: MUST in syntax.
148 }
149
150 $uri = $uri->get_absolute_reference ($_[3]);
151
152 if (defined $uri->uri_fragment) {
153 $uri->uri_fragment (undef);
154 $onerror->(type => 'URI fragment not allowed',
155 level => $must_level, line => $line_number, column => 1,
156 value => $line);
157 ## NOTE: MUST in writing section.
158 }
159
160 my $scheme = $uri->uri_scheme;
161 unless (defined $scheme and $scheme eq $m_scheme) {
162 $onerror->(type => 'different scheme from manifest',
163 level => $warn_level, line => $line_number, column => 1,
164 value => $uri->uri_reference);
165 next START_OF_LINE;
166 }
167 ## ISSUE: case-insensitive?
168
169 push @$explicit_uris, $uri->uri_reference;
170 } elsif ($mode eq 'fallback') {
171 my ($p1, $p2) = split /[\x20\x09]+/, $line, 2;
172
173 unless (defined $p2) {
174 $onerror->(type => 'no fallback entry URI',
175 level => $must_level, line => $line_number, column => 1,
176 value => $line);
177 next START_OF_LINE; ## NOTE: MUST in syntax.
178 }
179
180 my $u1 = Message::DOM::DOMImplementation->create_uri_reference ($p1);
181
182 unless ($u1->is_iri_reference_3987) {
183 $onerror->(type => 'URI::syntax error:iriref3987',
184 level => $must_level, line => $line_number, column => 1,
185 index => 0, value => $p1);
186 next START_OF_LINE; ## NOTE: MUST in syntax.
187 }
188
189 my $u2 = Message::DOM::DOMImplementation->create_uri_reference ($p2);
190
191 unless ($u2->is_iri_reference_3987) {
192 $onerror->(type => 'URI::syntax error:iriref3987',
193 level => $must_level, line => $line_number, column => 1,
194 index => 1, value => $p2);
195 next START_OF_LINE; ## NOTE: MUST in syntax.
196 }
197
198 if (defined $u1->uri_fragment) {
199 $onerror->(type => 'URI fragment not allowed',
200 level => $must_level, line => $line_number, column => 1,
201 index => 0, value => $p1);
202 ## NOTE: MUST in writing section.
203 ## ISSUE: Not dropped
204 }
205
206 if (defined $u2->uri_fragment) {
207 $onerror->(type => 'URI fragment not allowed',
208 level => $must_level, line => $line_number, column => 1,
209 index => 1, value => $p2);
210 ## NOTE: MUST in writing section.
211 ## ISSUE: Not dropped
212 }
213
214 $u1 = $u1->get_absolute_reference ($_[3]);
215 $u2 = $u2->get_absolute_reference ($_[3]);
216
217 if (exists $fallback_uris->{$u1->uri_reference}) {
218 $onerror->(type => 'duplicate oc namespace',
219 level => $must_level, line => $line_number, column => 1,
220 index => 0, value => $u1->uri_reference);
221 next START_OF_LINE; ## NOTE: MUST in syntax.
222 }
223
224 unless ($same_shp->($u1)) {
225 $onerror->(type => 'different shp from manifest',
226 level => $must_level, line => $line_number, column => 1,
227 index => 0, value => $u1->uri_reference);
228 next START_OF_LINE; ## NOTE: MUST in syntax.
229 }
230
231 my $u2_scheme = $u2->uri_scheme;
232 unless (defined $u2_scheme and $u2_scheme eq $m_scheme) {
233 $onerror->(type => 'different scheme from manifest',
234 level => $warn_level, line => $line_number, column => 1,
235 index => 1, value => $u2->uri_reference);
236 next START_OF_LINE;
237 }
238
239 $fallback_uris->{$u1->uri_reference} = $u2->uri_reference;
240 } elsif ($mode eq 'online whitelist') {
241 my $uri = Message::DOM::DOMImplementation->create_uri_reference ($line);
242
243 unless ($uri->is_iri_reference_3987) {
244 $onerror->(type => 'URI::syntax error:iriref3987',
245 level => $must_level, line => $line_number, column => 1,
246 value => $line);
247 next START_OF_LINE; ## NOTE: MUST in syntax.
248 }
249
250 $uri = $uri->get_absolute_reference ($_[3]);
251
252 if (defined $uri->uri_fragment) {
253 $uri->uri_fragment (undef);
254 $onerror->(type => 'URI fragment not allowed',
255 level => $must_level, line => $line_number, column => 1,
256 value => $line);
257 ## NOTE: MUST in writing section.
258 }
259
260 my $scheme = $uri->uri_scheme;
261 unless (defined $scheme and $scheme eq $m_scheme) {
262 $onerror->(type => 'different scheme from manifest',
263 level => $warn_level, line => $line_number, column => 1,
264 value => $uri->uri_reference);
265 next START_OF_LINE;
266 }
267
268 push @$online_whitelist_uris, $uri->uri_reference;
269 }
270
271 ## Step 21
272 #next START_OF_LINE;
273 } # START_OF_LINE
274
275 ## Step 22
276 return [$explicit_uris, $fallback_uris, $online_whitelist_uris];
277 } # _parse
278
279 sub check_manifest ($$$) {
280 my (undef, $manifest, $onerror) = @_;
281
282 my $listed = {};
283 my $must_level = 'm';
284
285 require Whatpm::URIChecker;
286
287 for my $uri (@{$manifest->[0]}) {
288 $listed->{$uri} = 1;
289
290 Whatpm::URIChecker->check_iri_reference ($uri, sub {
291 my %opt = @_;
292 $onerror->(level => $opt{level}, value => $uri,
293 type => 'URI::'.$opt{type}.
294 (defined $opt{position} ? ':'.$opt{position} : ''));
295 });
296 }
297
298 for my $uri (values %{$manifest->[1]}) {
299 $listed->{$uri} = 1;
300
301 Whatpm::URIChecker->check_iri_reference ($uri, sub {
302 my %opt = @_;
303 $onerror->(level => $opt{level}, index => 1, value => $uri,
304 type => 'URI::'.$opt{type}.
305 (defined $opt{position} ? ':'.$opt{position} : ''));
306 });
307 }
308
309 for my $uri (keys %{$manifest->[1]}) {
310 Whatpm::URIChecker->check_iri_reference ($uri, sub {
311 my %opt = @_;
312 $onerror->(level => $opt{level}, index => 0, value => $uri,
313 type => 'URI::'.$opt{type}.
314 (defined $opt{position} ? ':'.$opt{position} : ''));
315 });
316 }
317
318 for my $uri (@{$manifest->[2]}) {
319 if ($listed->{$uri}) {
320 $onerror->(type => 'both in entries and whitelist',
321 level => $must_level, value => $uri);
322 ## NOTE: MUST in writing section.
323 }
324
325 Whatpm::URIChecker->check_iri_reference ($uri, sub {
326 my %opt = @_;
327 $onerror->(level => $opt{level}, value => $uri,
328 type => 'URI::'.$opt{type}.
329 (defined $opt{position} ? ':'.$opt{position} : ''));
330 });
331 }
332 } # check_manifest
333
334
335 =head1 LICENSE
336
337 Copyright 2007 Wakaba <w@suika.fam.cx>
338
339 This library is free software; you can redistribute it
340 and/or modify it under the same terms as Perl itself.
341
342 =cut
343
344 1;
345 # $Date: 2007/08/06 10:56:50 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24