ports/76556: Update: www/publicfile optional patches

David Thiel lx at redundancy.redundancy.org
Sat Jan 22 00:40:31 UTC 2005


>Number:         76556
>Category:       ports
>Synopsis:       Update: www/publicfile optional patches
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jan 22 00:40:21 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     David Thiel
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
>Environment:
System: FreeBSD redundancy.redundancy.org 5.3-STABLE FreeBSD 5.3-STABLE #0: Sun Jan 9 21:41:16 PST 2005 root at redundancy.redundancy.org:/usr/obj/usr/src/sys/REDUNDANCY i386

>Description:

Adding the following optional patches to publicfile, djb's web/ftp server:

WITH_BASICAUTH - basic HTTP authentication support
WITH_COMMONLOG - support for Apache common log format
WITH_REDIRECT_SLASH - don't complain when omitting trailing slash
WITH_SSL - provide SSL support through ucspi-ssl

Also, take maintainership of the port.

>How-To-Repeat:
>Fix:

diff -ruN publicfile/Makefile publicfile.new/Makefile
--- publicfile/Makefile	Tue Apr 20 01:33:16 2004
+++ publicfile.new/Makefile	Fri Jan 21 16:28:59 2005
@@ -7,19 +7,85 @@
 
 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 at FreeBSD.org
+MAINTAINER=	lx at redundancy.redundancy.org
 COMMENT=	A secure, read-only, anonymous HTTP/FTP server
 
 RUN_DEPENDS=	setuidgid:${PORTSDIR}/sysutils/daemontools \
 		tcpserver:${PORTSDIR}/sysutils/ucspi-tcp
 
+pre-everything::
+
+	@${ECHO_MSG}
+	@${ECHO_MSG} "This port can use the following tuneables:"
+	@${ECHO_MSG}
+	@${ECHO_MSG} "WITH_BASICAUTH 		basic HTTP authentication support"
+	@${ECHO_MSG} "WITH_COMMONLOG 		support for Apache common log format"
+	@${ECHO_MSG} "WITH_REDIRECT_SLASH 	don't complain when omitting trailing slash"
+	@${ECHO_MSG} "WITH_SSL 		provide SSL support through ucspi-ssl"
+	@${ECHO_MSG}
+
+.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
diff -ruN publicfile/distinfo publicfile.new/distinfo
--- publicfile/distinfo	Fri Jan 28 08:41:09 2000
+++ publicfile.new/distinfo	Tue Jan  4 11:12:19 2005
@@ -1 +1,2 @@
 MD5 (publicfile-0.52.tar.gz) = e493d69627b4fb2c7c764c0ff34330d7
+SIZE (publicfile-0.52.tar.gz) = 34892
diff -ruN publicfile/files/publicfile-0.52-commonlog-2.patch publicfile.new/files/publicfile-0.52-commonlog-2.patch
--- publicfile/files/publicfile-0.52-commonlog-2.patch	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/publicfile-0.52-commonlog-2.patch	Tue Jan  4 11:11:47 2005
@@ -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 -ruN publicfile/files/publicfile-0.52-filetype-diff publicfile.new/files/publicfile-0.52-filetype-diff
--- publicfile/files/publicfile-0.52-filetype-diff	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/publicfile-0.52-filetype-diff	Tue Jan  4 11:11:47 2005
@@ -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 -ruN publicfile/files/publicfile-0.52_basicauth.patch publicfile.new/files/publicfile-0.52_basicauth.patch
--- publicfile/files/publicfile-0.52_basicauth.patch	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/publicfile-0.52_basicauth.patch	Thu Jan  6 14:41:18 2005
@@ -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.new/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 at 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 -ruN publicfile/files/publicfile-0.52_basicauth.patch.in publicfile.new/files/publicfile-0.52_basicauth.patch.in
--- publicfile/files/publicfile-0.52_basicauth.patch.in	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/publicfile-0.52_basicauth.patch.in	Tue Jan  4 11:24:01 2005
@@ -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 at 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 -ruN publicfile/files/publicfile.sslserver publicfile.new/files/publicfile.sslserver
--- publicfile/files/publicfile.sslserver	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/publicfile.sslserver	Tue Jan  4 11:11:47 2005
@@ -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 -ruN publicfile/files/redirect-slash-patch publicfile.new/files/redirect-slash-patch
--- publicfile/files/redirect-slash-patch	Wed Dec 31 16:00:00 1969
+++ publicfile.new/files/redirect-slash-patch	Tue Jan  4 11:17:13 2005
@@ -0,0 +1,217 @@
+From: Giles Lean <giles at nemeton.com.au>
+To: publicfile at 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 at 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:
+
+ at 4000000038490b1f26a03cac 127.0.0.1 read ./localhost.nemeton.com.au/cr.yp.to/publicfile: is a directory
+ at 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 at 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 -ruN publicfile/pkg-plist publicfile.new/pkg-plist
--- publicfile/pkg-plist	Fri Jan 28 08:41:09 2000
+++ publicfile.new/pkg-plist	Tue Jan  4 10:28:04 2005
@@ -1,3 +1,4 @@
 bin/configure
 bin/httpd
 bin/ftpd
+%%BASICAUTH%%bin/htrules
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list