/[suikacvs]/messaging/manakai/lib/Message/DOM/Attr.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Attr.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (hide annotations) (download)
Sun Jul 8 13:04:36 2007 UTC (17 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.8: +4 -13 lines
++ manakai/t/ChangeLog	8 Jul 2007 13:03:58 -0000
	* DOM-Element.t: Tests for |attributes| are added.

	* DOM-Entity.t: Tests for |is_externally_declared|
	and |input_encoding| are added.

	* DOM-Node.t: Test data for |tag_name| and
	|get_feature| are added.

2007-07-08  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/DOM/ChangeLog	8 Jul 2007 13:02:01 -0000
	* Attr.pm (value, node_value): Now it is defined
	as |text_content| itself.

	* AttributeDefinition.pm, ElementTypeDefinition.pm,
	Node.pm (AUTOLOAD): Unused block is removed.

	* CDATASection.pm, DocumentFragment.pm (AUTOLOAD): Removed.  Unused.

	* DocumentType.pm (internal_subset): Implemented.

	* Entity.pm (is_externally_declared, input_encoding,
	xml_version): Implemented.

	* ProcessingInstruction.pm (target, data): Implemented.

2007-07-08  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 package Message::DOM::Attr;
2     use strict;
3 wakaba 1.9 our $VERSION=do{my @r=(q$Revision: 1.8 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4 wakaba 1.1 push our @ISA, 'Message::DOM::Node', 'Message::IF::Attr';
5     require Message::DOM::Node;
6    
7     sub ____new ($$$$$$) {
8     my $self = shift->SUPER::____new (shift);
9     ($$self->{owner_element},
10     $$self->{namespace_uri},
11     $$self->{prefix},
12     $$self->{local_name}) = @_;
13     Scalar::Util::weaken ($$self->{owner_element});
14 wakaba 1.4 $$self->{child_nodes} = [];
15 wakaba 1.6 $$self->{specified} = 1;
16 wakaba 1.1 return $self;
17     } # ____new
18    
19     sub AUTOLOAD {
20     my $method_name = our $AUTOLOAD;
21     $method_name =~ s/.*:://;
22     return if $method_name eq 'DESTROY';
23    
24     if ({
25     ## Read-only attributes (trivial accessors)
26 wakaba 1.3 namespace_uri => 1,
27 wakaba 1.1 owner_element => 1,
28     }->{$method_name}) {
29     no strict 'refs';
30     eval qq{
31     sub $method_name (\$) {
32     return \${\$_[0]}->{$method_name};
33     }
34     };
35     goto &{ $AUTOLOAD };
36     } else {
37     require Carp;
38     Carp::croak (qq<Can't locate method "$AUTOLOAD">);
39     }
40     } # AUTOLOAD
41     sub owner_element ($);
42    
43 wakaba 1.6 ## |Node| attributes
44    
45     sub base_uri ($) {
46     my $self = $_[0];
47     local $Error::Depth = $Error::Depth + 1;
48     my $oe = $self->owner_element;
49     if ($oe) {
50     my $ln = $self->local_name;
51     my $nsuri = $self->namespace_uri;
52     if (($ln eq 'base' and
53     defined $nsuri and $nsuri eq 'http://www.w3.org/XML/1998/namespace') or
54     ($ln eq 'xml:base' and not defined $nsuri)) {
55     my $oep = $oe->parent_node;
56     if ($oep) {
57     return $oep->base_uri;
58     } else {
59     return $self->owner_document->base_uri;
60     }
61     } else {
62     return $oe->base_uri;
63     }
64     } else {
65     return $self->owner_document->base_uri;
66     }
67     } # base_uri
68 wakaba 1.1
69 wakaba 1.3 sub local_name ($) {
70     ## TODO: HTML5
71     return ${+shift}->{local_name};
72     } # local_name
73    
74     sub manakai_local_name ($) {
75 wakaba 1.6 return ${$_[0]}->{local_name};
76 wakaba 1.3 } # manakai_local_name
77    
78     sub namespace_uri ($);
79 wakaba 1.2
80     *node_name = \&name;
81    
82     sub node_type () { 2 } # ATTRIBUTE_NODE
83    
84 wakaba 1.9 *node_value = \&Message::DOM::Node::text_content;
85 wakaba 1.1
86 wakaba 1.3 sub prefix ($;$) {
87 wakaba 1.5 ## NOTE: No check for new value as Firefox doesn't do.
88     ## See <http://suika.fam.cx/gate/2005/sw/prefix>.
89    
90     ## NOTE: Same as trivial setter except "" -> undef
91    
92     ## NOTE: Same as |Element|'s |prefix|.
93    
94     if (@_ > 1) {
95 wakaba 1.6 if (${${$_[0]}->{owner_document}}->{strict_error_checking} and
96     ${$_[0]}->{manakai_read_only}) {
97 wakaba 1.5 report Message::DOM::DOMException
98     -object => $_[0],
99     -type => 'NO_MODIFICATION_ALLOWED_ERR',
100     -subtype => 'READ_ONLY_NODE_ERR';
101     }
102     if (defined $_[1] and $_[1] ne '') {
103     ${$_[0]}->{prefix} = ''.$_[1];
104     } else {
105     delete ${$_[0]}->{prefix};
106     }
107     }
108     return ${$_[0]}->{prefix};
109 wakaba 1.3 } # prefix
110    
111 wakaba 1.8 ## |Node| methods
112    
113     sub append_child ($$) {
114     my $self = $_[0];
115    
116     ## NOTE: Depends on $self->node_type:
117     my $self_od = $$self->{owner_document};
118    
119     ## -- Node Type check
120     my @new_child;
121     my $new_child_parent;
122     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
123     push @new_child, @{$_[1]->child_nodes};
124     $new_child_parent = $_[1];
125     } else {
126     @new_child = ($_[1]);
127     $new_child_parent = $_[1]->parent_node;
128     }
129    
130     ## NOTE: Depends on $self->node_type:
131     if ($$self_od->{strict_error_checking}) {
132     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
133     if ($self_od ne $child_od and $child_od->node_type != 10) {
134     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
135     -object => $self,
136     -type => 'WRONG_DOCUMENT_ERR',
137     -subtype => 'EXTERNAL_OBJECT_ERR';
138     }
139    
140     if ($$self->{manakai_read_only} or
141     (@new_child and defined $new_child_parent and
142     $$new_child_parent->{manakai_read_only})) {
143     report Message::DOM::DOMException
144     -object => $self,
145     -type => 'NO_MODIFICATION_ALLOWED_ERR',
146     -subtype => 'READ_ONLY_NODE_ERR';
147     }
148    
149     ## NOTE: |Document| has children order check here.
150    
151     for my $cn (@new_child) {
152     unless ({
153     3, 1, 5, 1, # TEXT_NODE, ENTITY_REFERENCE_NODE
154     }->{$cn->node_type}) {
155     report Message::DOM::DOMException
156     -object => $self,
157     -type => 'HIERARCHY_REQUEST_ERR',
158     -subtype => 'CHILD_NODE_TYPE_ERR';
159     }
160     }
161    
162     ## NOTE: Ancestor check here in |Node|.
163     }
164    
165     ## NOTE: "Insert at" code only in insert_before and replace_child
166    
167     ## -- Removes from parent
168     if ($new_child_parent) {
169     if (@new_child == 1) {
170     my $v = $$new_child_parent->{child_nodes};
171     RP: for my $i (0..$#$v) {
172     if ($v->[$i] eq $new_child[0]) {
173     splice @$v, $i, 1, ();
174     last RP;
175     }
176     } # RP
177     } else {
178     @{$$new_child_parent->{child_nodes}} = ();
179     }
180     }
181    
182     ## -- Rewrite the |parentNode| properties
183     for my $nc (@new_child) {
184     $$nc->{parent_node} = $self;
185     Scalar::Util::weaken ($$nc->{parent_node});
186     }
187    
188     ## NOTE: Depends on method:
189     push @{$$self->{child_nodes}}, @new_child;
190    
191     ## NOTE: Setting |owner_document| in |Document|.
192    
193     return $_[1];
194     } # apepnd_child
195    
196     sub insert_before ($$) {
197     my $self = $_[0];
198    
199     ## NOTE: Depends on $self->node_type:
200     my $self_od = $$self->{owner_document};
201    
202     ## -- Node Type check
203     my @new_child;
204     my $new_child_parent;
205     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
206     push @new_child, @{$_[1]->child_nodes};
207     $new_child_parent = $_[1];
208     } else {
209     @new_child = ($_[1]);
210     $new_child_parent = $_[1]->parent_node;
211     }
212    
213     ## NOTE: Depends on $self->node_type:
214     if ($$self_od->{strict_error_checking}) {
215     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
216     if ($self_od ne $child_od and $child_od->node_type != 10) {
217     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
218     -object => $self,
219     -type => 'WRONG_DOCUMENT_ERR',
220     -subtype => 'EXTERNAL_OBJECT_ERR';
221     }
222    
223     if ($$self->{manakai_read_only} or
224     (@new_child and defined $new_child_parent and
225     $$new_child_parent->{manakai_read_only})) {
226     report Message::DOM::DOMException
227     -object => $self,
228     -type => 'NO_MODIFICATION_ALLOWED_ERR',
229     -subtype => 'READ_ONLY_NODE_ERR';
230     }
231    
232     ## NOTE: |Document| has children order check here.
233    
234     for my $cn (@new_child) {
235     unless ({
236     3, 1, 5, 1, # TEXT_NODE, ENTITY_REFERENCE_NODE
237     }->{$cn->node_type}) {
238     report Message::DOM::DOMException
239     -object => $self,
240     -type => 'HIERARCHY_REQUEST_ERR',
241     -subtype => 'CHILD_NODE_TYPE_ERR';
242     }
243     }
244    
245     ## NOTE: Ancestor check here in |Node|.
246     }
247    
248     ## -- Insert at... ## NOTE: Only in insert_before and replace_child
249     my $index = -1; # last
250     if (defined $_[2]) {
251     ## error if $_[1] eq $_[2];
252    
253     my $cns = $self->child_nodes;
254     my $cnsl = @$cns;
255     C: {
256     $index = 0;
257     for my $i (0..($cnsl-1)) {
258     my $cn = $cns->[$i];
259     if ($cn eq $_[2]) {
260     $index += $i;
261     last C;
262     } elsif ($cn eq $_[1]) {
263     $index = -1; # offset
264     }
265     }
266    
267     report Message::DOM::DOMException
268     -object => $self,
269     -type => 'NOT_FOUND_ERR',
270     -subtype => 'NOT_CHILD_ERR';
271     } # C
272     }
273     ## NOTE: "else" only in replace_child
274    
275     ## -- Removes from parent
276     if ($new_child_parent) {
277     if (@new_child == 1) {
278     my $v = $$new_child_parent->{child_nodes};
279     RP: for my $i (0..$#$v) {
280     if ($v->[$i] eq $new_child[0]) {
281     splice @$v, $i, 1, ();
282     last RP;
283     }
284     } # RP
285     } else {
286     @{$$new_child_parent->{child_nodes}} = ();
287     }
288     }
289    
290     ## -- Rewrite the |parentNode| properties
291     for my $nc (@new_child) {
292     $$nc->{parent_node} = $self;
293     Scalar::Util::weaken ($$nc->{parent_node});
294     }
295    
296     ## NOTE: Depends on method:
297     if ($index == -1) {
298     push @{$$self->{child_nodes}}, @new_child;
299     } else {
300     splice @{$$self->{child_nodes}}, $index, 0, @new_child;
301     }
302    
303     ## NOTE: Setting |owner_document| in |Document|.
304    
305     return $_[1];
306     } # insert_before
307    
308     sub replace_child ($$) {
309     my $self = $_[0];
310    
311     ## NOTE: Depends on $self->node_type:
312     my $self_od = $$self->{owner_document};
313    
314     ## -- Node Type check
315     my @new_child;
316     my $new_child_parent;
317     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
318     push @new_child, @{$_[1]->child_nodes};
319     $new_child_parent = $_[1];
320     } else {
321     @new_child = ($_[1]);
322     $new_child_parent = $_[1]->parent_node;
323     }
324    
325     ## NOTE: Depends on $self->node_type:
326     if ($$self_od->{strict_error_checking}) {
327     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
328     if ($self_od ne $child_od and $child_od->node_type != 10) {
329     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
330     -object => $self,
331     -type => 'WRONG_DOCUMENT_ERR',
332     -subtype => 'EXTERNAL_OBJECT_ERR';
333     }
334    
335     if ($$self->{manakai_read_only} or
336     (@new_child and defined $new_child_parent and
337     $$new_child_parent->{manakai_read_only})) {
338     report Message::DOM::DOMException
339     -object => $self,
340     -type => 'NO_MODIFICATION_ALLOWED_ERR',
341     -subtype => 'READ_ONLY_NODE_ERR';
342     }
343    
344     ## NOTE: |Document| has children order check here.
345    
346     for my $cn (@new_child) {
347     unless ({
348     3, 1, 5, 1, # TEXT_NODE, ENTITY_REFERENCE_NODE
349     }->{$cn->node_type}) {
350     report Message::DOM::DOMException
351     -object => $self,
352     -type => 'HIERARCHY_REQUEST_ERR',
353     -subtype => 'CHILD_NODE_TYPE_ERR';
354     }
355     }
356    
357     ## NOTE: Ancestor check here in |Node|.
358     }
359    
360     ## -- Insert at... ## NOTE: Only in insertBefore and replaceChild
361     my $index = -1; # last
362     if (defined $_[2]) {
363     ## error if $_[1] eq $_[2];
364    
365     my $cns = $self->child_nodes;
366     my $cnsl = @$cns;
367     C: {
368     $index = 0;
369     for my $i (0..($cnsl-1)) {
370     my $cn = $cns->[$i];
371     if ($cn eq $_[2]) {
372     $index += $i;
373     last C;
374     } elsif ($cn eq $_[1]) {
375     $index = -1; # offset
376     }
377     }
378    
379     report Message::DOM::DOMException
380     -object => $self,
381     -type => 'NOT_FOUND_ERR',
382     -subtype => 'NOT_CHILD_ERR';
383     } # C
384     } else {
385     ## NOTE: Only in replaceChild
386     report Message::DOM::DOMException
387     -object => $self,
388     -type => 'NOT_FOUND_ERR',
389     -subtype => 'NOT_CHILD_ERR';
390     }
391    
392     ## -- Removes from parent
393     if ($new_child_parent) {
394     if (@new_child == 1) {
395     my $v = $$new_child_parent->{child_nodes};
396     RP: for my $i (0..$#$v) {
397     if ($v->[$i] eq $new_child[0]) {
398     splice @$v, $i, 1, ();
399     last RP;
400     }
401     } # RP
402     } else {
403     @{$$new_child_parent->{child_nodes}} = ();
404     }
405     }
406    
407     ## -- Rewrite the |parentNode| properties
408     for my $nc (@new_child) {
409     $$nc->{parent_node} = $self;
410     Scalar::Util::weaken ($$nc->{parent_node});
411     }
412    
413     ## NOTE: Depends on method:
414     splice @{$$self->{child_nodes}}, $index, 1, @new_child;
415     delete ${$_[2]}->{parent_node};
416    
417     ## NOTE: Setting |owner_document| in |Document|.
418    
419     return $_[2];
420     } # replace_child
421    
422 wakaba 1.6 ## |Attr| attributes
423    
424     sub manakai_attribute_type ($;$) {
425     my $self = $_[0];
426     if (@_ > 1) {
427     if (${$$self->{owner_document}}->{strict_error_checking}) {
428     if ($$self->{manakai_read_only}) {
429     report Message::DOM::DOMException
430     -object => $self,
431     -type => 'NO_MODIFICATION_ALLOWED_ERR',
432     -subtype => 'READ_ONLY_NODE_ERR';
433     }
434     }
435     if ($_[1]) {
436     $$self->{manakai_attribute_type} = 0+$_[1];
437     } else {
438     delete $$self->{manakai_attribute_type};
439     }
440     }
441    
442     return $$self->{manakai_attribute_type} || 0;
443     } # manakai_attribute_type
444 wakaba 1.1
445     ## TODO: HTML5 case stuff?
446     sub name ($) {
447     my $self = shift;
448     if (defined $$self->{prefix}) {
449     return $$self->{prefix} . ':' . $$self->{local_name};
450     } else {
451     return $$self->{local_name};
452     }
453     } # name
454    
455 wakaba 1.6 sub specified ($;$) {
456 wakaba 1.1 if (@_ > 1) {
457 wakaba 1.6 ## NOTE: A manakai extension.
458     if (${${$_[0]}->{owner_document}}->{strict_error_checking} and
459     ${$_[0]}->{manakai_read_only}) {
460     report Message::DOM::DOMException
461     -object => $_[0],
462     -type => 'NO_MODIFICATION_ALLOWED_ERR',
463     -subtype => 'READ_ONLY_NODE_ERR';
464     }
465     if ($_[1] or not defined ${$_[0]}->{owner_element}) {
466     ${$_[0]}->{specified} = 1;
467     } else {
468     delete ${$_[0]}->{specified};
469     }
470 wakaba 1.1 }
471 wakaba 1.6 return ${$_[0]}->{specified};
472     } # specified
473    
474 wakaba 1.9 *value = \&node_value;
475 wakaba 1.1
476     package Message::IF::Attr;
477    
478     package Message::DOM::Document;
479    
480     sub create_attribute ($$) {
481 wakaba 1.7 if (${$_[0]}->{strict_error_checking}) {
482     my $xv = $_[0]->xml_version;
483     ## TODO: HTML Document ??
484     if (defined $xv) {
485     if ($xv eq '1.0' and
486     $_[1] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
487     #
488     } elsif ($xv eq '1.1' and
489     $_[1] =~ /\A\p{InXMLNameStartChar11}\p{InXMLNameChar11}*\z/) {
490     #
491     } else {
492     report Message::DOM::DOMException
493     -object => $_[0],
494     -type => 'INVALID_CHARACTER_ERR',
495     -subtype => 'MALFORMED_NAME_ERR';
496     }
497     }
498     }
499 wakaba 1.1 ## TODO: HTML5
500     return Message::DOM::Attr->____new ($_[0], undef, undef, undef, $_[1]);
501     } # create_attribute
502    
503     sub create_attribute_ns ($$$) {
504     my ($prefix, $lname);
505     if (ref $_[2] eq 'ARRAY') {
506     ($prefix, $lname) = @{$_[2]};
507     } else {
508     ($prefix, $lname) = split /:/, $_[2], 2;
509     ($prefix, $lname) = (undef, $prefix) unless defined $lname;
510     }
511 wakaba 1.7
512     if (${$_[0]}->{strict_error_checking}) {
513     my $xv = $_[0]->xml_version;
514     ## TODO: HTML Document ?? (NOT_SUPPORTED_ERR is different from what Web browsers do)
515     if (defined $xv) {
516     if ($xv eq '1.0') {
517     if (ref $_[2] eq 'ARRAY' or
518     $_[2] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
519     if (defined $prefix) {
520     if ($prefix =~ /\A\p{InXML_NCNameStartChar10}\p{InXMLNCNameChar10}*\z/) {
521     #
522     } else {
523     report Message::DOM::DOMException
524     -object => $_[0],
525     -type => 'NAMESPACE_ERR',
526     -subtype => 'MALFORMED_QNAME_ERR';
527     }
528     }
529     if ($lname =~ /\A\p{InXML_NCNameStartChar10}\p{InXMLNCNameChar10}*\z/) {
530     #
531     } else {
532     report Message::DOM::DOMException
533     -object => $_[0],
534     -type => 'NAMESPACE_ERR',
535     -subtype => 'MALFORMED_QNAME_ERR';
536     }
537     } else {
538     report Message::DOM::DOMException
539     -object => $_[0],
540     -type => 'INVALID_CHARACTER_ERR',
541     -subtype => 'MALFORMED_NAME_ERR';
542     }
543     } elsif ($xv eq '1.1') {
544     if (ref $_[2] eq 'ARRAY' or
545     $_[2] =~ /\A\p{InXML_NameStartChar10}\p{InXMLNameChar10}*\z/) {
546     if (defined $prefix) {
547     if ($prefix =~ /\A\p{InXMLNCNameStartChar11}\p{InXMLNCNameChar11}*\z/) {
548     #
549     } else {
550     report Message::DOM::DOMException
551     -object => $_[0],
552     -type => 'NAMESPACE_ERR',
553     -subtype => 'MALFORMED_QNAME_ERR';
554     }
555     }
556     if ($lname =~ /\A\p{InXMLNCNameStartChar11}\p{InXMLNCNameChar11}*\z/) {
557     #
558     } else {
559     report Message::DOM::DOMException
560     -object => $_[0],
561     -type => 'NAMESPACE_ERR',
562     -subtype => 'MALFORMED_QNAME_ERR';
563     }
564     } else {
565     report Message::DOM::DOMException
566     -object => $_[0],
567     -type => 'INVALID_CHARACTER_ERR',
568     -subtype => 'MALFORMED_NAME_ERR';
569     }
570     } else {
571     die "create_attribute_ns: XML version |$xv| is not supported";
572     }
573     }
574    
575     if (defined $prefix) {
576     if (not defined $_[1]) {
577     report Message::DOM::DOMException
578     -object => $_[0],
579     -type => 'NAMESPACE_ERR',
580     -subtype => 'PREFIXED_NULLNS_ERR';
581     } elsif ($prefix eq 'xml' and
582     $_[1] ne q<http://www.w3.org/XML/1998/namespace>) {
583     report Message::DOM::DOMException
584     -object => $_[0],
585     -type => 'NAMESPACE_ERR',
586     -subtype => 'XMLPREFIX_NONXMLNS_ERR';
587     } elsif ($prefix eq 'xmlns' and
588     $_[1] ne q<http://www.w3.org/2000/xmlns/>) {
589     report Message::DOM::DOMException
590     -object => $_[0],
591     -type => 'NAMESPACE_ERR',
592     -subtype => 'XMLNSPREFIX_NONXMLNSNS_ERR';
593     } elsif ($_[1] eq q<http://www.w3.org/2000/xmlns/> and
594     $prefix ne 'xmlns') {
595     report Message::DOM::DOMException
596     -object => $_[0],
597     -type => 'NAMESPACE_ERR',
598     -subtype => 'NONXMLNSPREFIX_XMLNSNS_ERR';
599     }
600     } else { # no prefix
601     if ($lname eq 'xmlns' and
602     (not defined $_[1] or $_[1] ne q<http://www.w3.org/2000/xmlns/>)) {
603     report Message::DOM::DOMException
604     -object => $_[0],
605     -type => 'NAMESPACE_ERR',
606     -subtype => 'XMLNS_NONXMLNSNS_ERR';
607     } elsif (not defined $_[1]) {
608     #
609     } elsif ($_[1] eq q<http://www.w3.org/2000/xmlns/> and
610     $lname ne 'xmlns') {
611     report Message::DOM::DOMException
612     -object => $_[0],
613     -type => 'NAMESPACE_ERR',
614     -subtype => 'NONXMLNSPREFIX_XMLNSNS_ERR';
615     }
616     }
617     }
618    
619     ## TODO: Older version of manakai set |attribute_type|
620     ## attribute for |xml:id| attribute. Should we support this?
621    
622 wakaba 1.1 return Message::DOM::Attr->____new ($_[0], undef, $_[1], $prefix, $lname);
623 wakaba 1.7 } # create_attribute_ns
624    
625     =head1 LICENSE
626    
627     Copyright 2007 Wakaba <w@suika.fam.cx>
628    
629     This program is free software; you can redistribute it and/or
630     modify it under the same terms as Perl itself.
631    
632     =cut
633 wakaba 1.1
634     1;
635 wakaba 1.9 ## $Date: 2007/07/08 05:42:36 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24