httpd-apreq-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Geoffrey Young <gyo...@laserlink.net>
Subject RE: [RFC] Patch (Was: Apache::Request patch request (fwd))
Date Tue, 13 Mar 2001 20:46:19 GMT


> -----Original Message-----
> From: Joe Schaefer [mailto:joe@sunstarsys.com]
> Sent: Tuesday, March 13, 2001 3:31 PM
> To: Geoffrey Young
> Cc: apreq-dev@httpd.apache.org
> Subject: Re: [RFC] Patch (Was: Apache::Request patch request (fwd))
> 
> 
> 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.

looks ok as far as param() goes - I didn't get the chance to test the rest
(at all, that is)

--Geoff

> 
> 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