| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package File::Listing; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 509 | use strict; | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 4 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 22 |  | 
| 5 | 1 |  |  | 1 |  | 5 | use Carp (); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 17 |  | 
| 6 | 1 |  |  | 1 |  | 495 | use HTTP::Date qw(str2time); | 
|  | 1 |  |  |  |  | 4903 |  | 
|  | 1 |  |  |  |  | 96 |  | 
| 7 | 1 |  |  | 1 |  | 7 | use Exporter 5.57 qw( import ); | 
|  | 1 |  |  |  |  | 34 |  | 
|  | 1 |  |  |  |  | 753 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | # ABSTRACT: Parse directory listing | 
| 10 |  |  |  |  |  |  | our $VERSION = '6.16'; # VERSION | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 0 |  |  | 0 | 0 | 0 | sub Version { $File::Listing::VERSION; } | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | our @EXPORT = qw(parse_dir); | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | sub parse_dir ($;$$$) | 
| 17 |  |  |  |  |  |  | { | 
| 18 | 548 |  |  | 548 | 1 | 541495 | my($dir, $tz, $fstype, $error) = @_; | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 548 |  | 100 |  |  | 1429 | $fstype ||= 'unix'; | 
| 21 | 548 |  |  |  |  | 1037 | $fstype = "File::Listing::" . lc $fstype; | 
| 22 |  |  |  |  |  |  |  | 
| 23 | 548 |  |  |  |  | 1113 | my @args = $_[0]; | 
| 24 | 548 | 100 |  |  |  | 1301 | push(@args, $tz) if(@_ >= 2); | 
| 25 | 548 | 50 |  |  |  | 1133 | push(@args, $error) if(@_ >= 4); | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 548 |  |  |  |  | 1445 | $fstype->parse(@args); | 
| 28 |  |  |  |  |  |  | } | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 0 |  |  | 0 | 0 | 0 | sub line { Carp::croak("Not implemented yet"); } | 
| 32 |  |  |  | 0 | 0 |  | sub init { } # Dummy sub | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | sub file_mode ($) | 
| 36 |  |  |  |  |  |  | { | 
| 37 | 16465 | 50 |  | 16465 | 0 | 9252165 | Carp::croak("Input to file_mode() must be a 10 character string.") | 
| 38 |  |  |  |  |  |  | unless length($_[0]) == 10; | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | # This routine was originally borrowed from Graham Barr's | 
| 41 |  |  |  |  |  |  | # Net::FTP package. | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 16465 |  |  |  |  | 34377 | local $_ = shift; | 
| 44 | 16465 |  |  |  |  | 22162 | my $mode = 0; | 
| 45 | 16465 |  |  |  |  | 20333 | my($type); | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 16465 | 50 |  |  |  | 99615 | s/^(.)// and $type = $1; | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | # When the set-group-ID bit (file mode bit 02000) is set, and the group | 
| 50 |  |  |  |  |  |  | # execution bit (file mode bit 00020) is unset, and it is a regular file, | 
| 51 |  |  |  |  |  |  | # some implementations of `ls' use the letter `S', others use `l' or `L'. | 
| 52 |  |  |  |  |  |  | # Convert this `S'. | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 16465 |  |  |  |  | 48668 | s/[Ll](...)$/S$1/; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 16465 |  |  |  |  | 55026 | while (/(.)/g) { | 
| 57 | 148185 |  |  |  |  | 188479 | $mode <<= 1; | 
| 58 | 148185 | 100 | 100 |  |  | 639572 | $mode |= 1 if $1 ne "-" && | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 59 |  |  |  |  |  |  | $1 ne "*" && | 
| 60 |  |  |  |  |  |  | $1 ne 'S' && | 
| 61 |  |  |  |  |  |  | $1 ne 'T'; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 16465 | 100 |  |  |  | 40840 | $mode |= 0004000 if /^..s....../i; | 
| 65 | 16465 | 100 |  |  |  | 36511 | $mode |= 0002000 if /^.....s.../i; | 
| 66 | 16465 | 100 |  |  |  | 34861 | $mode |= 0001000 if /^........t/i; | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | # De facto standard definitions. From 'stat.h' on Solaris 9. | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 16465 | 0 | 33 |  |  | 134179 | $type eq "p" and $mode |= 0010000 or        # fifo | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 71 |  |  |  |  |  |  | $type eq "c" and $mode |= 0020000 or        # character special | 
| 72 |  |  |  |  |  |  | $type eq "d" and $mode |= 0040000 or        # directory | 
| 73 |  |  |  |  |  |  | $type eq "b" and $mode |= 0060000 or        # block special | 
| 74 |  |  |  |  |  |  | $type eq "-" and $mode |= 0100000 or        # regular | 
| 75 |  |  |  |  |  |  | $type eq "l" and $mode |= 0120000 or        # symbolic link | 
| 76 |  |  |  |  |  |  | $type eq "s" and $mode |= 0140000 or        # socket | 
| 77 |  |  |  |  |  |  | $type eq "D" and $mode |= 0150000 or        # door | 
| 78 |  |  |  |  |  |  | Carp::croak("Unknown file type: $type"); | 
| 79 |  |  |  |  |  |  |  | 
| 80 | 16465 |  |  |  |  | 43823 | $mode; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | sub parse | 
| 85 |  |  |  |  |  |  | { | 
| 86 | 548 |  |  | 548 | 0 | 1037 | my($pkg, $dir, $tz, $error) = @_; | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | # First let's try to determine what kind of dir parameter we have | 
| 89 |  |  |  |  |  |  | # received.  We allow both listings, reference to arrays and | 
| 90 |  |  |  |  |  |  | # file handles to read from. | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 548 | 50 |  |  |  | 2544 | if (ref($dir) eq 'ARRAY') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | # Already split up | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | elsif (ref($dir) eq 'GLOB') { | 
| 96 |  |  |  |  |  |  | # A file handle | 
| 97 |  |  |  |  |  |  | } | 
| 98 |  |  |  |  |  |  | elsif (ref($dir)) { | 
| 99 | 0 |  |  |  |  | 0 | Carp::croak("Illegal argument to parse_dir()"); | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  | elsif ($dir =~ /^\*\w+(::\w+)+$/) { | 
| 102 |  |  |  |  |  |  | # This scalar looks like a file handle, so we assume it is | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  | else { | 
| 105 |  |  |  |  |  |  | # A normal scalar listing | 
| 106 | 546 |  |  |  |  | 2842 | $dir = [ split(/\n/, $dir) ]; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 548 |  |  |  |  | 1606 | $pkg->init(); | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 548 |  |  |  |  | 788 | my @files = (); | 
| 112 | 548 | 100 |  |  |  | 1451 | if (ref($dir) eq 'ARRAY') { | 
| 113 | 546 |  |  |  |  | 1075 | for (@$dir) { | 
| 114 | 1925 |  |  |  |  | 5224 | push(@files, $pkg->line($_, $tz, $error)); | 
| 115 |  |  |  |  |  |  | } | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  | else { | 
| 118 | 2 |  |  |  |  | 6 | local($_); | 
| 119 | 2 |  |  |  |  | 89 | while (my $line = <$dir>) { | 
| 120 | 86 |  |  |  |  | 155 | chomp $line; | 
| 121 | 86 |  |  |  |  | 179 | push(@files, $pkg->line($line, $tz, $error)); | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  | } | 
| 124 | 548 | 100 |  |  |  | 3356 | wantarray ? @files : \@files;  ## no critic (Community::Wantarray) | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | package File::Listing::unix; | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 1 |  |  | 1 |  | 8 | use HTTP::Date qw(str2time); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 687 |  | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | our @ISA = qw(File::Listing); | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | # A place to remember current directory from last line parsed. | 
| 136 |  |  |  |  |  |  | our $curdir; | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | sub init | 
| 139 |  |  |  |  |  |  | { | 
| 140 | 5 |  |  | 5 |  | 10 | $curdir = ''; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | sub line | 
| 145 |  |  |  |  |  |  | { | 
| 146 | 135 |  |  | 135 |  | 174 | shift; # package name | 
| 147 | 135 |  |  |  |  | 244 | local($_) = shift; | 
| 148 | 135 |  |  |  |  | 205 | my($tz, $error) = @_; | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 135 |  |  |  |  | 218 | s/\015//g; | 
| 151 |  |  |  |  |  |  | #study; | 
| 152 |  |  |  |  |  |  |  | 
| 153 | 135 |  |  |  |  | 171 | my ($kind, $size, $date, $name); | 
| 154 | 135 | 100 | 66 |  |  | 1117 | if (($kind, $size, $date, $name) = | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  | 50 | 0 |  |  |  |  | 
|  |  | 0 | 0 |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | /^([\-\*FlrwxsStTdD]{10})                 # Type and permission bits | 
| 156 |  |  |  |  |  |  | .*                                       # Graps | 
| 157 |  |  |  |  |  |  | \D(\d+)                                  # File size | 
| 158 |  |  |  |  |  |  | \s+                                      # Some space | 
| 159 |  |  |  |  |  |  | (\w{3}\s+\d+\s+(?:\d{1,2}:\d{2}|\d{4})|\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2})  # Date | 
| 160 |  |  |  |  |  |  | \s+                                      # Some more space | 
| 161 |  |  |  |  |  |  | (.*)$                                    # File name | 
| 162 |  |  |  |  |  |  | /x ) | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | { | 
| 165 | 105 | 100 | 100 |  |  | 396 | return if $name eq '.' || $name eq '..'; | 
| 166 | 81 | 100 |  |  |  | 333 | $name = "$curdir/$name" if length $curdir; | 
| 167 | 81 |  |  |  |  | 118 | my $type = '?'; | 
| 168 | 81 | 50 | 33 |  |  | 279 | if ($kind =~ /^l/ && $name =~ /(.*) -> (.*)/ ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 169 | 0 |  |  |  |  | 0 | $name = $1; | 
| 170 | 0 |  |  |  |  | 0 | $type = "l $2"; | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | elsif ($kind =~ /^[\-F]/) { # (hopefully) a regular file | 
| 173 | 70 |  |  |  |  | 106 | $type = 'f'; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  | elsif ($kind =~ /^[dD]/) { | 
| 176 | 11 |  |  |  |  | 19 | $type = 'd'; | 
| 177 | 11 |  |  |  |  | 13 | $size = undef;  # Don't believe the reported size | 
| 178 |  |  |  |  |  |  | } | 
| 179 | 81 |  |  |  |  | 201 | return [$name, $type, $size, str2time($date, $tz), | 
| 180 |  |  |  |  |  |  | File::Listing::file_mode($kind)]; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  | elsif (/^(.+):$/ && !/^[dcbsp].*\s.*\s.*:$/ ) { | 
| 184 | 9 |  |  |  |  | 19 | my $dir = $1; | 
| 185 | 9 | 50 |  |  |  | 20 | return () if $dir eq '.'; | 
| 186 | 9 |  |  |  |  | 12 | $curdir = $dir; | 
| 187 | 9 |  |  |  |  | 24 | return (); | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  | elsif (/^[Tt]otal\s+(\d+)$/ || /^\s*$/) { | 
| 190 | 21 |  |  |  |  | 60 | return (); | 
| 191 |  |  |  |  |  |  | } | 
| 192 |  |  |  |  |  |  | elsif (/not found/    || # OSF1, HPUX, and SunOS return | 
| 193 |  |  |  |  |  |  | # "$file not found" | 
| 194 |  |  |  |  |  |  | /No such file/ || # IRIX returns | 
| 195 |  |  |  |  |  |  | # "UX:ls: ERROR: Cannot access $file: No such file or directory" | 
| 196 |  |  |  |  |  |  | # Solaris returns | 
| 197 |  |  |  |  |  |  | # "$file: No such file or directory" | 
| 198 |  |  |  |  |  |  | /cannot find/     # Windows NT returns | 
| 199 |  |  |  |  |  |  | # "The system cannot find the path specified." | 
| 200 |  |  |  |  |  |  | ) { | 
| 201 | 0 | 0 |  |  |  | 0 | return () unless defined $error; | 
| 202 | 0 | 0 |  |  |  | 0 | &$error($_) if ref($error) eq 'CODE'; | 
| 203 | 0 | 0 |  |  |  | 0 | warn "Error: $_\n" if $error eq 'warn'; | 
| 204 | 0 |  |  |  |  | 0 | return (); | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  | elsif ($_ eq '') {       # AIX, and Linux return nothing | 
| 207 | 0 | 0 |  |  |  | 0 | return () unless defined $error; | 
| 208 | 0 | 0 |  |  |  | 0 | &$error("No such file or directory") if ref($error) eq 'CODE'; | 
| 209 | 0 | 0 |  |  |  | 0 | warn "Warning: No such file or directory\n" if $error eq 'warn'; | 
| 210 | 0 |  |  |  |  | 0 | return (); | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  | else { | 
| 213 |  |  |  |  |  |  | # parse failed, check if the dosftp parse understands it | 
| 214 | 0 |  |  |  |  | 0 | File::Listing::dosftp->init(); | 
| 215 | 0 |  |  |  |  | 0 | return(File::Listing::dosftp->line($_,$tz,$error)); | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | package File::Listing::dosftp; | 
| 223 |  |  |  |  |  |  |  | 
| 224 | 1 |  |  | 1 |  | 7 | use HTTP::Date qw(str2time); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1107 |  | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | our @ISA = qw(File::Listing); | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | # A place to remember current directory from last line parsed. | 
| 229 |  |  |  |  |  |  | our $curdir; | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | sub init | 
| 234 |  |  |  |  |  |  | { | 
| 235 | 2 |  |  | 2 |  | 6 | $curdir = ''; | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | sub line | 
| 240 |  |  |  |  |  |  | { | 
| 241 | 4 |  |  | 4 |  | 10 | shift; # package name | 
| 242 | 4 |  |  |  |  | 9 | local($_) = shift; | 
| 243 | 4 |  |  |  |  | 9 | my($tz, $error) = @_; | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 4 |  |  |  |  | 10 | s/\015//g; | 
| 246 |  |  |  |  |  |  |  | 
| 247 | 4 |  |  |  |  | 6 | my ($date, $size_or_dir, $name, $size); | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | # usual format: | 
| 250 |  |  |  |  |  |  | # 02-05-96  10:48AM                 1415 src.slf | 
| 251 |  |  |  |  |  |  | # 09-10-96  09:18AM                 sl_util | 
| 252 |  |  |  |  |  |  | # alternative dos format with four-digit year: | 
| 253 |  |  |  |  |  |  | # 02-05-2022  10:48AM                 1415 src.slf | 
| 254 |  |  |  |  |  |  | # 09-10-2022  09:18AM                 sl_util | 
| 255 | 4 | 50 |  |  |  | 38 | if (($date, $size_or_dir, $name) = | 
| 256 |  |  |  |  |  |  | /^(\d\d-\d\d-\d{2,4}\s+\d\d:\d\d\wM)      # Date and time info | 
| 257 |  |  |  |  |  |  | \s+                                      # Some space | 
| 258 |  |  |  |  |  |  | (<\w{3}>|\d+)                            # Dir or Size | 
| 259 |  |  |  |  |  |  | \s+                                      # Some more space | 
| 260 |  |  |  |  |  |  | (.+)$                                    # File name | 
| 261 |  |  |  |  |  |  | /x ) | 
| 262 |  |  |  |  |  |  | { | 
| 263 | 4 | 50 | 33 |  |  | 22 | return if $name eq '.' || $name eq '..'; | 
| 264 | 4 | 50 |  |  |  | 10 | $name = "$curdir/$name" if length $curdir; | 
| 265 | 4 |  |  |  |  | 8 | my $type = '?'; | 
| 266 | 4 | 100 |  |  |  | 8 | if ($size_or_dir eq '') { | 
| 267 | 2 |  |  |  |  | 4 | $type = "d"; | 
| 268 | 2 |  |  |  |  | 4 | $size = ""; # directories have no size in the pc listing | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  | else { | 
| 271 | 2 |  |  |  |  | 4 | $type = 'f'; | 
| 272 | 2 |  |  |  |  | 3 | $size = $size_or_dir; | 
| 273 |  |  |  |  |  |  | } | 
| 274 | 4 |  |  |  |  | 15 | return [$name, $type, $size, str2time($date, $tz), undef]; | 
| 275 |  |  |  |  |  |  | } | 
| 276 |  |  |  |  |  |  | else { | 
| 277 | 0 | 0 |  |  |  | 0 | return () unless defined $error; | 
| 278 | 0 | 0 |  |  |  | 0 | &$error($_) if ref($error) eq 'CODE'; | 
| 279 | 0 | 0 |  |  |  | 0 | warn "Can't parse: $_\n" if $error eq 'warn'; | 
| 280 | 0 |  |  |  |  | 0 | return (); | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | package File::Listing::vms; | 
| 288 |  |  |  |  |  |  | our @ISA = qw(File::Listing); | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | package File::Listing::netware; | 
| 291 |  |  |  |  |  |  | our @ISA = qw(File::Listing); | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | package File::Listing::apache; | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | our @ISA = qw(File::Listing); | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  | 541 |  |  | sub init { } | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | sub line { | 
| 304 | 1872 |  |  | 1872 |  | 2547 | shift; # package name | 
| 305 | 1872 |  |  |  |  | 3617 | local($_) = shift; | 
| 306 | 1872 |  |  |  |  | 2957 | my($tz, $error) = @_; # ignored for now... | 
| 307 |  |  |  |  |  |  |  | 
| 308 | 1872 |  |  |  |  | 11871 | s!?t[rd][^>]*>! !g;  # clean away various table stuff | 
| 309 | 1872 | 100 |  |  |  | 13412 | if (m!.*.*?(\d+)-([a-zA-Z]+|\d+)-(\d+)\s+(\d+):(\d+)\s+(?:([\d\.]+[kMG]?|-))!i) { | 
|  |  | 100 |  |  |  |  |  | 
| 310 | 1608 |  |  |  |  | 5076 | my($filename, $filesize) = ($1, $7); | 
| 311 | 1608 |  |  |  |  | 4534 | my($d,$m,$y, $H,$M) = ($2,$3,$4,$5,$6); | 
| 312 | 1608 | 100 |  |  |  | 3885 | if ($m =~ /^\d+$/) { | 
| 313 | 699 |  |  |  |  | 1587 | ($d,$y) = ($y,$d) # iso date | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  | else { | 
| 316 | 909 |  |  |  |  | 1724 | $m = _monthabbrev_number($m); | 
| 317 |  |  |  |  |  |  | } | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 1608 | 100 |  |  |  | 3799 | $filesize = 0 if $filesize eq '-'; | 
| 320 | 1608 | 100 |  |  |  | 5380 | if ($filesize =~ s/k$//i) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 321 | 589 |  |  |  |  | 1455 | $filesize *= 1024; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | elsif ($filesize =~ s/M$//) { | 
| 324 | 10 |  |  |  |  | 30 | $filesize *= 1024*1024; | 
| 325 |  |  |  |  |  |  | } | 
| 326 |  |  |  |  |  |  | elsif ($filesize =~ s/G$//) { | 
| 327 | 0 |  |  |  |  | 0 | $filesize *= 1024*1024*1024; | 
| 328 |  |  |  |  |  |  | } | 
| 329 | 1608 |  |  |  |  | 2698 | $filesize = int $filesize; | 
| 330 |  |  |  |  |  |  |  | 
| 331 | 1608 |  |  |  |  | 7621 | require Time::Local; | 
| 332 | 1608 |  |  |  |  | 3624 | my $filetime = Time::Local::timelocal(0,$M,$H,$d,$m-1,_guess_year($y)); | 
| 333 | 1608 | 100 |  |  |  | 116250 | my $filetype = ($filename =~ s|/$|| ? "d" : "f"); | 
| 334 | 1608 |  |  |  |  | 7942 | return [$filename, $filetype, $filesize, $filetime, undef]; | 
| 335 |  |  |  |  |  |  | } | 
| 336 |  |  |  |  |  |  |  | 
| 337 |  |  |  |  |  |  | # the default listing doesn't include timestamps or file sizes | 
| 338 |  |  |  |  |  |  | # but we don't want to grab navigation links, so we ignore links | 
| 339 |  |  |  |  |  |  | # that have a non-trailing slash / character or ? | 
| 340 |  |  |  |  |  |  | elsif(m!.*!i) { | 
| 341 | 23 |  |  |  |  | 51 | my $filename = $1; | 
| 342 | 23 | 100 |  |  |  | 48 | my $filetype = ($filename =~ s|/$|| ? "d" : "f"); | 
| 343 | 23 |  |  |  |  | 69 | return [$filename, $filetype, undef, undef, undef]; | 
| 344 |  |  |  |  |  |  | } | 
| 345 |  |  |  |  |  |  |  | 
| 346 | 241 |  |  |  |  | 418 | return (); | 
| 347 |  |  |  |  |  |  | } | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | sub _guess_year { | 
| 351 | 1608 |  |  | 1608 |  | 2288 | my $y = shift; | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | # if the year is already four digit then we shouldn't do | 
| 354 |  |  |  |  |  |  | # anything to modify it. | 
| 355 | 1608 | 50 |  |  |  | 3467 | if ($y >= 1900) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | # do nothing | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | # TODO: for hysterical er historical reasons we assume 9x is in the | 
| 359 |  |  |  |  |  |  | # 1990s we should probably not do that, but I don't have any examples | 
| 360 |  |  |  |  |  |  | # where apache provides two digit dates so I am leaving this as-is | 
| 361 |  |  |  |  |  |  | # for now.  Possibly the right thing is to not handle two digit years. | 
| 362 |  |  |  |  |  |  | } elsif ($y >= 90) { | 
| 363 | 0 |  |  |  |  | 0 | $y = 1900+$y; | 
| 364 |  |  |  |  |  |  | } | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | # TODO: likewise assuming 00-89 are 20xx is long term probably wrong. | 
| 367 |  |  |  |  |  |  | elsif ($y < 100) { | 
| 368 | 0 |  |  |  |  | 0 | $y = 2000+$y; | 
| 369 |  |  |  |  |  |  | } | 
| 370 | 1608 |  |  |  |  | 4644 | $y; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | sub _monthabbrev_number { | 
| 375 | 909 |  |  | 909 |  | 1331 | my $mon = shift; | 
| 376 |  |  |  |  |  |  | +{'Jan' => 1, | 
| 377 |  |  |  |  |  |  | 'Feb' => 2, | 
| 378 |  |  |  |  |  |  | 'Mar' => 3, | 
| 379 |  |  |  |  |  |  | 'Apr' => 4, | 
| 380 |  |  |  |  |  |  | 'May' => 5, | 
| 381 |  |  |  |  |  |  | 'Jun' => 6, | 
| 382 |  |  |  |  |  |  | 'Jul' => 7, | 
| 383 |  |  |  |  |  |  | 'Aug' => 8, | 
| 384 |  |  |  |  |  |  | 'Sep' => 9, | 
| 385 |  |  |  |  |  |  | 'Oct' => 10, | 
| 386 |  |  |  |  |  |  | 'Nov' => 11, | 
| 387 |  |  |  |  |  |  | 'Dec' => 12, | 
| 388 | 909 |  |  |  |  | 6259 | }->{$mon}; | 
| 389 |  |  |  |  |  |  | } | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  |  | 
| 392 |  |  |  |  |  |  | 1; | 
| 393 |  |  |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | __END__ |