@ISA
=
qw(LWP::Protocol)
;
sub
request
{
my
(
$self
,
$request
,
$proxy
,
$arg
,
$size
) =
@_
;
LWP::Debug::trace(
'()'
);
$size
= 4096
unless
defined
$size
and
$size
> 0;
if
(
defined
$proxy
)
{
return
new HTTP::Response
&HTTP::Status::RC_BAD_REQUEST
,
'You can not proxy through the filesystem'
;
}
my
$method
=
$request
->method;
unless
(
$method
eq
'GET'
||
$method
eq
'HEAD'
) {
return
new HTTP::Response
&HTTP::Status::RC_BAD_REQUEST
,
'Library does not allow method '
.
"$method for 'file:' URLs"
;
}
my
$url
=
$request
->url;
my
$scheme
=
$url
->scheme;
if
(
$scheme
ne
'file'
) {
return
new HTTP::Response
&HTTP::Status::RC_INTERNAL_SERVER_ERROR
,
"LWP::Protocol::file::request called for '$scheme'"
;
}
my
$path
=
$url
->file;
unless
(-e
$path
) {
return
new HTTP::Response
&HTTP::Status::RC_NOT_FOUND
,
"File `$path' does not exist"
;
}
unless
(-r _) {
return
new HTTP::Response
&HTTP::Status::RC_FORBIDDEN
,
'User does not have read permission'
;
}
my
(
$dev
,
$ino
,
$mode
,
$nlink
,
$uid
,
$gid
,
$rdev
,
$filesize
,
$atime
,
$mtime
,
$ctime
,
$blksize
,
$blocks
)
=
stat
(_);
my
$ims
=
$request
->header(
'If-Modified-Since'
);
if
(
defined
$ims
) {
my
$time
= HTTP::Date::str2time(
$ims
);
if
(
defined
$time
and
$time
>=
$mtime
) {
return
new HTTP::Response
&HTTP::Status::RC_NOT_MODIFIED
,
"$method $path"
;
}
}
my
$response
= new HTTP::Response
&HTTP::Status::RC_OK
;
$response
->header(
'Last-Modified'
, HTTP::Date::time2str(
$mtime
));
if
(-d _) {
opendir
(D,
$path
) or
return
new HTTP::Response
&HTTP::Status::RC_INTERNAL_SERVER_ERROR
,
"Cannot read directory '$path': $!"
;
my
(
@files
) =
sort
readdir
(D);
closedir
(D);
my
$pathe
=
$path
. ( $^O eq
'MacOS'
?
':'
:
'/'
);
for
(
@files
) {
my
$furl
= URI::Escape::uri_escape(
$_
);
if
( -d
"$pathe$_"
) {
$furl
.=
'/'
;
$_
.=
'/'
;
}
my
$desc
= HTML::Entities::encode(
$_
);
$_
=
qq{<LI><A HREF="$furl">$desc</A>}
;
}
my
$base
=
$url
->clone;
unless
(
$base
->path =~ m|/$|) {
$base
->path(
$base
->path .
"/"
);
}
my
$html
=
join
(
"\n"
,
"<HTML>\n<HEAD>"
,
"<TITLE>Directory $path</TITLE>"
,
"<BASE HREF=\"$base\">"
,
"</HEAD>\n<BODY>"
,
"<H1>Directory listing of $path</H1>"
,
"<UL>"
,
@files
,
"</UL>"
,
"</BODY>\n</HTML>\n"
);
$response
->header(
'Content-Type'
,
'text/html'
);
$response
->header(
'Content-Length'
,
length
$html
);
$html
=
""
if
$method
eq
"HEAD"
;
return
$self
->collect_once(
$arg
,
$response
,
$html
);
}
$response
->header(
'Content-Length'
,
$filesize
);
LWP::MediaTypes::guess_media_type(
$path
,
$response
);
if
(
$method
ne
"HEAD"
) {
open
(F,
$path
) or
return
new
HTTP::Response(
&HTTP::Status::RC_INTERNAL_SERVER_ERROR
,
"Cannot read file '$path': $!"
);
binmode
(F);
$response
=
$self
->collect(
$arg
,
$response
,
sub
{
my
$content
=
""
;
my
$bytes
=
sysread
(F,
$content
,
$size
);
return
\
$content
if
$bytes
> 0;
return
\
""
;
});
close
(F);
}
$response
;
}
1;