"Fossies" - the Fresh Open Source Software Archive

Member "HTTP-DAV-0.49/lib/HTTP/DAV/Response.pm" (28 Nov 2018, 10090 Bytes) of package /linux/www/HTTP-DAV-0.49.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Response.pm" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.48_vs_0.49.

    1 package HTTP::DAV::Response;
    2 
    3 use strict;
    4 use vars qw(@ISA $VERSION);
    5 
    6 $VERSION = '0.14';
    7 
    8 require HTTP::Response;
    9 @ISA = qw(HTTP::Response);
   10 
   11 my %dav_status_codes = (
   12    102 => "Processing. Server has accepted the request, but has not yet completed it",
   13    204 => "No Content",
   14    207 => "Multistatus",
   15    422 => "Unprocessable Entity. Bad client XML sent?",
   16    423 => "Locked. The source or destination resource is locked",
   17    424 => "Failed Dependency",
   18    507 => "Insufficient Storage. The server is unable to store the request",
   19 );
   20 
   21 # PROTECTED METHODS
   22 
   23 sub clone_http_resp {
   24    my ($class,$http_resp) = @_;
   25    my %clone = %{$http_resp};
   26    my $self = \%clone;
   27    bless $self, (ref($class) || $class); 
   28 }
   29 
   30 # This routine resets the base
   31 # message in the 
   32 # object based on the 
   33 # code and the status_codes above.
   34 # set_message('207');
   35 sub set_message {
   36    my ($self,$code) = @_;
   37 
   38    # Set the status code
   39    if ( defined $dav_status_codes{$code} ) {
   40       $self->message( $dav_status_codes{$code} );
   41    }
   42 }
   43 
   44 sub set_responsedescription {
   45    $_[0]->{'_dav_responsedescription'} = $_[1] if $_[1];
   46 }
   47 
   48 sub get_responsedescription { $_[0]->{'_dav_responsedescription'}; }
   49 
   50 sub add_status_line {
   51    my($self,$message,$responsedescription,$handle,$url) = @_;
   52    
   53    # Parse "status-line". See section 6.1 of RFC 2068
   54    # Status-Line= HTTP-Version SP Status-Code SP Reason-Phrase CRLF
   55    if (defined $message && $message =~ /^(.*?)\s(.*?)\s(.*?)$/ ) {
   56       my ($http_version,$status_code,$reason_phrase) = ($1,$2,$3);
   57 
   58       push ( @{$self->{_dav_multistatus}},
   59                {
   60                   'handle' => $handle,
   61                   'url' => $url,
   62                   'HTTP Version' => $http_version,
   63                   'code' => $status_code,
   64                   'message' => $reason_phrase,
   65                   'description' => $responsedescription,
   66                }
   67            );
   68       return 1;
   69 
   70    } else {
   71       return 0;
   72    }
   73 }
   74 
   75 # PUBLIC METHODS
   76 
   77 sub is_multistatus {
   78     return ($_[0]->code eq "207" )? 1:0; 
   79 }
   80 
   81 sub messages {
   82    my ($self) = @_;
   83 
   84    my @messages = ();
   85    if ($self->is_multistatus() ) {
   86       foreach my $num ( 0 .. $self->response_count()) {
   87          push(@messages, $self->message_bynum($num));
   88       }
   89    } else {
   90       push(@messages,$self->message());
   91    }
   92 
   93    return wantarray ? @messages : join("\n",@messages);
   94 }
   95 
   96 sub codes {
   97    my ($self) = @_;
   98 
   99    my @codes = ();
  100    if ($self->is_multistatus() ) {
  101       foreach my $num ( 0 .. $self->response_count()) {
  102          push(@codes, $self->code_bynum($num));
  103       }
  104    } else {
  105       push(@codes,$self->code());
  106    }
  107 
  108    return \@codes;
  109 }
  110 
  111 sub response_count { 
  112    return -1 unless exists $_[0]->{_dav_multistatus};
  113    return -1 unless ref($_[0]->{_dav_multistatus}) =~ /ARRAY/;
  114    return  $#{$_[0]->{_dav_multistatus}}; 
  115 }
  116 
  117 sub message_bynum { $_[0]->{_dav_multistatus}[$_[1]]{'message'}; }
  118 sub    code_bynum { $_[0]->{_dav_multistatus}[$_[1]]{'code'}; }
  119 sub     url_bynum { $_[0]->{_dav_multistatus}[$_[1]]{'url'}; }
  120 sub description_bynum { $_[0]->{_dav_multistatus}[$_[1]]{'description'}; }
  121 
  122 sub response_bynum {
  123    my ($self,$number) = @_;
  124 
  125    if (defined $number && $number>=0 ) {
  126       return (
  127          $self->code_bynum($number),
  128          $self->message_bynum($number),
  129          $self->url_bynum($number),
  130          $self->description_bynum($number),
  131       );
  132    }
  133 }
  134 
  135 sub is_success {
  136    my ($self) = @_;
  137 
  138    if ($self->is_multistatus() ) {
  139       foreach my $code ( @{ $self->codes() } ) {
  140          return 0 if ( HTTP::Status::is_error($code) );
  141       }
  142    } else {
  143       return ($self->SUPER::is_success() || 0);
  144    }
  145 
  146    return 1;
  147 }
  148 
  149 sub as_string {
  150    my ($self) = @_;
  151    my ($ms, $returnstr) = "";
  152 
  153 #   use Data::Dumper;
  154 #   print Data::Dumper->Dump( [\$self] , [ '$self' ] );
  155    foreach my $num ( 0 .. $self->response_count() ) {
  156       my %h = %{$self->{_dav_multistatus}[$num]};
  157       $ms .= "Error number $num ($h{handle}):\n";
  158       $ms .= "   Href:       $h{url}\n"                 if defined $h{url};
  159       $ms .= "   Mesg(code): $h{message} ($h{code})\n"  if defined $h{code};
  160       $ms .= "   Desc:       $h{'description'}\n"       if defined $h{'description'};
  161       $ms .= "\n";
  162    }
  163 
  164    my $rd = $self->get_responsedescription() || "";
  165 
  166    $returnstr .= "Multistatus lines:\n$ms\n" if $ms;
  167    $returnstr .= "Overall responsedescription: \"$rd\"\n" if $rd;
  168    $returnstr .= $self->SUPER::as_string;
  169    $returnstr;
  170 }
  171 
  172 =head1 NAME
  173 
  174 HTTP::DAV::Response - represents a WebDAV HTTP Response (ala HTTP::Response)
  175 
  176 =head1 SYNOPSIS
  177 
  178 require HTTP::DAV::Response;
  179 
  180 =head1 DESCRIPTION
  181 
  182 The HTTP::DAV::Response class encapsulates HTTP style responses.  A response consists of a response line, some headers, and (potentially empty) content. 
  183 
  184 HTTP::DAV::Response is a subclass of C<HTTP::Response> and therefore inherits its methods.  (HTTP::Response in turn inherits it's methods from C<HTTP::Message>).
  185 
  186 Therefore, this class actually inherits a rich library of functions. You are more likely wanting to read the C<HTTP::Response> class as opposed to this class.
  187 
  188 Instances of this class are usually created by a C<HTTP::DAV::Resource> object after it has performed some request (such as get, lock, delete, etc). You use the object to analyse the success or otherwise of the request.
  189 
  190 HTTP::DAV::Response was created to handle two extra functions that normal HTTP Responses don't require:
  191 
  192  - WebDAV responses have 6 extra error codes: 102, 207, 422, 423, 424 and 507. Older versions of the LWP's C<HTTP::Status> class did not have these extra codes. These were added.
  193 
  194  - WebDAV responses can actually contain more than one response (and often DO contain more than one) in the form of a "Multistatus". These multistatus responses come in the form of an XML document. HTTP::DAV::Response can accurately parse these XML responses and emulate the normal of the C<HTTP::Response>.
  195 
  196 HTTP::DAV::Response transparently implements these extra features without the user having to be aware, so you really should be reading the C<HTTP::Response> documentation for most of the things you want to do (have I already said that?).
  197 
  198 There are only a handful of custom functions that HTTP::DAV::Response returns and those are to handle multistatus requests, C<messages()> and C<codes()>.
  199 
  200 The six extra status codes that DAV servers can be returned in an HTTP Response are:
  201   102 => "Processing. Server has accepted the request, but has not yet completed it",
  202   207 => "Multistatus",
  203   422 => "Unprocessable Entity. Bad client XML sent?",
  204   423 => "Locked. The source or destination resource is locked",
  205   424 => "Failed Dependency",
  206   507 => "Insufficient Storage. The server is unable to store the request",
  207 
  208 See C<HTTP::Status> for the rest.
  209 
  210 =head1 HANDLING A MULTISTATUS 
  211 
  212 So, many DAV requests may return a multistatus ("207 multistatus") instead of, say, "200 OK" or "403 Forbidden".
  213 
  214 The HTTP::DAV::Response object stores each "response" sent back in the multistatus. You access them by array number.
  215 
  216 The following code snippet shows what you will normally want to do:
  217 
  218 ...
  219 $response = $resource->lock();
  220 
  221 if ( $response->is_multistatus() ) {
  222 
  223    foreach $num ( 0 .. $response->response_count() ) {
  224       ($err_code,$mesg,$url,$desc) = 
  225          $response->response_bynum($num);
  226       print "$mesg ($err_code) for $url\n";
  227    }
  228 }
  229 
  230 Would produce something like this:
  231    Failed Dependency (424) for /test/directory
  232    Locked (423) for /test/directory/file3
  233 
  234 This says that we couldn't lock /test/directory 
  235 because file3 which exists inside is already locked by somebody else.
  236 
  237 =head1 METHODS
  238 
  239 =over 4 
  240 
  241 =item B<is_multistatus>
  242 
  243 This function takes no arguments and returns a 1 or a 0.
  244 
  245 For example: if ($response->is_multistatus() ) { }
  246 
  247 If the HTTP reply had "207 Multistatus" in the header then that indicates that there are multiple status messages in the XML content that was returned.
  248 
  249 In this event, you may be interested in knowing what the individual messages were. To do this you would then use C<messages>. 
  250 
  251 =item B<response_count>
  252 
  253 Takes no arguments and returns "the number of error responses -1" that we got.
  254 Why -1? Because usually you will want to use this like an array operator:
  255 
  256 foreach $num ( 0 .. $response->response_count() ) { 
  257    print $response->message_bynum();
  258 }
  259 
  260 =item B<response_bynum>
  261 
  262 Takes one argument, the "response number" that you're interested in. And returns an array of details:
  263 
  264    ($code,$message,$url,$description) = response_bynum(2);
  265 
  266 where 
  267    $code - is the HTTP error code (e.g. 403, 423, etc).
  268    $message - is the associated message for that error code.
  269    $url - is the url that this error applies to (recall that there can be multiple responses within one response and they all relate to one URL)
  270    $description - is server's attempt at an english description of what happened.
  271 
  272 =item B<code_bynum>
  273 
  274 Takes one argument, the "response number" that you're interested in, and returns it's code. E.g:
  275 
  276   $code = $response->code_bynum(1);
  277 
  278 See C<response_bynum()>
  279 
  280 =item B<message_bynum>
  281 
  282 Takes one argument, the "response number" that you're interested in, and returns it's message. E.g:
  283 
  284   $code = $response->message_bynum(1);
  285 
  286 See C<response_bynum()>
  287 
  288 =item B<url_bynum>
  289 
  290 Takes one argument, the "response number" that you're interested in, and returns it's url. E.g:
  291 
  292   $code = $response->message_bynum(1);
  293 
  294 See C<response_bynum()>
  295 
  296 =item B<description_bynum>
  297 
  298 Takes one argument, the "response number" that you're interested in, and returns it's description. E.g:
  299 
  300   $code = $response->message_description(1);
  301 
  302 See C<response_bynum()>
  303 
  304 =item B<messages>
  305 
  306 Takes no arguments and returns all of the messages returned in a multistatus response. If called in a scalar context then all of the messages will be returned joined together by newlines. If called in an array context the messages will be returned as an array.
  307 
  308 $messages = $response->messages();
  309 e.g. $messages eq "Forbidden\nLocked";
  310 
  311 @messages = $response->messages();
  312 e.g. @messages eq ["Forbidden", "Locked"];
  313 
  314 This routine is a variant on the standard C<HTTP::Response> C<message()>. 
  315 
  316 =back
  317 
  318 =cut
  319