=head1 NAME SuikaWiki::Output::HTTP --- SuikaWiki: HTTP or HTTP CGI output support =head1 DESCRIPTION This module provides HTTP or HTTP CGI outputing support. This module is part of SuikaWiki. =cut package SuikaWiki::Output::HTTP; use strict; our $VERSION = do{my @r=(q$Revision: 1.1 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; my %Status = ( 200 => q(OK), 301 => q(Permanently Redirect), 302 => q(Found), 303 => q(See Other), 307 => q(Temporary Redirect), 401 => q(Authorization Required), 403 => q(Forbidden), 404 => q(Not Found), 500 => q(Internal Server Error), 503 => q(Service Temporary Unavailable), ); =head1 METHODS =over 4 =item $http = SuikaWiki::Output::HTTP->new Constructs new instance of HTTP output implementation =cut sub new ($;%) { my $self = bless {header_field => [], negotiate_header_field => {Negotiate => 1}, entity => {language => [], media_type => 'application/octet-stream'}, }, shift; my %opt = @_; $self->{wiki} = $opt{wiki}; $self->{view} = $opt{view}; $self->{viewobj} = $opt{viewobj}; $self; } sub add_header_field ($$$;%) { my ($self, $name => $body, %opt) = @_; push @{$self->{header_field}}, {name => $name, body => $body}; } sub add_negotiate_header_field ($$) { my ($self, $name) = @_; $self->{negotiate_header_field}->{$name} = 1; } sub set_expires ($%) { my ($self, %opt) = @_; if ($opt{time}) { ## TODO: use rfc1123-time push @{$self->{header_field}}, {name => 'Expires', body => scalar gmtime $opt{time}}; } elsif (defined $opt{delta}) { $self->{expires_delta} = $opt{delta} + 0; } } sub set_redirect_uri ($%) { } sub set_last_modified ($%) { my ($self, %opt) = @_; $self->{lastmodified_time} = $opt{time}; } sub append_to_body ($$) { my ($self, $s) = @_; $self->{entity}->{body} .= $s; } sub output ($;%) { my ($self, %opt) = @_; my $nl; binmode STDOUT; $| = 1; my $status = qq(@{[$self->{status_code}||200]} @{[$self->{status_phrase}||$Status{$self->{status_code}||200}]}); if ($opt{output} eq 'http-cgi') { $nl = "\n"; print "Status: $status$nl"; } else { $nl = "\x0D\x0A"; print "$status HTTP/1.1$nl"; } for (@{$self->{header_field}}) { print "$_->{name}: $_->{body}$nl"; } my $time = time; print "Date: @{[scalar gmtime $time]}$nl"; if (defined $self->{expires_delta}) { print "Expires: @{[scalar gmtime ($time + $self->{expires_delta})]}$nl"; } if (defined $self->{lastmodified_time}) { print "Last-Modified: @{[scalar gmtime $self->{lastmodified_time}]}$nl"; } else { print "Last-Modified: @{[scalar gmtime $time]}$nl"; } print "Vary: ".join (', ', keys %{$self->{negotiate_header_field}})."$nl"; my $body = '' . $self->{entity}->{body}; ## TODO: $body = &main::code_convert (\$body, $self->{entity}->{charset}); if (($self->{entity}->{media_type} eq 'application/rdf+xml') && (index ($self->{view}->{wiki}->{var}->{client}->{user_agent_name}, 'Gecko') > -1)) { print "Content-Type: application/xml"; } else { print "Content-Type: $self->{entity}->{media_type}"; } if ($self->{entity}->{charset}) { if ($self->{view}->{wiki}->{var}->{client}->{user_agent_name} =~ m#Mozilla/[12]\.#) { print qq(; charset="@{[{qw/euc-jp x-euc-jp shift_jis x-sjis/} ->{$self->{entity}->{charset}} || $self->{entity}->{charset}]}"); } elsif ($self->{view}->{wiki}->{var}->{client}->{user_agent_name} =~ m#Mozilla/0\.|Infomosaic#) { } else { print qq(; charset="$self->{entity}->{charset}"); } } print $nl; for (join ', ', @{$self->{entity}->{language}||[]}) { print "Content-Language: $_$nl" if $_; } print "Content-Length: @{[length $body]}$nl"; print $nl; print $body; } =item $self->{entity}->{charset} =item $self->{entity}->{language} = [...] =item $self->{entity}->{media_type} =back =head1 TODO Use manakai. =head1 LICENSE Copyright 2003 Wakaba This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # $Date: 2003/10/05 11:55:29 $