httpd-apreq-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joe Schaefer <...@sunstarsys.com>
Subject Re: [RFC] Patch (Was: Apache::Request patch request (fwd))
Date Tue, 13 Mar 2001 20:30:53 GMT
Geoffrey Young <gyoung@laserlink.net> writes:

> > Try calling $apr->param('key') in list or scalar context to see if
> > you've got the same problem. 
> 
> yup - sorry I didn't check for that this time (I did last time)

Here's (hopefully) a good patch for Apache::Request::param.  The
rest is pretty much unchanged.

Best.
-- 
Joe Schaefer


<joe httpd-apreq> % cvs diff

cvs server: Diffing .
Index: libapreq.pod
===================================================================
RCS file: /home/cvs/httpd-apreq/libapreq.pod,v
retrieving revision 1.3
diff -u -r1.3 libapreq.pod
--- libapreq.pod	2000/12/23 02:56:53	1.3
+++ libapreq.pod	2001/03/13 20:21:56
@@ -49,6 +49,14 @@
      return status;
  }
 
+
+=item req->temp_dir
+
+Sets the directory where upload files are spooled.
+
+  char dir[] = "/usr/tmp";
+  req->temp_dir = dir;
+
 =back
 
 =head2 ApacheRequest *ApacheRequest_new (request_rec *r)
@@ -111,7 +119,7 @@
 
 =item upload->filename
 
-The name of the upload file:
+The name of the upload file as reported by the client:
 
  char *filename = upload->filename;
 
@@ -120,6 +128,12 @@
 A file pointer to the uploaded file:
 
  FILE *fp = upload->fp;
+
+=item upload->tempname
+
+The name of the temporary upload file on the server:
+
+char *tempname = upload->tempname;
 
 =item upload->size
 
cvs server: Diffing Cookie
cvs server: Diffing Request
Index: Request/Request.pm
===================================================================
RCS file: /home/cvs/httpd-apreq/Request/Request.pm,v
retrieving revision 1.12
diff -u -r1.12 Request.pm
--- Request/Request.pm	2000/12/23 03:19:14	1.12
+++ Request/Request.pm	2001/03/13 20:21:59
@@ -12,19 +12,6 @@
 }
 
 #just prototype methods here, moving to xs later
-sub param {
-    my $self = shift;
-    my($name, $value) = @_;
-    my $tab = $self->parms;
-    unless ($name) {
-	my %seen;
-	return wantarray ? grep { !$seen{$_}++ } keys %$tab : $tab;
-    }
-    if (defined $value) {
-	$tab->set($name, $value);
-    }
-    return wantarray ? ($tab->get($name)) : scalar $tab->get($name);
-}
 
 sub instance {
     my $class = shift;
@@ -100,6 +87,16 @@
      return $status;
  }
 
+=item TEMP_DIR
+
+Sets the directory where upload files are spooled.  On a *nix-like
+that supports link(2), the TEMP_DIR should be placed on the same
+file system as the final destination file:
+
+ my $apr = Apache::Request->new($r, TEMP_DIR => "/home/httpd/tmp");
+ my $upload = $apr->upload('file');
+ $upload->link("/home/user/myfile") || warn "link failed: $!";
+
 =back
 
 =head2 instance
@@ -240,6 +237,22 @@
     for my $upload ($apr->upload) {
 	...
     }
+
+=head2 tempname
+
+Provides the name of the spool file.
+
+=head2 link
+
+To avoid recopying the spool file on a Unix-like system,
+I<link> will create a hard link to it:
+
+  my $upload = $apr->upload('file');
+  $upload->link("/path/to/newfile") or
+      die sprintf "link from '%s' failed: $!", $upload->tempname;
+
+Typically the new name must lie on the same file system as the
+spool file. Check your system's link(2) manpage for details.
 
 =back
 
Index: Request/Request.xs
===================================================================
RCS file: /home/cvs/httpd-apreq/Request/Request.xs,v
retrieving revision 1.11
diff -u -r1.11 Request.xs
--- Request/Request.xs	2001/02/11 23:37:46	1.11
+++ Request/Request.xs	2001/03/13 20:21:59
@@ -76,6 +76,7 @@
 #define ApacheUpload_name(upload)     upload->name
 #define ApacheUpload_filename(upload) upload->filename
 #define ApacheUpload_next(upload)     upload->next
+#define ApacheUpload_tempname(upload)   upload->tempname
 
 #ifndef PerlLIO_dup
 #define PerlLIO_dup(fd)   dup((fd)) 
@@ -211,6 +212,11 @@
 		RETVAL->post_max = (int)SvIV(ST(i+1));
 		break;
 	    }
+	case 't':
+	    if (strcasecmp(key, "temp_dir") == 0) {
+		RETVAL->temp_dir = (char *)SvPV(ST(i+1), PL_na);
+		break;
+	    }
 	default:
 	    croak("[libapreq] unknown attribute: `%s'", key);
 	}
@@ -246,6 +252,92 @@
     ST(0) = mod_perl_tie_table(req->parms);
 
 void
+ApacheRequest_param(req, key=NULL, sv=Nullsv)
+    Apache::Request req	
+    char *key
+    SV *sv
+
+    PPCODE:
+    if ( !req->parsed ) ApacheRequest_parse(req);
+
+    if (key) {
+
+	if (sv != Nullsv) {
+
+	    if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) {
+	    	I32 i;
+	    	AV *av = (AV*)SvRV(sv);
+	    	const char *val;
+
+            	ap_table_unset(req->parms, key);
+	    	for (i=0; i<=AvFILL(av); i++) {
+		    val = (const char *)SvPV(*av_fetch(av, i, FALSE),PL_na);
+	            ap_table_add(req->parms, key, val);
+	    	}
+	    }
+            else ap_table_set(req->parms, key, (const char *)SvPV(sv, PL_na));
+	}
+
+	switch (GIMME_V) {
+
+        case G_SCALAR:			/* return (first) parameter value */
+	    {
+	    	const char *val = ap_table_get(req->parms, key);
+	    	if (val) XPUSHs(sv_2mortal(newSVpv((char*)val,0)));
+	    	else XSRETURN_UNDEF;
+	    }
+	    break;
+
+	case G_ARRAY:			/* return list of parameter values */
+	    {
+  	        I32 i;
+	        array_header *arr  = ap_table_elts(req->parms);
+	        table_entry *elts = (table_entry *)arr->elts;
+	        for (i = 0; i < arr->nelts; ++i) {
+	            if (elts[i].key && !strcasecmp(elts[i].key, key))
+	            	XPUSHs(sv_2mortal(newSVpv(elts[i].val,0)));
+	        }
+	    }
+	    break;
+
+	default:
+            XSRETURN_UNDEF;
+	} 
+    } 
+    else {		
+
+	switch (GIMME_V) {
+
+	case G_SCALAR:	    		/* like $apr->parms */
+	    ST(0) = mod_perl_tie_table(req->parms);
+	    XSRETURN(1); 
+	    break;
+
+	case G_ARRAY:			/* return list of unique keys */
+            {
+            	I32 i;
+	    	array_header *arr  = ap_table_elts(req->parms);
+	    	table_entry *elts = (table_entry *)arr->elts;
+	    	for (i = 0; i < arr->nelts; ++i) {
+		    I32 j;
+	           if (!elts[i].key) continue;
+		    /* simple but inefficient uniqueness check */
+		    for (j = 0; j < i; ++j) { 
+		        if (!strcasecmp(elts[i].key, elts[j].key))
+			    break;
+		    }
+	            if ( i == j )
+	                XPUSHs(sv_2mortal(newSVpv(elts[i].key,0)));
+	        }
+            }
+	    break;
+
+	default:
+	    XSRETURN_UNDEF;
+ 	}
+    }
+
+void
 ApacheRequest_upload(req, name=NULL)
     Apache::Request req
     char *name
@@ -323,6 +415,10 @@
 ApacheUpload_filename(upload)
     Apache::Upload upload
 
+char *
+ApacheUpload_tempname(upload)
+    Apache::Upload upload
+
 Apache::Upload
 ApacheUpload_next(upload)
     Apache::Upload upload 
@@ -330,6 +426,17 @@
 const char *
 ApacheUpload_type(upload)
     Apache::Upload upload 
+
+char *
+ApacheUpload_link(upload, name)
+    Apache::Upload upload
+    char *name
+
+	CODE:
+	RETVAL = (link(upload->tempname, name)) ? NULL : name;
+	
+	OUTPUT:
+	RETVAL	
 
 void
 ApacheUpload_info(upload, key=NULL)
cvs server: Diffing c
Index: c/apache_cookie.c
===================================================================
RCS file: /home/cvs/httpd-apreq/c/apache_cookie.c,v
retrieving revision 1.8
diff -u -r1.8 apache_cookie.c
--- c/apache_cookie.c	2001/01/05 00:05:23	1.8
+++ c/apache_cookie.c	2001/03/13 20:22:01
@@ -192,8 +192,40 @@
         cookie_push_arr(arr, ap_pstrcat(p, name, "=", val, NULL)); \
     }
 
-#define escape_url(val) \
-ap_os_escape_path(p, val?val:"", 1)
+static char * escape_url(pool *p, char *val) 
+{
+  char *result = ap_os_escape_path(p, val?val:"", 1);
+  char *end = result + strlen(result);
+  char *seek;
+
+  for ( seek = end-1; seek >= result; --seek) {
+    char *ptr, *replacement;
+
+    switch (*seek) {
+
+    case '&':
+	replacement = "%26";
+	break;
+    case '=':
+	replacement = "%3d";
+	break;
+    /* additional cases here */
+
+    default:
+	continue; /* next for() */
+    }
+
+
+    for (ptr = end; ptr > seek; --ptr) {
+      ptr[2] = ptr[0];
+    }
+
+    strncpy(seek, replacement, 3);
+    end += 2;
+  }
+
+  return(result);
+}
 
 char *ApacheCookie_as_string(ApacheCookie *c)
 {
@@ -214,10 +246,10 @@
 	cookie_push_arr(values, "secure");
     }
 
-    cookie = ap_pstrcat(p, escape_url(c->name), "=", NULL);
+    cookie = ap_pstrcat(p, escape_url(p, c->name), "=", NULL);
     for (i=0; i<c->values->nelts; i++) {
 	cookie = ap_pstrcat(p, cookie, 
-			    escape_url(((char**)c->values->elts)[i]), 
+			    escape_url(p, ((char**)c->values->elts)[i]), 
 			    (i < (c->values->nelts-1) ? "&" : NULL),
 			    NULL);
     }
Index: c/apache_request.c
===================================================================
RCS file: /home/cvs/httpd-apreq/c/apache_request.c,v
retrieving revision 1.8
diff -u -r1.8 apache_request.c
--- c/apache_request.c	2000/12/17 00:36:38	1.8
+++ c/apache_request.c	2001/03/13 20:22:01
@@ -203,6 +203,7 @@
     req->upload = NULL;
     req->post_max = -1;
     req->disable_uploads = 0;
+    req->temp_dir = NULL;
     req->parsed = 0;
     req->r = r;
 
@@ -315,20 +316,41 @@
     return OK;
 }
 
-FILE *ApacheRequest_tmpfile(ApacheRequest *req)
+static void remove_tmpfile(void *data) {
+    remove((char *) data);
+}
+
+FILE *ApacheRequest_tmpfile(ApacheRequest *req, ApacheUpload *upload)
 {
     request_rec *r = req->r;
     FILE *fp;
-
-    if (!(fp = tmpfile())) {
-	ap_log_rerror(REQ_ERROR,
-		      "[libapreq] could not create tmpfile()"); 
+    char prefix[] = "apreq";
+    char *name;
+    int fd, tries = 100;
+    
+    while (--tries > 0) {
+	if ( (name = tempnam(req->temp_dir, prefix)) == NULL ) continue;
+	fd = ap_popenf(r->pool, name, O_CREAT|O_EXCL|O_RDWR, 0600);
+	if ( fd >= 0 )
+	    break; /* success */
+	else
+	    free(name);
     }
-    else {
-	ap_note_cleanups_for_file(r->pool, fp);
+    
+    if ( tries == 0  || (fp = ap_pfdopen(r->pool, fd, "w+") ) == NULL ) {
+	ap_log_rerror(REQ_ERROR,
+		      "[libapreq] could not open temp file '%s'", name); 	
+	if ( fd >= 0 ) { remove(name); }
+	return NULL;
     }
 
+    upload->fp = fp;
+    upload->tempname = ap_pstrdup(r->pool, name);
+    ap_register_cleanup(r->pool, (void *)upload->tempname, 
+			remove_tmpfile, ap_null_cleanup);
+
     return fp;
+
 }
 
 int ApacheRequest_parse_multipart(ApacheRequest *req)
@@ -418,7 +440,7 @@
 		req->upload = upload;
 	    }
 
-	    if (!(upload->fp = ApacheRequest_tmpfile(req))) {
+	    if (! ApacheRequest_tmpfile(req, upload) ) {
 		return HTTP_INTERNAL_SERVER_ERROR;
 	    }
 
Index: c/apache_request.h
===================================================================
RCS file: /home/cvs/httpd-apreq/c/apache_request.h,v
retrieving revision 1.4
diff -u -r1.4 apache_request.h
--- c/apache_request.h	2001/01/03 03:58:56	1.4
+++ c/apache_request.h	2001/03/13 20:22:01
@@ -19,6 +19,7 @@
     int parsed;
     int post_max;
     int disable_uploads;
+    char* temp_dir;
     request_rec *r;
 } ApacheRequest;
 
@@ -26,6 +27,7 @@
     ApacheUpload *next;
     char *filename;
     char *name;
+    char *tempname;
     table *info;
     FILE *fp;
     long size;
@@ -72,7 +74,7 @@
 #define ApacheRequest_parse(req) \
     (req->status = req->parsed ? req->status : ApacheRequest___parse(req)) 
 
-FILE *ApacheRequest_tmpfile(ApacheRequest *req);
+FILE *ApacheRequest_tmpfile(ApacheRequest *req, ApacheUpload *upload);
 ApacheUpload *ApacheUpload_new(ApacheRequest *req);
 ApacheUpload *ApacheUpload_find(ApacheUpload *upload, char *name);

Mime
View raw message