Subject: | patch for creating/using local persistent check daemon |
assuming that the user has installed an rpm/dpkg/etc for the w3c
validator check script, this patch starts a HTTP::Server::Simple::CGI
and reads in the check script. The patch then provides
WebService::Validator::HTML::W3C::Embedded as a super class of
WebService::Validator::HTML::W3C, the super class just starts the local
http server and calls the WebService::Validator::HTML::W3C->new method
with the specified parameters.
Subject: | persistent.patch |
diff -Naur old/lib/WebService/Validator/HTML/W3C/Embedded.pm new/lib/WebService/Validator/HTML/W3C/Embedded.pm
--- old/lib/WebService/Validator/HTML/W3C/Embedded.pm 1970-01-01 10:00:00.000000000 +1000
+++ new/lib/WebService/Validator/HTML/W3C/Embedded.pm 2009-02-12 14:44:06.000000000 +1100
@@ -0,0 +1,113 @@
+package WebService::Validator::HTML::W3C::Embedded;
+
+use strict;
+use warnings;
+use WebService::Validator::HTML::W3C();
+use base qw(WebService::Validator::HTML::W3C);
+use Fcntl();
+use Symbol();
+
+=head1 NAME
+
+WebService::Validator::HTML::W3C::Embedded - Access the W3Cs online HTML validator in a local persistent daemon
+
+=head1 SYNOPSIS
+
+ use WebService::Validator::HTML::W3C;
+
+ my $v = WebService::Validator::HTML::W3C::Embedded->new(
+ validator_path => '/path/to/validator/check', # defaults to '/usr/share/w3c-markup-validator/cgi-bin/check'
+ validator_port => 8888, # defaults to 8080
+ );
+
+ if ( $v->validate_markup(<<_HTML_) ) {
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head><title></title></head><body></body></html>
+_HTML_
+ if ( $v->is_valid ) {
+ printf ("%s is valid\n", $v->uri);
+ } else {
+ printf ("%s is not valid\n", $v->uri);
+ foreach my $error ( @{$v->errors} ) {
+ printf("%s at line %d\n", $error->msg,
+ $error->line);
+ }
+ }
+ } else {
+ printf ("Failed to validate the supplied markup: %s\n", $v->validator_error);
+ }
+
+=head1 DESCRIPTION
+
+WebService::Validator::HTML::W3C::Embedded provides access a local version of
+the W3C's Markup validator, via WebService::Validator::HTML::W3C. It loads up
+a small HTTP::Server::Simple::CGI daemon and loads the check cgi script into
+a mod_perl type persistent environment for speedy checking of lots of documents
+
+=cut
+
+sub new {
+ my ($class, %params) = @_;
+ my $self = {};
+ bless $self, $class;
+ return $self->validator_error("The path to the validator cgi script has not been supplied")
+ unless ($params{validator_path});
+ return $self->validator_error("The validator uri cannot be used here")
+ if ($params{validator_uri});
+ my ($validator_port) = $params{validator_port} || '8080';
+ my ($validator_path) = $params{validator_path} || '/usr/share/w3c-markup-validator/cgi-bin/check';
+ delete $params{validator_path};
+ my ($handle) = Symbol::gensym();
+ return $self->validator_error("Could not open '$validator_path':$^E")
+ unless (sysopen($handle, $validator_path, Fcntl::O_RDONLY()));
+ my ($validator_source);
+ my ($result, $buffer);
+ while($result = read($handle, $buffer, 4096)) {
+ $validator_source .= $buffer;
+ }
+ return $self->validator_error("Could not read from '$validator_path':$^E")
+ unless (defined $result);
+ return $self->validator_error("Could not close '$validator_path':$^E")
+ unless (close($handle));
+ $validator_source =~ s/exit/return/g;
+ # cannot get prepCGI to work in this environment. just comment it out for now
+ return $self->validator_error("Could not patch away the prepCGI function in '$validator_path'")
+ unless($validator_source =~ s/^(\$q = \&prepCGI\(\$File, \$q\);)$/#$1\n/m);
+ eval <<_SERVER_;
+package WebService::Validator::HTML::W3C::Embedded::Server;
+
+use strict;
+use warnings;
+use HTTP::Server::Simple::CGI();
+use base qw(HTTP::Server::Simple::CGI);
+
+sub print_banner {
+}
+
+sub handle_request {
+print "HTTP/1.1 200 OK\r\n";
+$validator_source
+}
+_SERVER_
+ if ($@) {
+ print STDERR $@;
+ }
+ my ($server) = WebService::Validator::HTML::W3C::Embedded::Server->new();
+ $server->port($validator_port);
+ my ($pid) = $server->background();
+ $self = WebService::Validator::HTML::W3C->new( 'validator_uri' => 'http://localhost:' . $server->port(), %params );
+ bless $self, $class;
+ $self->{_internal_http_server_pid} = $pid;
+ return $self;
+}
+
+sub DESTROY {
+ my ($self) = @_;
+ if ((exists $self->{_internal_http_server_pid}) && ($self->{_internal_http_server_pid})) {
+ kill("TERM", $self->{_internal_http_server_pid});
+ }
+}
+
+1;
diff -Naur old/t/15embedded.t new/t/15embedded.t
--- old/t/15embedded.t 1970-01-01 10:00:00.000000000 +1000
+++ new/t/15embedded.t 2009-02-11 16:21:12.000000000 +1100
@@ -0,0 +1,24 @@
+
+use Test::More;
+
+use WebService::Validator::HTML::W3C::Embedded;
+
+plan tests => 7;
+
+SKIP: {
+ my ($check_cgi_path) = '/usr/share/w3c-markup-validator/cgi-bin/check';
+ unless (-f $check_cgi_path) {
+ skip "no local validator detected", 7;
+ }
+ my $v = WebService::Validator::HTML::W3C::Embedded->new('validator_path' => $check_cgi_path);
+ ok($v, 'Object created');
+
+ my $r = $v->validate_markup('<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><title></title></head><body></body></html>');
+ ok($r, 'embedded validator created');
+ ok($v->is_valid, 'page is valid');
+ is($v->num_errors, 0, 'no errors in valid page');
+ $r = $v->validate_markup('<html><head><title></title></head><body></body></html>');
+ ok($r, 'embedded validator created');
+ ok(not($v->is_valid), 'page is invalid');
+ is($v->num_errors, 1, 'errors in invalid page');
+}