|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Plack::HTTPParser::PP;  | 
| 
2
 | 
40
 | 
 
 | 
 
 | 
  
40
  
 | 
 
 | 
54723
 | 
 use strict;  | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1782
 | 
    | 
| 
3
 | 
40
 | 
 
 | 
 
 | 
  
40
  
 | 
 
 | 
198
 | 
 use warnings;  | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
116
 | 
    | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1661
 | 
    | 
| 
4
 | 
40
 | 
 
 | 
 
 | 
  
40
  
 | 
 
 | 
1298
 | 
 use URI::Escape;  | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5186
 | 
    | 
| 
 
 | 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34991
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse_http_request {  | 
| 
7
 | 
710
 | 
 
 | 
 
 | 
  
710
  
 | 
  
0
  
 | 
3785
 | 
     my($chunk, $env) = @_;  | 
| 
8
 | 
710
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
1746
 | 
     $env ||= {};  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # pre-header blank lines are allowed (RFC 2616 4.1)  | 
| 
11
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10421
 | 
     $chunk =~ s/^(\x0d?\x0a)+//;  | 
| 
12
 | 
710
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2556
 | 
     return -2 unless length $chunk;  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # double line break indicates end of header; parse it  | 
| 
15
 | 
710
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8566
 | 
     if ($chunk =~ /^(.*?\x0d?\x0a\x0d?\x0a)/s) {  | 
| 
16
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7273
 | 
         return _parse_header($chunk, length $1, $env);  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
18
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return -2;  # still waiting for unknown amount of header lines  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_header {  | 
| 
22
 | 
710
 | 
 
 | 
 
 | 
  
710
  
 | 
 
 | 
3330
 | 
     my($chunk, $eoh, $env) = @_;  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3329
 | 
     my $header = substr($chunk, 0, $eoh,'');  | 
| 
25
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1439
 | 
     $chunk =~ s/^\x0d?\x0a\x0d?\x0a//;  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # parse into lines  | 
| 
28
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10368
 | 
     my @header  = split /\x0d?\x0a/,$header;  | 
| 
29
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2853
 | 
     my $request = shift @header;  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # join folded lines  | 
| 
32
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1000
 | 
     my @out;  | 
| 
33
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2335
 | 
     for(@header) {  | 
| 
34
 | 
2452
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
5229
 | 
         if(/^[ \t]+/) {  | 
| 
35
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             return -1 unless @out;  | 
| 
36
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             $out[-1] .= $_;  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
38
 | 
2450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4911
 | 
             push @out, $_;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # parse request or response line  | 
| 
43
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1717
 | 
     my $obj;  | 
| 
44
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1832
 | 
     my ($major, $minor);  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3661
 | 
     my ($method,$uri,$http) = split / /,$request;  | 
| 
47
 | 
710
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
9658
 | 
     return -1 unless $http and $http =~ /^HTTP\/(\d+)\.(\d+)$/i;  | 
| 
48
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9090
 | 
     ($major, $minor) = ($1, $2);  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3333
 | 
     $env->{REQUEST_METHOD}  = $method;  | 
| 
51
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2891
 | 
     $env->{SERVER_PROTOCOL} = "HTTP/$major.$minor";  | 
| 
52
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1448
 | 
     $env->{REQUEST_URI}     = $uri;  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
54
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9430
 | 
     my($path, $query) = ( $uri =~ /^([^?]*)(?:\?(.*))?$/s );  | 
| 
55
 | 
710
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
2681
 | 
     for ($path, $query) { s/\#.*$// if defined && length } # dumb clients sending URI fragments  | 
| 
 
 | 
1420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8614
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11978
 | 
     $env->{PATH_INFO}    = URI::Escape::uri_unescape($path);  | 
| 
58
 | 
710
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
16668
 | 
     $env->{QUERY_STRING} = $query || '';  | 
| 
59
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1869
 | 
     $env->{SCRIPT_NAME}  = '';  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # import headers  | 
| 
62
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7993
 | 
     my $token = qr/[^][\x00-\x1f\x7f()<>@,;:\\"\/?={} \t]+/;  | 
| 
63
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1874
 | 
     my $k;  | 
| 
64
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2801
 | 
     for my $header (@out) {  | 
| 
65
 | 
2450
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21522
 | 
         if ( $header =~ s/^($token): ?// ) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
66
 | 
2450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6808
 | 
             $k = $1;  | 
| 
67
 | 
2450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10631
 | 
             $k =~ s/-/_/g;  | 
| 
68
 | 
2450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5517
 | 
             $k = uc $k;  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
2450
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
5969
 | 
             if ($k !~ /^(?:CONTENT_LENGTH|CONTENT_TYPE)$/) {  | 
| 
71
 | 
2234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4583
 | 
                 $k = "HTTP_$k";  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ( $header =~ /^\s+/) {  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # multiline header  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
76
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return -1;  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
79
 | 
2450
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
6126
 | 
         if (exists $env->{$k}) {  | 
| 
80
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
310
 | 
             $env->{$k} .= ", $header";  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
82
 | 
2431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9044
 | 
             $env->{$k} = $header;  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4397
 | 
     return $eoh;  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |