aboutsummaryrefslogtreecommitdiff
path: root/www/publicfile
diff options
context:
space:
mode:
authorVolker Stolz <vs@FreeBSD.org>2005-02-27 18:42:31 +0000
committerVolker Stolz <vs@FreeBSD.org>2005-02-27 18:42:31 +0000
commit03874bb5ff1fe59ee8bea892866a143650978876 (patch)
tree712ab1d77f78fd68d11dedf8df651e4d8c3f07fb /www/publicfile
parent854c622b1c78c04e34ac923c63c462813b9e5346 (diff)
downloadports-03874bb5ff1fe59ee8bea892866a143650978876.tar.gz
ports-03874bb5ff1fe59ee8bea892866a143650978876.zip
Notes
Diffstat (limited to 'www/publicfile')
-rw-r--r--www/publicfile/Makefile69
-rw-r--r--www/publicfile/distinfo1
-rw-r--r--www/publicfile/files/publicfile-0.52-commonlog-2.patch463
-rw-r--r--www/publicfile/files/publicfile-0.52-filetype-diff34
-rw-r--r--www/publicfile/files/publicfile-0.52_basicauth.patch638
-rw-r--r--www/publicfile/files/publicfile-0.52_basicauth.patch.in638
-rw-r--r--www/publicfile/files/publicfile.sslserver36
-rw-r--r--www/publicfile/files/redirect-slash-patch217
-rw-r--r--www/publicfile/pkg-plist1
9 files changed, 2094 insertions, 3 deletions
diff --git a/www/publicfile/Makefile b/www/publicfile/Makefile
index 5e9ce066be84..e3edce1fcd7f 100644
--- a/www/publicfile/Makefile
+++ b/www/publicfile/Makefile
@@ -7,23 +7,86 @@
PORTNAME= publicfile
PORTVERSION= 0.52
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= www ftp
MASTER_SITES= http://cr.yp.to/publicfile/ \
ftp://cr.yp.to/publicfile/
-MAINTAINER= ports@FreeBSD.org
+MAINTAINER= lx@redundancy.redundancy.org
COMMENT= A secure, read-only, anonymous HTTP/FTP server
RUN_DEPENDS= setuidgid:${PORTSDIR}/sysutils/daemontools \
tcpserver:${PORTSDIR}/sysutils/ucspi-tcp
+OPTIONS= BASICAUTH "basic HTTP authentication support" off \
+ COMMONLOG "support for Apache common log format" on \
+ REDIRECT_SLASH "don't complain when omitting trailing slash" off \
+ SSL "provide SSL support through ucspi-ssl" on
+
+.include <bsd.port.pre.mk>
+
+pre-everything::
+.if defined(WITH_BASICAUTH) && defined(WITH_COMMONLOG)
+ @${ECHO_MSG}
+ @${ECHO_MSG} "Currently the common log and auth patches conflict."
+ @${ECHO_MSG}
+BROKEN= "Currently the common log and auth patches conflict."
+.endif
+
+.if defined(WITH_BASICAUTH) && defined(WITH_REDIRECT_SLASH)
+ @${ECHO_MSG}
+ @${ECHO_MSG} "Currently the redirect slash and auth patches conflict."
+ @${ECHO_MSG}
+BROKEN= "Currently the redirect slash and auth patches conflict."
+.endif
+
+.if defined(WITH_REDIRECT_SLASH)
+pre-configure::
+ @${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/redirect-slash-patch
+.endif
+
+.if defined(WITH_ENV_FILETYPES)
+pre-configure::
+ @${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/publicfile-0.52-filetype-diff
+.endif
+
+.if defined(WITH_SSL)
+pre-configure::
+ @${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/publicfile.sslserver
+RUN_DEPENDS+= sslserver:${PORTSDIR}/sysutils/ucspi-ssl
+.endif
+
+.if defined(WITH_BASICAUTH)
+pre-configure::
+ @${SED} -e "s:__PORTSDIR__:${PORTSDIR}:g" \
+ -e "s:__WRKSRC__:${WRKSRC}:g" \
+ ${PATCHDIR}/publicfile-0.52_basicauth.patch.in > \
+ ${PATCHDIR}/publicfile-0.52_basicauth.patch
+ @${PATCH} ${PATCH_ARGS} -p1 < \
+ ${PATCHDIR}/publicfile-0.52_basicauth.patch
+BUILD_DEPENDS+= ${NONEXISTENT}:${PORTSDIR}/databases/cdb:extract
+PLIST_SUB+= BASICAUTH=""
+.else
+PLIST_SUB+= BASICAUTH="@comment "
+.endif
+
+.if defined(WITH_COMMONLOG)
+pre-configure::
+ @${PATCH} ${PATCH_ARGS} -p1 < \
+ ${PATCHDIR}/publicfile-0.52-commonlog-2.patch
+.endif
+
ALL_TARGET= it
INSTALL_TARGET= setup check
+post-extract:
+.if defined(WITH_BASICAUTH)
+ @${LN} -s ${PORTSDIR}/databases/cdb/work/cdb-0.75 ${WRKSRC}/cdb-0.75
+.endif
+
post-patch:
@${ECHO_CMD} "${CC} ${CFLAGS}" > ${WRKSRC}/conf-cc
@${ECHO_CMD} "${CC} -s" > ${WRKSRC}/conf-ld
@${ECHO_CMD} "${PREFIX}" > ${WRKSRC}/conf-home
-.include <bsd.port.mk>
+.include <bsd.port.post.mk>
diff --git a/www/publicfile/distinfo b/www/publicfile/distinfo
index 1ac7cfe1b22c..e2cde273c6bf 100644
--- a/www/publicfile/distinfo
+++ b/www/publicfile/distinfo
@@ -1 +1,2 @@
MD5 (publicfile-0.52.tar.gz) = e493d69627b4fb2c7c764c0ff34330d7
+SIZE (publicfile-0.52.tar.gz) = 34892
diff --git a/www/publicfile/files/publicfile-0.52-commonlog-2.patch b/www/publicfile/files/publicfile-0.52-commonlog-2.patch
new file mode 100644
index 000000000000..ed14642b22e7
--- /dev/null
+++ b/www/publicfile/files/publicfile-0.52-commonlog-2.patch
@@ -0,0 +1,463 @@
+diff -rNC3 publicfile-0.52.orig/Makefile publicfile-0.52/Makefile
+*** publicfile-0.52.orig/Makefile Tue Nov 9 08:23:46 1999
+--- publicfile-0.52/Makefile Fri Nov 9 10:09:45 2001
+***************
+*** 450,460 ****
+ stralloc.a: \
+ makelib stralloc_cat.o stralloc_catb.o stralloc_cats.o \
+ stralloc_copy.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \
+! stralloc_pend.o stralloc_num.o
+ ./makelib stralloc.a stralloc_cat.o stralloc_catb.o \
+ stralloc_cats.o stralloc_copy.o stralloc_eady.o \
+ stralloc_opyb.o stralloc_opys.o stralloc_pend.o \
+! stralloc_num.o
+
+ stralloc_cat.o: \
+ compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+--- 450,460 ----
+ stralloc.a: \
+ makelib stralloc_cat.o stralloc_catb.o stralloc_cats.o \
+ stralloc_copy.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \
+! stralloc_pend.o stralloc_num.o stralloc_opytrim.o
+ ./makelib stralloc.a stralloc_cat.o stralloc_catb.o \
+ stralloc_cats.o stralloc_copy.o stralloc_eady.o \
+ stralloc_opyb.o stralloc_opys.o stralloc_pend.o \
+! stralloc_num.o stralloc_opytrim.o
+
+ stralloc_cat.o: \
+ compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+***************
+*** 484,489 ****
+--- 484,493 ----
+ stralloc_opyb.o: \
+ compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_opyb.c
++
++ stralloc_opytrim.o: \
++ compile stralloc_opytrim.c stralloc.h
++ ./compile stralloc_opytrim.c
+
+ stralloc_opys.o: \
+ compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h
+diff -rNC3 publicfile-0.52.orig/README.log_combined publicfile-0.52/README.log_combined
+*** publicfile-0.52.orig/README.log_combined Thu Jan 1 01:00:00 1970
+--- publicfile-0.52/README.log_combined Fri Nov 9 10:09:45 2001
+***************
+*** 0 ****
+--- 1,36 ----
++ This version of publicfile has been patched to write *additional* log
++ information to STDERR. This additional information conforms to Apache's
++ and Netscape's "common" or "combined" log formats, i. e. a line may look
++ like this (common log format):
++
++ 127.0.0.1 - - [23/Oct/2001:14:04:56 +0200] "HEAD /~conrad/hello_world_gen.swf HTTP/1.0" 200 0
++
++ or like this (combined log format):
++
++ 127.0.0.1 - - [23/Oct/2001:14:04:56 +0200] "HEAD /~conrad/hello_world_gen.swf HTTP/1.0" 200 0 "http://localhost/~conrad/hello_world.html" "Mozilla 4"
++
++ The meaning of the (space-separated) fields is as follows:
++
++ 1. Client IP-address
++ 2. Remote logname (from ident (RFC-...) lookup - always "-" in publicfile)
++ 3. Authenticated username (from Basic-Auth - always "-" in publicfile)
++ 4. Human-readable timestamp enclosed in []
++ 5. The request line enclosed in ""
++ 6. HTTP status code
++ 7. Number of bytes sent excluding HTTP headers
++ 8. Referrer information sent by the browser
++ 9. User-Agent information sent by the browser
++
++ These log lines can easily be distinguished from other log lines using the
++ second field: this will always be "-" for common and combined log lines,
++ and "read" or "dir" for publicfile standard log lines (see
++ http://cr.yp.to/publicfile/log.html). The script "splitPublicfileLog.pl"
++ may serve as an example how to split the log into interesting parts.
++
++ The logformat to be used can be selected via environment variables:
++
++ - HTTPD_LOG_COMMON selects common log format
++ - HTTPD_LOG_COMBINED selects combined log format
++
++ The latter takes precedence over the former.
++
+diff -rNC3 publicfile-0.52.orig/httpd.c publicfile-0.52/httpd.c
+*** publicfile-0.52.orig/httpd.c Tue Nov 9 08:23:46 1999
+--- publicfile-0.52/httpd.c Fri Nov 9 10:10:51 2001
+***************
+*** 15,20 ****
+--- 15,102 ----
+ #include "substdio.h"
+ #include "error.h"
+ #include "getln.h"
++ #include "caltime.h"
++ #include "subfd.h"
++ #include "env.h"
++
++ char logformat = 0;
++ char *remoteip;
++ char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
++ stralloc referer = {0};
++ stralloc agent = {0};
++
++ char strnum[FMT_ULONG];
++ stralloc method = {0};
++ stralloc url = {0};
++ stralloc protocol = {0};
++ stralloc host = {0};
++
++ void log(char *code, unsigned long length) {
++ struct caltime ct;
++ int dummy1, dummy2;
++ struct tai now;
++
++ if (!logformat) return;
++
++ substdio_puts(subfderr,remoteip);
++ substdio_puts(subfderr," - - [");
++ tai_now(&now);
++ caltime_utc(&ct, &now, &dummy1, &dummy2);
++ if (ct.date.day < 10)
++ substdio_puts(subfderr,"0");
++ dummy1 = fmt_ulong(strnum,ct.date.day);
++ substdio_put(subfderr,strnum,dummy1);
++ substdio_puts(subfderr,"/");
++ if (ct.date.month > 0 && ct.date.month < 13)
++ substdio_puts(subfderr,months[ct.date.month-1]);
++ substdio_puts(subfderr,"/");
++ dummy1 = fmt_ulong(strnum,ct.date.year);
++ substdio_put(subfderr,strnum,dummy1);
++ substdio_puts(subfderr,":");
++ if (ct.hour < 10)
++ substdio_puts(subfderr,"0");
++ dummy1 = fmt_ulong(strnum,ct.hour);
++ substdio_put(subfderr,strnum,dummy1);
++ substdio_puts(subfderr,":");
++ if (ct.minute < 10)
++ substdio_puts(subfderr,"0");
++ dummy1 = fmt_ulong(strnum,ct.minute);
++ substdio_put(subfderr,strnum,dummy1);
++ substdio_puts(subfderr,":");
++ if (ct.second < 10)
++ substdio_puts(subfderr,"0");
++ dummy1 = fmt_ulong(strnum,ct.second);
++ substdio_put(subfderr,strnum,dummy1);
++ substdio_puts(subfderr," +0000] \"");
++ substdio_put(subfderr,method.s,method.len - 1); /* len includes \0 */
++ substdio_puts(subfderr," ");
++ substdio_put(subfderr,url.s,url.len);
++ substdio_puts(subfderr," ");
++ substdio_put(subfderr,protocol.s,protocol.len > 0 ? protocol.len - 1 : 0); /* len includes \0 */
++ substdio_puts(subfderr,"\" ");
++ substdio_put(subfderr,code,str_len(code) < 3 ? str_len(code) : 3);
++ substdio_puts(subfderr," ");
++ if (length > 0) {
++ dummy1 = fmt_ulong(strnum,length);
++ substdio_put(subfderr,strnum,dummy1);
++ } else {
++ substdio_puts(subfderr,"-");
++ }
++
++ if (logformat > 1) {
++ substdio_puts(subfderr," \"");
++ substdio_put(subfderr,referer.s,referer.len);
++ substdio_puts(subfderr,"\" \"");
++ substdio_put(subfderr,agent.s,agent.len);
++ substdio_puts(subfderr,"\"");
++ }
++
++ substdio_puts(subfderr," \"");
++ substdio_put(subfderr,host.s,host.len);
++ substdio_puts(subfderr,"\"\n");
++ substdio_flush(subfderr);
++ }
+
+ int safewrite(int fd,char *buf,int len)
+ {
+***************
+*** 42,54 ****
+ substdio_flush(&out);
+ }
+
+- char strnum[FMT_ULONG];
+-
+- stralloc protocol = {0};
+ int protocolnum = 0;
+- stralloc method = {0};
+- stralloc url = {0};
+- stralloc host = {0};
+ stralloc path = {0};
+ stralloc ims = {0};
+ int flagbody = 1;
+--- 124,130 ----
+***************
+*** 93,98 ****
+--- 169,175 ----
+ out_puts("</body></html>\r\n");
+ }
+ out_flush();
++ log(code, str_len(message) + 28);
+ if (protocolnum >= 2) {
+ shutdown(1,1);
+ sleep(1); /* XXX */
+***************
+*** 105,108 ****
+--- 182,186 ----
+
+ void get(void)
+ {
++ char *code;
+ unsigned long length;
+***************
+*** 133,143 ****
+ tai_now(&now);
+ if (!httpdate(&mtimestr,&mtime)) _exit(21);
+ if ((ims.len < mtimestr.len) || byte_diff(mtimestr.s,mtimestr.len,ims.s))
+! header("200 ","OK");
+ else {
+! header("304 ","OK");
+ flagbody = 0;
+ }
+ if (tai_less(&mtime,&now)) {
+ tai_sub(&mtimeage,&now,&mtime);
+ if (tai_approx(&mtimeage) >= 60.0) {
+--- 211,222 ----
+ tai_now(&now);
+ if (!httpdate(&mtimestr,&mtime)) _exit(21);
+ if ((ims.len < mtimestr.len) || byte_diff(mtimestr.s,mtimestr.len,ims.s))
+! code = "200 ";
+ else {
+! code = "304 ";
+ flagbody = 0;
+ }
++ header(code,"OK");
+ if (tai_less(&mtime,&now)) {
+ tai_sub(&mtimeage,&now,&mtime);
+ if (tai_approx(&mtimeage) >= 60.0) {
+***************
+*** 166,171 ****
+--- 245,253 ----
+ if (r == 0) break;
+ out_put(filebuf,r);
+ }
++ else
++ length = 0;
++ log(code,length);
+ out_flush();
+ _exit(0);
+ }
+***************
+*** 180,185 ****
+--- 262,270 ----
+ out_put(filebuf,r);
+ out_puts("\r\n");
+ }
++ else
++ length = 0;
++ log(code,length);
+
+ close(fd);
+ }
+***************
+*** 216,221 ****
+--- 301,314 ----
+
+ sig_pipeignore();
+
++ if (env_get("HTTPD_LOG_COMMON"))
++ logformat = 1;
++ if (env_get("HTTPD_LOG_COMBINED"))
++ logformat = 2;
++ remoteip = env_get("TCPREMOTEIP");
++ if (!remoteip)
++ remoteip = "0";
++
+ for (;;) {
+ readline();
+
+***************
+*** 227,232 ****
+--- 320,327 ----
+ if (!stralloc_copys(&path,"")) _exit(21);
+ if (!stralloc_copys(&protocol,"")) _exit(21);
+ if (!stralloc_copys(&ims,"")) _exit(21);
++ if (!stralloc_copys(&referer,"")) _exit(21);
++ if (!stralloc_copys(&agent,"")) _exit(21);
+ protocolnum = 2;
+
+ spaces = 0;
+***************
+*** 294,299 ****
+--- 389,398 ----
+ barf("412 ","I do not accept If-None-Match");
+ if (case_startb(field.s,field.len,"if-unmodified-since:"))
+ barf("412 ","I do not accept If-Unmodified-Since");
++ if (case_startb(field.s,field.len,"referer:"))
++ if (!stralloc_copytrim(&referer,field.s + 8,field.len - 8)) _exit(21);
++ if (case_startb(field.s,field.len,"user-agent:"))
++ if (!stralloc_copytrim(&agent,field.s + 11,field.len - 11)) _exit(21);
+ if (case_startb(field.s,field.len,"host:"))
+ if (!host.len)
+ for (i = 5;i < field.len;++i)
+diff -rNC3 publicfile-0.52.orig/splitPublicfileLog.pl publicfile-0.52/splitPublicfileLog.pl
+*** publicfile-0.52.orig/splitPublicfileLog.pl Thu Jan 1 01:00:00 1970
+--- publicfile-0.52/splitPublicfileLog.pl Fri Nov 9 10:09:45 2001
+***************
+*** 0 ****
+--- 1,119 ----
++ #!/usr/bin/perl -w
++
++ # This script will read lines from stdin. All lines starting with
++ # "a.b.c.d - " (for an IP-number a.b.c.d) will be written to the
++ # "access logfile" given as the first argument. Anything else will be
++ # prepended with a timestamp and
++ # written to the "error logfile" given as the second argument.
++ # Note that the messages usually are not really *error* messages, but
++ # simply the standard publicfile output.
++
++ use strict;
++ use Symbol;
++
++ if ($#ARGV < 0 || $#ARGV > 3) {
++ &usage();
++ }
++
++ local $main::logdir;
++ local $main::accessfile;
++ local $main::errorfile;
++ local $main::multilog;
++ local %main::handles = ();
++
++ if ($ARGV[0] eq "-m") {
++ $main::multilog = 1;
++ if ($#ARGV != 3) { &usage(); }
++ $main::logdir = $ARGV[1]."/";
++ $main::accessfile = $main::logdir.$ARGV[2];
++ $main::errorfile = $main::logdir.$ARGV[3];
++ } else {
++ $main::multilog = 0;
++ if ($#ARGV != 1) { &usage(); }
++ $main::accessfile = $ARGV[0];
++ $main::errorfile = $ARGV[1];
++ }
++
++ #open(ACCESS, ">>".$ARGV[0]) || die("Can't open access logfile!");
++ #open(ERROR, ">>".$ARGV[1]) || die("Can't open error logfile!");
++ $SIG{PIPE} = \&closeAndExit;
++ $SIG{TERM} = \&closeAndExit;
++ $SIG{QUIT} = \&closeAndExit;
++ $SIG{INT} = \&closeAndExit;
++ $SIG{HUP} = \&closeAll;
++
++ while($_ = <STDIN>) {
++ if (/^\d+\.\d+\.\d+\.\d+ - /) {
++ my $host = "";
++ if ($main::multilog && / \"([^\"\/]*)\"[\r\n]*$/) {
++ $_ = $`."\n";
++ $host = $1;
++ }
++ my $fh = &getHandle($host);
++ print $fh $_;
++ } else {
++ my $fh = &getHandle($main::errorfile);
++ print $fh time()." $_";
++ }
++ }
++
++ closeAndExit("End of input");
++
++ sub closeAll {
++ foreach my $key (keys %main::handles) {
++ my $fh = $main::handles{$key};
++ close $fh;
++ delete $main::handles{$key};
++ }
++ }
++
++ sub closeAndExit {
++ my $reason = shift;
++ my $now = time();
++
++ my $fh = &getHandle($main::errorfile);
++ print $fh "$now $reason received\n";
++ print STDERR "$now $reason received\n";
++ &closeAll();
++ exit 0;
++ }
++
++ sub getHandle {
++ my $key = shift;
++ my $res = 0;
++
++ if (defined($main::handles{$key})) {
++ return $main::handles{$key};
++ }
++
++ my $fh = Symbol::gensym();
++ if ($key eq $main::errorfile) {
++ open($fh, ">>".$main::errorfile) || die("Can't open error logfile!");
++ } else {
++ if ($main::multilog) {
++ my $fn = $main::logdir.$key;
++ if (-f $fn && -w $fn) {
++ $res = open($fh, ">>$fn");
++ }
++ }
++ if (!$res) {
++ open($fh, ">>".$main::accessfile) || die("Can't open error logfile!");
++ }
++ }
++
++ $main::handles{$key} = $fh;
++ return $fh;
++ }
++
++ sub usage {
++ print STDERR "Usage: $0 <access-path> <error-path>\n";
++ print STDERR " or: $0 -m <logdir> <access-file> <error-file>\n";
++ print STDERR "The first form will separate publicfile standard messages from \"common\" log\n";
++ print STDERR "lines. The second form will write \"common\" lines to <logdir>/<hostname>\n";
++ print STDERR "where <hostname> is the host given in the request. The file <logdir>/<hostname>\n";
++ print STDERR "must exist before it will be used. Anything for which no suitable logfile can\n";
++ print STDERR "be found will be logged to <logdir>/<access-path>.\n";
++
++ exit 1;
++ }
++
+diff -rNC3 publicfile-0.52.orig/stralloc.h publicfile-0.52/stralloc.h
+*** publicfile-0.52.orig/stralloc.h Tue Nov 9 08:23:46 1999
+--- publicfile-0.52/stralloc.h Fri Nov 9 10:09:45 2001
+***************
+*** 12,17 ****
+--- 12,18 ----
+ extern int stralloc_copys();
+ extern int stralloc_cats();
+ extern int stralloc_copyb();
++ extern int stralloc_copytrim();
+ extern int stralloc_catb();
+ extern int stralloc_append(); /* beware: this takes a pointer to 1 char */
+ extern int stralloc_starts();
+diff -rNC3 publicfile-0.52.orig/stralloc_opytrim.c publicfile-0.52/stralloc_opytrim.c
+*** publicfile-0.52.orig/stralloc_opytrim.c Thu Jan 1 01:00:00 1970
+--- publicfile-0.52/stralloc_opytrim.c Fri Nov 9 10:09:45 2001
+***************
+*** 0 ****
+--- 1,17 ----
++ #include "stralloc.h"
++
++ int stralloc_copytrim(sa,s,n)
++ stralloc *sa;
++ char *s;
++ unsigned int n;
++ {
++ while (n > 0 &&
++ (s[n] == ' ' || s[n] == '\t' || s[n] == '\n' || s[n] == '\r')) n--;
++ while (n > 0 &&
++ (s[0] == ' ' || s[0] == '\t' || s[0] == '\n' || s[0] == '\r')) {
++ n--;
++ s++;
++ }
++
++ return stralloc_copyb(sa,s,n);
++ }
diff --git a/www/publicfile/files/publicfile-0.52-filetype-diff b/www/publicfile/files/publicfile-0.52-filetype-diff
new file mode 100644
index 000000000000..3c963feca229
--- /dev/null
+++ b/www/publicfile/files/publicfile-0.52-filetype-diff
@@ -0,0 +1,34 @@
+--- filetype.c.old Mon Dec 6 10:43:36 1999
++++ filetype.c Mon Dec 6 10:50:36 1999
+@@ -1,5 +1,6 @@
+ #include "filetype.h"
+ #include "str.h"
++#include "env.h"
+
+ void filetype(char *fn,stralloc *contenttype)
+ {
+@@ -22,7 +23,7 @@
+ if (!stralloc_append(contenttype,&ch)) _exit(21);
+ }
+ else {
+- result = "text/plain";
++ result = 0;
+ if (str_equal(x,".html")) result = "text/html";
+ else if (str_equal(x,".gz")) result = "application/x-gzip";
+ else if (str_equal(x,".dvi")) result = "application/x-dvi";
+@@ -32,6 +33,15 @@
+ else if (str_equal(x,".jpeg")) result = "image/jpeg";
+ else if (str_equal(x,".png")) result = "image/png";
+ else if (str_equal(x,".mpeg")) result = "video/mpeg";
++ if (!result) {
++ stralloc envname = {0};
++ if (!stralloc_copys(&envname,"CT_")) _exit(21);
++ if (!stralloc_cats(&envname,x+1)) _exit(21);
++ if (!stralloc_0(&envname)) _exit(21);
++ result=env_get(envname.s);
++ alloc_free(envname.s); /* is this the right function */
++ }
++ if (!result) result="text/plain";
+
+ if (!stralloc_cats(contenttype,result)) _exit(21);
+ }
diff --git a/www/publicfile/files/publicfile-0.52_basicauth.patch b/www/publicfile/files/publicfile-0.52_basicauth.patch
new file mode 100644
index 000000000000..7200c5b3321d
--- /dev/null
+++ b/www/publicfile/files/publicfile-0.52_basicauth.patch
@@ -0,0 +1,638 @@
+diff -N -u -r publicfile-0.52.orig/Makefile publicfile-0.52/Makefile
+--- publicfile-0.52.orig/Makefile Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/Makefile Wed Aug 29 20:27:09 2001
+@@ -234,21 +234,43 @@
+ compile hier.c auto_home.h
+ ./compile hier.c
+
++htrules: \
++load htrules.o base64.o
++ ./load htrules cdb.a base64.o byte.a getln.a stralloc.a alloc.a \
++ substdio.a str.a buffer.a unix.a
++
++htrules.o: \
++compile htrules.c strerr.h stralloc.h gen_alloc.h getln.h buffer.h \
++stralloc.h buffer.h exit.h fmt.h byte.h cdb_make.h buffer.h uint32.h \
++base64.h
++ ./compile htrules.c
++
++base64.o: \
++compile base64.c base64.h
++ ./compile base64.c
++
+ httpd: \
+ load httpd.o main.o pathdecode.o file.o filetype.o httpdate.o \
+ percent.o prot.o timeoutread.o timeoutwrite.o libtai.a case.a getln.a \
+ stralloc.a alloc.a substdio.a error.a open.a sig.a env.a str.a fs.a \
+-socket.lib
++socket.lib readclose.o openreadclose.o
+ ./load httpd main.o pathdecode.o file.o filetype.o \
+ httpdate.o percent.o prot.o timeoutread.o timeoutwrite.o \
+ libtai.a case.a getln.a stralloc.a alloc.a substdio.a \
+- error.a open.a sig.a env.a str.a fs.a `cat socket.lib`
++ error.a open.a sig.a env.a str.a fs.a cdb.a byte.a seek_set.o \
++ readclose.o openreadclose.o `cat socket.lib`
++
++cdb:
++ (cd /usr/ports/databases/cdb/work/cdb-0.75 && \
++ make && \
++ cp -p cdb_make.h buffer.h cdb.h uint32.h cdb.a byte.a seek_set.o \
++ cdb_make.o error.c buffer.a unix.a /usr/ports/www/publicfile/work/publicfile-0.52/)
+
+ httpd.o: \
+ compile httpd.c pathdecode.h stralloc.h gen_alloc.h file.h tai.h \
+ uint64.h filetype.h stralloc.h percent.h stralloc.h stralloc.h sig.h \
+ exit.h fmt.h case.h str.h tai.h httpdate.h stralloc.h tai.h \
+-timeoutread.h timeoutwrite.h substdio.h error.h getln.h
++timeoutread.h timeoutwrite.h substdio.h error.h getln.h byte.h
+ ./compile httpd.c
+
+ httpdate.o: \
+@@ -358,6 +380,11 @@
+ compile open_trunc.c open.h
+ ./compile open_trunc.c
+
++openreadclose.o: \
++compile openreadclose.c error.h open.h readclose.h stralloc.h \
++gen_alloc.h openreadclose.h stralloc.h
++ ./compile openreadclose.c
++
+ pathdecode.o: \
+ compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h
+ ./compile pathdecode.c
+@@ -367,7 +394,7 @@
+ ./compile percent.c
+
+ prog: \
+-configure httpd ftpd rts utime
++cdb configure httpd ftpd rts utime htrules
+
+ prot.o: \
+ compile prot.c hasshsgr.h prot.h
+diff -N -u -r publicfile-0.52.orig/README.basicauth publicfile-0.52/README.basicauth
+--- publicfile-0.52.orig/README.basicauth Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/README.basicauth Wed Aug 29 22:16:02 2001
+@@ -0,0 +1,100 @@
++Here is a patch for publicfile to allow for Basic Auth.
++
++Building Instructions:
++
++Save this patch as publicfile-0.52.basicauth.patch
++Download publicfile-0.52
++Download cdb-0.75
++
++gunzip publicfile-0.52.tar
++gunzip cdb-0.75.tar
++tar -xf publicfile-0.52.tar
++cd publicfile-0.52
++tar -xf ../cdb-0.75.tar
++patch -p1 < publicfile-0.52.basicauth.patch
++
++Follow normal installation instructions for publicfile beginning with
++'make setup check'
++
++Usage Instructions:
++
++Once this patch has been applied, httpd will check for a file
++called '.access' in the current directory of any requested
++file. e.g, if /public/file/0/path/to/file.html is requested, httpd
++will first check for /public/file/0/path/to/.access.
++
++.access should have the format:
++ realm_id:realm_txt
++
++realm_id is used as documented below. realm_txt is typically
++presented by the user's browser. .access must be readable by httpd
++and only protects a specific directory. Sub-directories are not
++protected unless they also contain a .access file.
++
++An additional program will be installed in /usr/local/publicfile (or
++whatever conf-home is) called htrules. Use this like tcprules:
++
++cd /public/file
++htrules access.cdb access.tmp < access
++
++This may safely be run at any time.
++
++access should have the format:
++
++ # this is a comment. blank lines are allowed too.
++ # the next line authorizes a user to a specific realm_id
++ realm_id:username:password
++ # the next line authorizes host class.
++ realm_id:LOCALHOST
++
++access.cdb must be readable by httpd.
++
++realm_id corresponds to the realm_id in the .access file(s).
++
++Each realm_id line specifies either a username:password combination
++or a host class. Note that the same username may have different
++passwords in different realm_id's.
++
++A host is mapped into a host class via the environment
++variable HTTPCLIENT. This environment variable should be
++set in tcpserver's rules.cdb.
++
++Here is an example:
++
++ === /public/file/0/private1/.access ===
++ realm1:Dr. Suess
++
++ === /public/file/0/private2/.access ===
++ realm2:Sesame Street
++
++ === /public/file/access ===
++ # realm1 are Dr Suess users/clients
++ realm1:john:catinthehat
++ realm1:mary:greeneggswithham
++ realm1:LOCALHOST
++ realm1:DR SUESS
++ # realm1 are Sesame Street users/clients
++ realm2:tom:bigbird
++ realm2:abi:cookiemonster
++ realm2:mary:earnie
++ realm2:LOCALHOST
++ realm2:SESAME STREET
++
++ === /etc/rules ===
++ 127.0.0.1:allow,HTTPCLIENT="LOCALHOST"
++ 10.0.0.:allow,HTTPCLIENT="DR SUESS"
++ 10.1.0.:allow,HTTPCLIENT="SESAME STREET"
++ :allow
++
++The changes to the Makefile aren't very clean, but everything compiles
++correctly.
++
++Thanks to Eric M. Johnston's for base64.{c,h} from YAQSAP
++(Yet Another qmail SMTP AUTH Patch) -
++http://qmail.goof.com/qmail-auth-20010105.tar.gz
++
++This patch available at
++http://www.soffian.org/downloads/publicfile-0.52_basicauth.patch
++
++Jay Soffian <jay@soffian.org> 29 Aug 2001
++
+diff -N -u -r publicfile-0.52.orig/base64.c publicfile-0.52/base64.c
+--- publicfile-0.52.orig/base64.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/base64.c Wed Aug 22 22:17:39 2001
+@@ -0,0 +1,90 @@
++#include "base64.h"
++#include "stralloc.h"
++#include "substdio.h"
++#include "str.h"
++
++static char *b64alpha =
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
++#define B64PAD '='
++
++/* returns 0 ok, 1 illegal, -1 problem */
++
++int b64decode(in,l,out)
++const unsigned char *in;
++int l;
++stralloc *out; /* not null terminated */
++{
++ int i, j;
++ unsigned char a[4];
++ unsigned char b[3];
++ char *s;
++
++ if (l == 0)
++ {
++ if (!stralloc_copys(out,"")) return -1;
++ return 0;
++ }
++
++ if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */
++ s = out->s;
++
++ for (i = 0;i < l;i += 4) {
++ for (j = 0;j < 4;j++)
++ if ((i + j) < l && in[i + j] != B64PAD)
++ {
++ a[j] = str_chr(b64alpha,in[i + j]);
++ if (a[j] > 63) return 1;
++ }
++ else a[j] = 0;
++
++ b[0] = (a[0] << 2) | (a[1] >> 4);
++ b[1] = (a[1] << 4) | (a[2] >> 2);
++ b[2] = (a[2] << 6) | (a[3]);
++
++ *s++ = b[0];
++
++ if (in[i + 1] == B64PAD) break;
++ *s++ = b[1];
++
++ if (in[i + 2] == B64PAD) break;
++ *s++ = b[2];
++ }
++ out->len = s - out->s;
++ while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */
++ return 0;
++}
++
++int b64encode(in,out)
++stralloc *in;
++stralloc *out; /* not null terminated */
++{
++ unsigned char a, b, c;
++ int i;
++ char *s;
++
++ if (in->len == 0)
++ {
++ if (!stralloc_copys(out,"")) return -1;
++ return 0;
++ }
++
++ if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
++ s = out->s;
++
++ for (i = 0;i < in->len;i += 3) {
++ a = in->s[i];
++ b = i + 1 < in->len ? in->s[i + 1] : 0;
++ c = i + 2 < in->len ? in->s[i + 2] : 0;
++
++ *s++ = b64alpha[a >> 2];
++ *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
++
++ if (i + 1 >= in->len) *s++ = B64PAD;
++ else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
++
++ if (i + 2 >= in->len) *s++ = B64PAD;
++ else *s++ = b64alpha[c & 63];
++ }
++ out->len = s - out->s;
++ return 0;
++}
+diff -N -u -r publicfile-0.52.orig/base64.h publicfile-0.52/base64.h
+--- publicfile-0.52.orig/base64.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/base64.h Wed Aug 22 22:17:39 2001
+@@ -0,0 +1,7 @@
++#ifndef BASE64_H
++#define BASE64_H
++
++extern int b64decode();
++extern int b64encode();
++
++#endif
+diff -N -u -r publicfile-0.52.orig/hier.c publicfile-0.52/hier.c
+--- publicfile-0.52.orig/hier.c Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/hier.c Wed Aug 22 22:17:39 2001
+@@ -7,6 +7,7 @@
+ d(auto_home,"bin",-1,-1,02755);
+
+ c(auto_home,"bin","configure",-1,-1,0755);
++ c(auto_home,"bin","htrules",-1,-1,0755);
+ c(auto_home,"bin","httpd",-1,-1,0755);
+ c(auto_home,"bin","ftpd",-1,-1,0755);
+ }
+diff -N -u -r publicfile-0.52.orig/htrules.c publicfile-0.52/htrules.c
+--- publicfile-0.52.orig/htrules.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/htrules.c Wed Aug 29 21:27:42 2001
+@@ -0,0 +1,117 @@
++#include "strerr.h"
++#include "stralloc.h"
++#include "getln.h"
++#include "buffer.h"
++#include "exit.h"
++#include "fmt.h"
++#include "byte.h"
++#include "base64.h"
++#include "cdb_make.h"
++
++#define FATAL "htrules: fatal: "
++
++unsigned long linenum = 0;
++char *fntemp;
++char *fn;
++
++stralloc line = {0};
++int match = 1;
++
++stralloc base64 = {0};
++stralloc key = {0};
++stralloc realm = {0};
++stralloc userpass = {0};
++
++struct cdb_make c;
++
++void nomem(void)
++{
++ strerr_die2x(111,FATAL,"out of memory");
++}
++void usage(void)
++{
++ strerr_die1x(100,"htrules: usage: htrules access.cdb access.tmp");
++}
++void die_bad(void)
++{
++ if (!stralloc_0(&line)) nomem();
++ strerr_die3x(100,FATAL,"unable to parse this line: ",line.s);
++}
++void die_write(void)
++{
++ strerr_die4sys(111,FATAL,"unable to write to ",fntemp,": ");
++}
++
++main(int argc,char **argv)
++{
++ int colon;
++ char *x;
++ int len;
++ int fd;
++ int i;
++ char ch;
++
++ fn = argv[1];
++ if (!fn) usage();
++ fntemp = argv[2];
++ if (!fntemp) usage();
++
++ fd = open_trunc(fntemp);
++ if (fd == -1)
++ strerr_die4sys(111,FATAL,"unable to create ",fntemp,": ");
++ if (cdb_make_start(&c,fd) == -1) die_write();
++
++ while (match) {
++ if (getln(buffer_0,&line,&match,'\n') == -1)
++ strerr_die2sys(111,FATAL,"unable to read input: ");
++
++ x = line.s; len = line.len;
++
++ if (!len) break;
++ if (x[0] == '#') continue;
++ if (x[0] == '\n') continue;
++
++ while (len) {
++ ch = x[len - 1];
++ if (ch != '\n') if (ch != ' ') if (ch != '\t') break;
++ --len;
++ }
++ line.len = len; /* for die_bad() */
++ if (!len) continue;
++
++ colon = byte_chr(x,len,':');
++ if (!colon || colon == len) die_bad();
++ if (!stralloc_copyb(&realm,x,colon)) nomem();
++ x += colon + 1; len -= colon + 1;
++
++ colon = byte_chr(x,len,':');
++ if (colon == len) {
++ if (!stralloc_copyb(&key,"C",1)) nomem();
++ if (!stralloc_cat(&key,&realm)) nomem();
++ if (!stralloc_catb(&key,":",1)) nomem();
++ if (!stralloc_catb(&key,x,len)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++ } else {
++ if (!stralloc_copyb(&userpass,x,len)) nomem();
++ if (b64encode(&userpass,&base64) == -1) nomem();
++
++ if (!stralloc_copyb(&key,"U",1)) nomem();
++ if (!stralloc_cat(&key,&base64)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++
++ if (!stralloc_copyb(&key,"R",1)) nomem();
++ if (!stralloc_cat(&key,&realm)) nomem();
++ if (!stralloc_catb(&key,":",1)) nomem();
++ if (!stralloc_cat(&key,&base64)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++ }
++ }
++
++ if (cdb_make_finish(&c) == -1) die_write();
++ if (fsync(fd) == -1) die_write();
++ if (close(fd) == -1) die_write(); /* NFS stupidity */
++ if (rename(fntemp,fn))
++ strerr_die6sys(111,FATAL,"unable to move ",fntemp," to ",fn,": ");
++
++ _exit(0);
++}
+diff -N -u -r publicfile-0.52.orig/httpd.c publicfile-0.52/httpd.c
+--- publicfile-0.52.orig/httpd.c Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/httpd.c Wed Aug 29 21:30:34 2001
+@@ -15,6 +15,10 @@
+ #include "substdio.h"
+ #include "error.h"
+ #include "getln.h"
++#include "byte.h"
++#include "cdb.h"
++#include "openreadclose.h"
++#include "env.h"
+
+ int safewrite(int fd,char *buf,int len)
+ {
+@@ -51,6 +55,7 @@
+ stralloc host = {0};
+ stralloc path = {0};
+ stralloc ims = {0};
++stralloc basic_auth = {0};
+ int flagbody = 1;
+
+ char filebuf[1024];
+@@ -75,11 +80,16 @@
+ out_puts("\r\n");
+ }
+
+-void barf(char *code,char *message)
++void barf2(char *code,char *message,char *realm)
+ {
+ if (protocolnum > 0) {
+ tai_now(&now);
+ header(code,message);
++ if(realm) {
++ out_puts("WWW-Authenticate: Basic realm=\"");
++ out_puts(realm);
++ out_puts("\"\r\n");
++ }
+ out_puts("Content-Length: ");
+ out_put(strnum,fmt_ulong(strnum,str_len(message) + 28));
+ out_puts("\r\n");
+@@ -100,8 +110,81 @@
+ _exit(0);
+ }
+
++void barf(char *code,char *message)
++{
++ barf2(code,message,(char *)0);
++}
++
+ stralloc fn = {0};
++stralloc accessfn = {0};
+ stralloc contenttype = {0};
++stralloc realm = {0};
++stralloc realmtxt = {0};
++stralloc key = {0};
++
++void checkauth(void)
++{
++ int len;
++ int fd;
++ int colon;
++ static struct cdb c;
++ char *x;
++
++ len = byte_rchr(fn.s,fn.len,'/');
++ if (!stralloc_copyb(&accessfn,fn.s,len)) _exit(21);
++ if (!stralloc_cats(&accessfn,"/.access")) _exit(21);
++ if (!stralloc_0(&accessfn)) _exit(21);
++
++ if (openreadclose(accessfn.s,&realm,256) == 0) return;
++ if (!realm.len) _exit(23); /* no realm */
++ realm.len = byte_chr(realm.s,realm.len,'\n');
++ while (realm.len) {
++ if (realm.s[realm.len - 1] != ' ')
++ if (realm.s[realm.len - 1] != '\t')
++ break;
++ --realm.len;
++ }
++ colon = byte_chr(realm.s,realm.len,':');
++ if (!colon) _exit(23); /* no realm */
++ if (colon == realm.len) {
++ if (!stralloc_copys(&realmtxt,"restricted access")) _exit(21);
++ } else {
++ if (!stralloc_copyb(&realmtxt,realm.s+colon+1,realm.len-(colon+1))) _exit(21);
++ realm.len = colon;
++ }
++ if (!stralloc_0(&realmtxt)) _exit(21);
++
++ fd = open_read("/access.cdb");
++ if (fd == -1) _exit(23);
++ cdb_init(&c,fd);
++
++ x = env_get("HTTPCLIENT");
++ if (x) {
++ if (!stralloc_copyb(&key,"C",1)) _exit(21);
++ if (!stralloc_cat(&key,&realm)) _exit(21);
++ if (!stralloc_catb(&key,":",1)) _exit(21);
++ if (!stralloc_cats(&key,x)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) == 1) goto AUTH_OK;
++ }
++
++ if (!basic_auth.len) barf2("401 ","Authorization Required", realmtxt.s);
++
++ if (!stralloc_copyb(&key,"U",1)) _exit(21);
++ if (!stralloc_cat(&key,&basic_auth)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) != 1)
++ barf2("401 ","Authorization Required",realmtxt.s);
++
++ if (!stralloc_copyb(&key,"R",1)) _exit(21);
++ if (!stralloc_cat(&key,&realm)) _exit(21);
++ if (!stralloc_catb(&key,":",1)) _exit(21);
++ if (!stralloc_cat(&key,&basic_auth)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) != 1) barf("403 ","Forbidden");
++
++ AUTH_OK:
++ alloc_free(key);
++ cdb_free(&c);
++ close(fd);
++}
+
+ void get(void)
+ {
+@@ -124,6 +207,8 @@
+ if (!stralloc_cat(&fn,&path)) _exit(21);
+ pathdecode(&fn);
+ if (!stralloc_0(&fn)) _exit(21);
++
++ checkauth();
+
+ fd = file_open(fn.s,&mtime,&length,1);
+ if (fd == -1)
+@@ -227,6 +312,7 @@
+ if (!stralloc_copys(&path,"")) _exit(21);
+ if (!stralloc_copys(&protocol,"")) _exit(21);
+ if (!stralloc_copys(&ims,"")) _exit(21);
++ if (!stralloc_copys(&basic_auth,"")) _exit(21);
+ protocolnum = 2;
+
+ spaces = 0;
+@@ -302,6 +388,8 @@
+ if (!stralloc_append(&host,&field.s[i])) _exit(21);
+ if (case_startb(field.s,field.len,"if-modified-since:"))
+ if (!stralloc_copyb(&ims,field.s + 18,field.len - 18)) _exit(21);
++ if (case_startb(field.s,field.len,"authorization: basic "))
++ if (!stralloc_copyb(&basic_auth,field.s + 21,field.len - 21)) _exit(21);
+ field.len = 0;
+ }
+ if (!line.len) break;
+diff -N -u -r publicfile-0.52.orig/openreadclose.c publicfile-0.52/openreadclose.c
+--- publicfile-0.52.orig/openreadclose.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/openreadclose.c Wed Aug 29 14:24:21 2001
+@@ -0,0 +1,18 @@
++/* Public domain. */
++
++#include "error.h"
++#include "open.h"
++#include "readclose.h"
++#include "openreadclose.h"
++
++int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize)
++{
++ int fd;
++ fd = open_read(fn);
++ if (fd == -1) {
++ if (errno == error_noent) return 0;
++ return -1;
++ }
++ if (readclose(fd,sa,bufsize) == -1) return -1;
++ return 1;
++}
+diff -N -u -r publicfile-0.52.orig/openreadclose.h publicfile-0.52/openreadclose.h
+--- publicfile-0.52.orig/openreadclose.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/openreadclose.h Wed Aug 29 14:24:21 2001
+@@ -0,0 +1,10 @@
++/* Public domain. */
++
++#ifndef OPENREADCLOSE_H
++#define OPENREADCLOSE_H
++
++#include "stralloc.h"
++
++extern int openreadclose(const char *,stralloc *,unsigned int);
++
++#endif
+diff -N -u -r publicfile-0.52.orig/readclose.c publicfile-0.52/readclose.c
+--- publicfile-0.52.orig/readclose.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/readclose.c Wed Aug 29 14:30:52 2001
+@@ -0,0 +1,23 @@
++/* Public domain. */
++
++#include <unistd.h>
++#include "error.h"
++#include "readclose.h"
++
++int readclose_append(int fd,stralloc *sa,unsigned int bufsize)
++{
++ int r;
++ for (;;) {
++ if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
++ r = read(fd,sa->s + sa->len,bufsize);
++ if (r == -1) if (errno == error_intr) continue;
++ if (r <= 0) { close(fd); return r; }
++ sa->len += r;
++ }
++}
++
++int readclose(int fd,stralloc *sa,unsigned int bufsize)
++{
++ if (!stralloc_copys(sa,"")) { close(fd); return -1; }
++ return readclose_append(fd,sa,bufsize);
++}
+diff -N -u -r publicfile-0.52.orig/readclose.h publicfile-0.52/readclose.h
+--- publicfile-0.52.orig/readclose.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/readclose.h Wed Aug 29 14:30:52 2001
+@@ -0,0 +1,11 @@
++/* Public domain. */
++
++#ifndef READCLOSE_H
++#define READCLOSE_H
++
++#include "stralloc.h"
++
++extern int readclose_append(int,stralloc *,unsigned int);
++extern int readclose(int,stralloc *,unsigned int);
++
++#endif
diff --git a/www/publicfile/files/publicfile-0.52_basicauth.patch.in b/www/publicfile/files/publicfile-0.52_basicauth.patch.in
new file mode 100644
index 000000000000..170e658d848e
--- /dev/null
+++ b/www/publicfile/files/publicfile-0.52_basicauth.patch.in
@@ -0,0 +1,638 @@
+diff -N -u -r publicfile-0.52.orig/Makefile publicfile-0.52/Makefile
+--- publicfile-0.52.orig/Makefile Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/Makefile Wed Aug 29 20:27:09 2001
+@@ -234,21 +234,43 @@
+ compile hier.c auto_home.h
+ ./compile hier.c
+
++htrules: \
++load htrules.o base64.o
++ ./load htrules cdb.a base64.o byte.a getln.a stralloc.a alloc.a \
++ substdio.a str.a buffer.a unix.a
++
++htrules.o: \
++compile htrules.c strerr.h stralloc.h gen_alloc.h getln.h buffer.h \
++stralloc.h buffer.h exit.h fmt.h byte.h cdb_make.h buffer.h uint32.h \
++base64.h
++ ./compile htrules.c
++
++base64.o: \
++compile base64.c base64.h
++ ./compile base64.c
++
+ httpd: \
+ load httpd.o main.o pathdecode.o file.o filetype.o httpdate.o \
+ percent.o prot.o timeoutread.o timeoutwrite.o libtai.a case.a getln.a \
+ stralloc.a alloc.a substdio.a error.a open.a sig.a env.a str.a fs.a \
+-socket.lib
++socket.lib readclose.o openreadclose.o
+ ./load httpd main.o pathdecode.o file.o filetype.o \
+ httpdate.o percent.o prot.o timeoutread.o timeoutwrite.o \
+ libtai.a case.a getln.a stralloc.a alloc.a substdio.a \
+- error.a open.a sig.a env.a str.a fs.a `cat socket.lib`
++ error.a open.a sig.a env.a str.a fs.a cdb.a byte.a seek_set.o \
++ readclose.o openreadclose.o `cat socket.lib`
++
++cdb:
++ (cd __PORTSDIR__/databases/cdb/work/cdb-0.75 && \
++ make && \
++ cp -p cdb_make.h buffer.h cdb.h uint32.h cdb.a byte.a seek_set.o \
++ cdb_make.o error.c buffer.a unix.a __WRKSRC__/)
+
+ httpd.o: \
+ compile httpd.c pathdecode.h stralloc.h gen_alloc.h file.h tai.h \
+ uint64.h filetype.h stralloc.h percent.h stralloc.h stralloc.h sig.h \
+ exit.h fmt.h case.h str.h tai.h httpdate.h stralloc.h tai.h \
+-timeoutread.h timeoutwrite.h substdio.h error.h getln.h
++timeoutread.h timeoutwrite.h substdio.h error.h getln.h byte.h
+ ./compile httpd.c
+
+ httpdate.o: \
+@@ -358,6 +380,11 @@
+ compile open_trunc.c open.h
+ ./compile open_trunc.c
+
++openreadclose.o: \
++compile openreadclose.c error.h open.h readclose.h stralloc.h \
++gen_alloc.h openreadclose.h stralloc.h
++ ./compile openreadclose.c
++
+ pathdecode.o: \
+ compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h
+ ./compile pathdecode.c
+@@ -367,7 +394,7 @@
+ ./compile percent.c
+
+ prog: \
+-configure httpd ftpd rts utime
++cdb configure httpd ftpd rts utime htrules
+
+ prot.o: \
+ compile prot.c hasshsgr.h prot.h
+diff -N -u -r publicfile-0.52.orig/README.basicauth publicfile-0.52/README.basicauth
+--- publicfile-0.52.orig/README.basicauth Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/README.basicauth Wed Aug 29 22:16:02 2001
+@@ -0,0 +1,100 @@
++Here is a patch for publicfile to allow for Basic Auth.
++
++Building Instructions:
++
++Save this patch as publicfile-0.52.basicauth.patch
++Download publicfile-0.52
++Download cdb-0.75
++
++gunzip publicfile-0.52.tar
++gunzip cdb-0.75.tar
++tar -xf publicfile-0.52.tar
++cd publicfile-0.52
++tar -xf ../cdb-0.75.tar
++patch -p1 < publicfile-0.52.basicauth.patch
++
++Follow normal installation instructions for publicfile beginning with
++'make setup check'
++
++Usage Instructions:
++
++Once this patch has been applied, httpd will check for a file
++called '.access' in the current directory of any requested
++file. e.g, if /public/file/0/path/to/file.html is requested, httpd
++will first check for /public/file/0/path/to/.access.
++
++.access should have the format:
++ realm_id:realm_txt
++
++realm_id is used as documented below. realm_txt is typically
++presented by the user's browser. .access must be readable by httpd
++and only protects a specific directory. Sub-directories are not
++protected unless they also contain a .access file.
++
++An additional program will be installed in /usr/local/publicfile (or
++whatever conf-home is) called htrules. Use this like tcprules:
++
++cd /public/file
++htrules access.cdb access.tmp < access
++
++This may safely be run at any time.
++
++access should have the format:
++
++ # this is a comment. blank lines are allowed too.
++ # the next line authorizes a user to a specific realm_id
++ realm_id:username:password
++ # the next line authorizes host class.
++ realm_id:LOCALHOST
++
++access.cdb must be readable by httpd.
++
++realm_id corresponds to the realm_id in the .access file(s).
++
++Each realm_id line specifies either a username:password combination
++or a host class. Note that the same username may have different
++passwords in different realm_id's.
++
++A host is mapped into a host class via the environment
++variable HTTPCLIENT. This environment variable should be
++set in tcpserver's rules.cdb.
++
++Here is an example:
++
++ === /public/file/0/private1/.access ===
++ realm1:Dr. Suess
++
++ === /public/file/0/private2/.access ===
++ realm2:Sesame Street
++
++ === /public/file/access ===
++ # realm1 are Dr Suess users/clients
++ realm1:john:catinthehat
++ realm1:mary:greeneggswithham
++ realm1:LOCALHOST
++ realm1:DR SUESS
++ # realm1 are Sesame Street users/clients
++ realm2:tom:bigbird
++ realm2:abi:cookiemonster
++ realm2:mary:earnie
++ realm2:LOCALHOST
++ realm2:SESAME STREET
++
++ === /etc/rules ===
++ 127.0.0.1:allow,HTTPCLIENT="LOCALHOST"
++ 10.0.0.:allow,HTTPCLIENT="DR SUESS"
++ 10.1.0.:allow,HTTPCLIENT="SESAME STREET"
++ :allow
++
++The changes to the Makefile aren't very clean, but everything compiles
++correctly.
++
++Thanks to Eric M. Johnston's for base64.{c,h} from YAQSAP
++(Yet Another qmail SMTP AUTH Patch) -
++http://qmail.goof.com/qmail-auth-20010105.tar.gz
++
++This patch available at
++http://www.soffian.org/downloads/publicfile-0.52_basicauth.patch
++
++Jay Soffian <jay@soffian.org> 29 Aug 2001
++
+diff -N -u -r publicfile-0.52.orig/base64.c publicfile-0.52/base64.c
+--- publicfile-0.52.orig/base64.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/base64.c Wed Aug 22 22:17:39 2001
+@@ -0,0 +1,90 @@
++#include "base64.h"
++#include "stralloc.h"
++#include "substdio.h"
++#include "str.h"
++
++static char *b64alpha =
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
++#define B64PAD '='
++
++/* returns 0 ok, 1 illegal, -1 problem */
++
++int b64decode(in,l,out)
++const unsigned char *in;
++int l;
++stralloc *out; /* not null terminated */
++{
++ int i, j;
++ unsigned char a[4];
++ unsigned char b[3];
++ char *s;
++
++ if (l == 0)
++ {
++ if (!stralloc_copys(out,"")) return -1;
++ return 0;
++ }
++
++ if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */
++ s = out->s;
++
++ for (i = 0;i < l;i += 4) {
++ for (j = 0;j < 4;j++)
++ if ((i + j) < l && in[i + j] != B64PAD)
++ {
++ a[j] = str_chr(b64alpha,in[i + j]);
++ if (a[j] > 63) return 1;
++ }
++ else a[j] = 0;
++
++ b[0] = (a[0] << 2) | (a[1] >> 4);
++ b[1] = (a[1] << 4) | (a[2] >> 2);
++ b[2] = (a[2] << 6) | (a[3]);
++
++ *s++ = b[0];
++
++ if (in[i + 1] == B64PAD) break;
++ *s++ = b[1];
++
++ if (in[i + 2] == B64PAD) break;
++ *s++ = b[2];
++ }
++ out->len = s - out->s;
++ while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */
++ return 0;
++}
++
++int b64encode(in,out)
++stralloc *in;
++stralloc *out; /* not null terminated */
++{
++ unsigned char a, b, c;
++ int i;
++ char *s;
++
++ if (in->len == 0)
++ {
++ if (!stralloc_copys(out,"")) return -1;
++ return 0;
++ }
++
++ if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
++ s = out->s;
++
++ for (i = 0;i < in->len;i += 3) {
++ a = in->s[i];
++ b = i + 1 < in->len ? in->s[i + 1] : 0;
++ c = i + 2 < in->len ? in->s[i + 2] : 0;
++
++ *s++ = b64alpha[a >> 2];
++ *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
++
++ if (i + 1 >= in->len) *s++ = B64PAD;
++ else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
++
++ if (i + 2 >= in->len) *s++ = B64PAD;
++ else *s++ = b64alpha[c & 63];
++ }
++ out->len = s - out->s;
++ return 0;
++}
+diff -N -u -r publicfile-0.52.orig/base64.h publicfile-0.52/base64.h
+--- publicfile-0.52.orig/base64.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/base64.h Wed Aug 22 22:17:39 2001
+@@ -0,0 +1,7 @@
++#ifndef BASE64_H
++#define BASE64_H
++
++extern int b64decode();
++extern int b64encode();
++
++#endif
+diff -N -u -r publicfile-0.52.orig/hier.c publicfile-0.52/hier.c
+--- publicfile-0.52.orig/hier.c Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/hier.c Wed Aug 22 22:17:39 2001
+@@ -7,6 +7,7 @@
+ d(auto_home,"bin",-1,-1,02755);
+
+ c(auto_home,"bin","configure",-1,-1,0755);
++ c(auto_home,"bin","htrules",-1,-1,0755);
+ c(auto_home,"bin","httpd",-1,-1,0755);
+ c(auto_home,"bin","ftpd",-1,-1,0755);
+ }
+diff -N -u -r publicfile-0.52.orig/htrules.c publicfile-0.52/htrules.c
+--- publicfile-0.52.orig/htrules.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/htrules.c Wed Aug 29 21:27:42 2001
+@@ -0,0 +1,117 @@
++#include "strerr.h"
++#include "stralloc.h"
++#include "getln.h"
++#include "buffer.h"
++#include "exit.h"
++#include "fmt.h"
++#include "byte.h"
++#include "base64.h"
++#include "cdb_make.h"
++
++#define FATAL "htrules: fatal: "
++
++unsigned long linenum = 0;
++char *fntemp;
++char *fn;
++
++stralloc line = {0};
++int match = 1;
++
++stralloc base64 = {0};
++stralloc key = {0};
++stralloc realm = {0};
++stralloc userpass = {0};
++
++struct cdb_make c;
++
++void nomem(void)
++{
++ strerr_die2x(111,FATAL,"out of memory");
++}
++void usage(void)
++{
++ strerr_die1x(100,"htrules: usage: htrules access.cdb access.tmp");
++}
++void die_bad(void)
++{
++ if (!stralloc_0(&line)) nomem();
++ strerr_die3x(100,FATAL,"unable to parse this line: ",line.s);
++}
++void die_write(void)
++{
++ strerr_die4sys(111,FATAL,"unable to write to ",fntemp,": ");
++}
++
++main(int argc,char **argv)
++{
++ int colon;
++ char *x;
++ int len;
++ int fd;
++ int i;
++ char ch;
++
++ fn = argv[1];
++ if (!fn) usage();
++ fntemp = argv[2];
++ if (!fntemp) usage();
++
++ fd = open_trunc(fntemp);
++ if (fd == -1)
++ strerr_die4sys(111,FATAL,"unable to create ",fntemp,": ");
++ if (cdb_make_start(&c,fd) == -1) die_write();
++
++ while (match) {
++ if (getln(buffer_0,&line,&match,'\n') == -1)
++ strerr_die2sys(111,FATAL,"unable to read input: ");
++
++ x = line.s; len = line.len;
++
++ if (!len) break;
++ if (x[0] == '#') continue;
++ if (x[0] == '\n') continue;
++
++ while (len) {
++ ch = x[len - 1];
++ if (ch != '\n') if (ch != ' ') if (ch != '\t') break;
++ --len;
++ }
++ line.len = len; /* for die_bad() */
++ if (!len) continue;
++
++ colon = byte_chr(x,len,':');
++ if (!colon || colon == len) die_bad();
++ if (!stralloc_copyb(&realm,x,colon)) nomem();
++ x += colon + 1; len -= colon + 1;
++
++ colon = byte_chr(x,len,':');
++ if (colon == len) {
++ if (!stralloc_copyb(&key,"C",1)) nomem();
++ if (!stralloc_cat(&key,&realm)) nomem();
++ if (!stralloc_catb(&key,":",1)) nomem();
++ if (!stralloc_catb(&key,x,len)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++ } else {
++ if (!stralloc_copyb(&userpass,x,len)) nomem();
++ if (b64encode(&userpass,&base64) == -1) nomem();
++
++ if (!stralloc_copyb(&key,"U",1)) nomem();
++ if (!stralloc_cat(&key,&base64)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++
++ if (!stralloc_copyb(&key,"R",1)) nomem();
++ if (!stralloc_cat(&key,&realm)) nomem();
++ if (!stralloc_catb(&key,":",1)) nomem();
++ if (!stralloc_cat(&key,&base64)) nomem();
++ if (cdb_make_add(&c,key.s,key.len,"",0) == -1) die_write();
++ }
++ }
++
++ if (cdb_make_finish(&c) == -1) die_write();
++ if (fsync(fd) == -1) die_write();
++ if (close(fd) == -1) die_write(); /* NFS stupidity */
++ if (rename(fntemp,fn))
++ strerr_die6sys(111,FATAL,"unable to move ",fntemp," to ",fn,": ");
++
++ _exit(0);
++}
+diff -N -u -r publicfile-0.52.orig/httpd.c publicfile-0.52/httpd.c
+--- publicfile-0.52.orig/httpd.c Mon Nov 8 23:23:46 1999
++++ publicfile-0.52/httpd.c Wed Aug 29 21:30:34 2001
+@@ -15,6 +15,10 @@
+ #include "substdio.h"
+ #include "error.h"
+ #include "getln.h"
++#include "byte.h"
++#include "cdb.h"
++#include "openreadclose.h"
++#include "env.h"
+
+ int safewrite(int fd,char *buf,int len)
+ {
+@@ -51,6 +55,7 @@
+ stralloc host = {0};
+ stralloc path = {0};
+ stralloc ims = {0};
++stralloc basic_auth = {0};
+ int flagbody = 1;
+
+ char filebuf[1024];
+@@ -75,11 +80,16 @@
+ out_puts("\r\n");
+ }
+
+-void barf(char *code,char *message)
++void barf2(char *code,char *message,char *realm)
+ {
+ if (protocolnum > 0) {
+ tai_now(&now);
+ header(code,message);
++ if(realm) {
++ out_puts("WWW-Authenticate: Basic realm=\"");
++ out_puts(realm);
++ out_puts("\"\r\n");
++ }
+ out_puts("Content-Length: ");
+ out_put(strnum,fmt_ulong(strnum,str_len(message) + 28));
+ out_puts("\r\n");
+@@ -100,8 +110,81 @@
+ _exit(0);
+ }
+
++void barf(char *code,char *message)
++{
++ barf2(code,message,(char *)0);
++}
++
+ stralloc fn = {0};
++stralloc accessfn = {0};
+ stralloc contenttype = {0};
++stralloc realm = {0};
++stralloc realmtxt = {0};
++stralloc key = {0};
++
++void checkauth(void)
++{
++ int len;
++ int fd;
++ int colon;
++ static struct cdb c;
++ char *x;
++
++ len = byte_rchr(fn.s,fn.len,'/');
++ if (!stralloc_copyb(&accessfn,fn.s,len)) _exit(21);
++ if (!stralloc_cats(&accessfn,"/.access")) _exit(21);
++ if (!stralloc_0(&accessfn)) _exit(21);
++
++ if (openreadclose(accessfn.s,&realm,256) == 0) return;
++ if (!realm.len) _exit(23); /* no realm */
++ realm.len = byte_chr(realm.s,realm.len,'\n');
++ while (realm.len) {
++ if (realm.s[realm.len - 1] != ' ')
++ if (realm.s[realm.len - 1] != '\t')
++ break;
++ --realm.len;
++ }
++ colon = byte_chr(realm.s,realm.len,':');
++ if (!colon) _exit(23); /* no realm */
++ if (colon == realm.len) {
++ if (!stralloc_copys(&realmtxt,"restricted access")) _exit(21);
++ } else {
++ if (!stralloc_copyb(&realmtxt,realm.s+colon+1,realm.len-(colon+1))) _exit(21);
++ realm.len = colon;
++ }
++ if (!stralloc_0(&realmtxt)) _exit(21);
++
++ fd = open_read("/access.cdb");
++ if (fd == -1) _exit(23);
++ cdb_init(&c,fd);
++
++ x = env_get("HTTPCLIENT");
++ if (x) {
++ if (!stralloc_copyb(&key,"C",1)) _exit(21);
++ if (!stralloc_cat(&key,&realm)) _exit(21);
++ if (!stralloc_catb(&key,":",1)) _exit(21);
++ if (!stralloc_cats(&key,x)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) == 1) goto AUTH_OK;
++ }
++
++ if (!basic_auth.len) barf2("401 ","Authorization Required", realmtxt.s);
++
++ if (!stralloc_copyb(&key,"U",1)) _exit(21);
++ if (!stralloc_cat(&key,&basic_auth)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) != 1)
++ barf2("401 ","Authorization Required",realmtxt.s);
++
++ if (!stralloc_copyb(&key,"R",1)) _exit(21);
++ if (!stralloc_cat(&key,&realm)) _exit(21);
++ if (!stralloc_catb(&key,":",1)) _exit(21);
++ if (!stralloc_cat(&key,&basic_auth)) _exit(21);
++ if (cdb_find(&c,key.s,key.len) != 1) barf("403 ","Forbidden");
++
++ AUTH_OK:
++ alloc_free(key);
++ cdb_free(&c);
++ close(fd);
++}
+
+ void get(void)
+ {
+@@ -124,6 +207,8 @@
+ if (!stralloc_cat(&fn,&path)) _exit(21);
+ pathdecode(&fn);
+ if (!stralloc_0(&fn)) _exit(21);
++
++ checkauth();
+
+ fd = file_open(fn.s,&mtime,&length,1);
+ if (fd == -1)
+@@ -227,6 +312,7 @@
+ if (!stralloc_copys(&path,"")) _exit(21);
+ if (!stralloc_copys(&protocol,"")) _exit(21);
+ if (!stralloc_copys(&ims,"")) _exit(21);
++ if (!stralloc_copys(&basic_auth,"")) _exit(21);
+ protocolnum = 2;
+
+ spaces = 0;
+@@ -302,6 +388,8 @@
+ if (!stralloc_append(&host,&field.s[i])) _exit(21);
+ if (case_startb(field.s,field.len,"if-modified-since:"))
+ if (!stralloc_copyb(&ims,field.s + 18,field.len - 18)) _exit(21);
++ if (case_startb(field.s,field.len,"authorization: basic "))
++ if (!stralloc_copyb(&basic_auth,field.s + 21,field.len - 21)) _exit(21);
+ field.len = 0;
+ }
+ if (!line.len) break;
+diff -N -u -r publicfile-0.52.orig/openreadclose.c publicfile-0.52/openreadclose.c
+--- publicfile-0.52.orig/openreadclose.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/openreadclose.c Wed Aug 29 14:24:21 2001
+@@ -0,0 +1,18 @@
++/* Public domain. */
++
++#include "error.h"
++#include "open.h"
++#include "readclose.h"
++#include "openreadclose.h"
++
++int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize)
++{
++ int fd;
++ fd = open_read(fn);
++ if (fd == -1) {
++ if (errno == error_noent) return 0;
++ return -1;
++ }
++ if (readclose(fd,sa,bufsize) == -1) return -1;
++ return 1;
++}
+diff -N -u -r publicfile-0.52.orig/openreadclose.h publicfile-0.52/openreadclose.h
+--- publicfile-0.52.orig/openreadclose.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/openreadclose.h Wed Aug 29 14:24:21 2001
+@@ -0,0 +1,10 @@
++/* Public domain. */
++
++#ifndef OPENREADCLOSE_H
++#define OPENREADCLOSE_H
++
++#include "stralloc.h"
++
++extern int openreadclose(const char *,stralloc *,unsigned int);
++
++#endif
+diff -N -u -r publicfile-0.52.orig/readclose.c publicfile-0.52/readclose.c
+--- publicfile-0.52.orig/readclose.c Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/readclose.c Wed Aug 29 14:30:52 2001
+@@ -0,0 +1,23 @@
++/* Public domain. */
++
++#include <unistd.h>
++#include "error.h"
++#include "readclose.h"
++
++int readclose_append(int fd,stralloc *sa,unsigned int bufsize)
++{
++ int r;
++ for (;;) {
++ if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
++ r = read(fd,sa->s + sa->len,bufsize);
++ if (r == -1) if (errno == error_intr) continue;
++ if (r <= 0) { close(fd); return r; }
++ sa->len += r;
++ }
++}
++
++int readclose(int fd,stralloc *sa,unsigned int bufsize)
++{
++ if (!stralloc_copys(sa,"")) { close(fd); return -1; }
++ return readclose_append(fd,sa,bufsize);
++}
+diff -N -u -r publicfile-0.52.orig/readclose.h publicfile-0.52/readclose.h
+--- publicfile-0.52.orig/readclose.h Wed Dec 31 16:00:00 1969
++++ publicfile-0.52/readclose.h Wed Aug 29 14:30:52 2001
+@@ -0,0 +1,11 @@
++/* Public domain. */
++
++#ifndef READCLOSE_H
++#define READCLOSE_H
++
++#include "stralloc.h"
++
++extern int readclose_append(int,stralloc *,unsigned int);
++extern int readclose(int,stralloc *,unsigned int);
++
++#endif
diff --git a/www/publicfile/files/publicfile.sslserver b/www/publicfile/files/publicfile.sslserver
new file mode 100644
index 000000000000..23b3c8778141
--- /dev/null
+++ b/www/publicfile/files/publicfile.sslserver
@@ -0,0 +1,36 @@
+--- httpd.c.orig Tue Nov 9 02:23:46 1999
++++ httpd.c Sun Dec 9 21:30:59 2001
+@@ -271,8 +271,16 @@
+ if (!stralloc_copyb(&path,host.s + i,host.len - i)) _exit(21);
+ host.len = i;
+ }
+- else
+- if (!stralloc_copy(&path,&url)) _exit(21);
++ else {
++ if (case_startb(url.s,url.len,"https://")) {
++ if (!stralloc_copyb(&host,url.s + 8,url.len - 8)) _exit(21);
++ i = byte_chr(host.s,host.len,'/');
++ if (!stralloc_copyb(&path,host.s + i,host.len - i)) _exit(21);
++ host.len = i;
++ }
++ else
++ if (!stralloc_copy(&path,&url)) _exit(21);
++ }
+
+ if (!path.len || (path.s[path.len - 1] == '/'))
+ if (!stralloc_cats(&path,"index.html")) _exit(21);
+--- file.c.orig Wed Dec 12 07:09:57 2001
++++ file.c Wed Dec 12 07:09:33 2001
+@@ -15,7 +15,11 @@
+ char *x;
+
+ x = env_get("TCPREMOTEIP");
+- if (!x) x = "0";
++ if (!x) {
++ x = env_get("SSLREMOTEIP");
++ if (!x)
++ x = "0";
++ }
+ substdio_puts(subfderr,x);
+ substdio_puts(subfderr,flagread ? " read ": " dir ");
+
diff --git a/www/publicfile/files/redirect-slash-patch b/www/publicfile/files/redirect-slash-patch
new file mode 100644
index 000000000000..38c936cae8e6
--- /dev/null
+++ b/www/publicfile/files/redirect-slash-patch
@@ -0,0 +1,217 @@
+From: Giles Lean <giles@nemeton.com.au>
+To: publicfile@list.cr.yp.to
+Subject: redirect patch for publicfile-0.52
+Date: Sun, 05 Dec 1999 08:43:14 +1100
+
+------- =_aaaaaaaaaa0
+Content-Type: text/plain; charset="us-ascii"
+Content-ID: <23894.944342900.1@nemeton.com.au>
+
+I have a patch for publicfile-0.52 that will make it send redirects
+instead of "404 access denied" when directories are requested
+without a trailing slash.
+
+Comments and suggestions are welcome, particularly if someone can
+see where I've either done something wrong protocol-wise or if the
+integration with Dan's code can be improved.
+
+This patch is only appropriate for publicfile installations where
+an existing server is being replaced or where lots of third party
+HTML is installed without editing. This is not the target market
+Dan Bernstein claims for publicfile, but some of us will use it
+anyway. (My #1 reason? The low memory requirement.)
+
+After this patch is applied log messages about "is a directory"
+will show up if the redirect code is used:
+
+@4000000038490b1f26a03cac 127.0.0.1 read ./localhost.nemeton.com.au/cr.yp.to/publicfile: is a directory
+@40000000384973483712ee2c 127.0.0.1 read ./localhost.nemeton.com.au/susv2: is a directory
+
+Regards,
+
+Giles
+
+
+------- =_aaaaaaaaaa0
+Content-Type: text/plain; name="diff"; charset="us-ascii"
+Content-ID: <23894.944342900.2@nemeton.com.au>
+
+Index: error.c
+===================================================================
+RCS file: /a/CVS/net/publicfile/error.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.1.2.1
+diff -c -r1.1.1.1 -r1.1.1.1.2.1
+*** error.c 1999/12/01 19:38:15 1.1.1.1
+--- error.c 1999/12/04 21:15:37 1.1.1.1.2.1
+***************
+*** 100,102 ****
+--- 100,109 ----
+ #else
+ -14;
+ #endif
++
++ int error_isdir =
++ #ifdef EISDIR
++ EISDIR;
++ #else
++ -15;
++ #endif
+Index: error.h
+===================================================================
+RCS file: /a/CVS/net/publicfile/error.h,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.1.2.1
+diff -c -r1.1.1.1 -r1.1.1.1.2.1
+*** error.h 1999/12/01 19:38:15 1.1.1.1
+--- error.h 1999/12/04 21:15:37 1.1.1.1.2.1
+***************
+*** 17,22 ****
+--- 17,23 ----
+ extern int error_perm;
+ extern int error_acces;
+ extern int error_nodevice;
++ extern int error_isdir;
+
+ extern char *error_str();
+ extern int error_temp();
+Index: error_str.c
+===================================================================
+RCS file: /a/CVS/net/publicfile/error_str.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.1.2.1
+diff -c -r1.1.1.1 -r1.1.1.1.2.1
+*** error_str.c 1999/12/01 19:38:15 1.1.1.1
+--- error_str.c 1999/12/04 21:15:38 1.1.1.1.2.1
+***************
+*** 21,26 ****
+--- 21,27 ----
+ X(error_perm,"permission denied")
+ X(error_acces,"access denied")
+ X(error_nodevice,"device not configured")
++ X(error_isdir,"is a directory")
+ #ifdef ESRCH
+ X(ESRCH,"no such process")
+ #endif
+Index: file.c
+===================================================================
+RCS file: /a/CVS/net/publicfile/file.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.1.2.1
+diff -c -r1.1.1.1 -r1.1.1.1.2.1
+*** file.c 1999/12/01 19:38:14 1.1.1.1
+--- file.c 1999/12/04 21:15:38 1.1.1.1.2.1
+***************
+*** 65,77 ****
+ errno = error_acces;
+ return -1;
+ }
+! if (flagread)
+! if ((st.st_mode & S_IFMT) != S_IFREG) {
+ log(fn,": ","not a regular file",flagread);
+ close(fd);
+ errno = error_acces;
+- return -1;
+ }
+
+ log(fn,": ","success",flagread);
+
+--- 65,83 ----
+ errno = error_acces;
+ return -1;
+ }
+! if (flagread && (st.st_mode & S_IFMT) != S_IFREG) {
+! if ((st.st_mode & S_IFMT) == S_IFDIR) {
+! log(fn,": ",error_str(error_isdir),flagread);
+! close(fd);
+! errno = error_isdir;
+! }
+! else {
+ log(fn,": ","not a regular file",flagread);
+ close(fd);
+ errno = error_acces;
+ }
++ return -1;
++ }
+
+ log(fn,": ","success",flagread);
+
+Index: httpd.c
+===================================================================
+RCS file: /a/CVS/net/publicfile/httpd.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.1.2.1
+diff -c -r1.1.1.1 -r1.1.1.1.2.1
+*** httpd.c 1999/12/01 19:38:14 1.1.1.1
+--- httpd.c 1999/12/04 21:15:38 1.1.1.1.2.1
+***************
+*** 103,114 ****
+--- 103,142 ----
+ stralloc fn = {0};
+ stralloc contenttype = {0};
+
++ void redirect(void)
++ {
++ if (!stralloc_cats(&url, "/")) _exit(21);
++ if (protocolnum > 0) {
++ tai_now(&now);
++ header("301 ", "Moved Permanently");
++ out_puts("Content-Length: ");
++ out_put(strnum,fmt_ulong(strnum,url.len * 2 + 127));
++ out_puts("\r\nLocation: ");
++ out_put(url.s, url.len);
++ out_puts("\r\nContent-Type: text/html\r\n\r\n");
++ }
++ if (flagbody) {
++ out_puts("<html><body>The document you requested is a directory. Try adding a trailing slash to the URL: <A HREF=\"");
++ out_put(url.s,url.len);
++ out_puts("\">");
++ out_put(url.s,url.len);
++ out_puts("</A></body></html>\r\n");
++ }
++ out_flush();
++ }
++
+ void get(void)
+ {
+ unsigned long length;
+ int fd;
+ int r;
+
++ if (!case_startb(url.s,url.len,"http://")) {
++ if (!stralloc_copys(&url,"http://")) _exit(21);
++ if (!stralloc_cat(&url,&host)) _exit(21);
++ if (!stralloc_cat(&url,&path)) _exit(21);
++ }
++
+ host.len = byte_chr(host.s,host.len,':');
+ if (!host.len) {
+ if (protocolnum > 1)
+***************
+*** 126,133 ****
+ if (!stralloc_0(&fn)) _exit(21);
+
+ fd = file_open(fn.s,&mtime,&length,1);
+! if (fd == -1)
+ barf("404 ",error_str(errno));
+
+ if (protocolnum > 0) {
+ tai_now(&now);
+--- 154,167 ----
+ if (!stralloc_0(&fn)) _exit(21);
+
+ fd = file_open(fn.s,&mtime,&length,1);
+! if (fd == -1) {
+! if (errno == error_isdir) {
+! redirect();
+! if (protocolnum < 2) _exit(0);
+! return;
+! }
+ barf("404 ",error_str(errno));
++ }
+
+ if (protocolnum > 0) {
+ tai_now(&now);
+
+------- =_aaaaaaaaaa0--
+
diff --git a/www/publicfile/pkg-plist b/www/publicfile/pkg-plist
index 6a48a1edaf35..8b7b66177460 100644
--- a/www/publicfile/pkg-plist
+++ b/www/publicfile/pkg-plist
@@ -1,3 +1,4 @@
bin/configure
bin/httpd
bin/ftpd
+%%BASICAUTH%%bin/htrules