Skip to content

Commit

Permalink
X-Sendfile-Temporary
Browse files Browse the repository at this point in the history
Delete temporary files on close.
See XSendFilePath AllowFileDelete

Closes #7
  • Loading branch information
jrhee authored and nmaier committed Jul 25, 2011
1 parent 0efcd03 commit f2a8c1f
Showing 1 changed file with 66 additions and 20 deletions.
86 changes: 66 additions & 20 deletions mod_xsendfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "http_protocol.h" /* ap_hook_insert_error_filter */

#define AP_XSENDFILE_HEADER "X-SENDFILE"
#define AP_XSENDFILETEMPORARY_HEADER "X-SENDFILE-TEMPORARY"

module AP_MODULE_DECLARE_DATA xsendfile_module;

Expand All @@ -66,8 +67,15 @@ typedef struct xsendfile_conf_t {
xsendfile_conf_active_t ignoreLM;
xsendfile_conf_active_t unescape;
apr_array_header_t *paths;
apr_array_header_t *temporaryPaths;
} xsendfile_conf_t;

/* structure to hold the path and permissions */
typedef struct xsendfile_path_t {
const char *path;
int allowFileDelete;
} xsendfile_path_t;

static xsendfile_conf_t *xsendfile_config_create(apr_pool_t *p) {
xsendfile_conf_t *conf;

Expand All @@ -78,7 +86,7 @@ static xsendfile_conf_t *xsendfile_config_create(apr_pool_t *p) {
conf->enabled =
XSENDFILE_UNSET;

conf->paths = apr_array_make(p, 1, sizeof(char*));
conf->paths = apr_array_make(p, 1, sizeof(xsendfile_path_t));

return conf;
}
Expand Down Expand Up @@ -141,13 +149,15 @@ static const char *xsendfile_cmd_flag(cmd_parms *cmd, void *perdir_confv, int fl
return NULL;
}

static const char *xsendfile_cmd_path(cmd_parms *cmd, void *pdc, const char *arg) {
static const char *xsendfile_cmd_path(cmd_parms *cmd, void *pdc, const char *path, const char *allowFileDelete) {
xsendfile_conf_t *conf = (xsendfile_conf_t*)ap_get_module_config(
cmd->server->module_config,
&xsendfile_module
);
char **newpath = (char**)apr_array_push(conf->paths);
*newpath = apr_pstrdup(cmd->pool, arg);

xsendfile_path_t *newpath = (xsendfile_path_t*)apr_array_push(conf->paths);
newpath->path = apr_pstrdup(cmd->pool, path);
newpath->allowFileDelete = (allowFileDelete && strcmp(allowFileDelete, "AllowFileDelete") == 0) ? 1: 0;

return NULL;
}
Expand Down Expand Up @@ -211,37 +221,46 @@ static const char *ap_xsendfile_get_orginal_path(request_rec *rec) {
/*
little helper function to build the file path if available
*/
static apr_status_t ap_xsendfile_get_filepath(request_rec *r, xsendfile_conf_t *conf, const char *file, /* out */ char **path) {
static apr_status_t ap_xsendfile_get_filepath(request_rec *r, xsendfile_conf_t *conf, const char *file, int shouldDeleteFile, /* out */ char **path) {

const char *root = ap_xsendfile_get_orginal_path(r);
apr_status_t rv;

apr_array_header_t *patharr;
const char **paths;
const xsendfile_path_t *paths;
int i;


#ifdef _DEBUG
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: path is %s", root);
#endif

/* merge the array */
if (root) {
patharr = apr_array_make(r->pool, conf->paths->nelts + 1, sizeof(char*));
*(const char**)(apr_array_push(patharr)) = root;
apr_array_cat(patharr, conf->paths);
} else {
patharr = conf->paths;
patharr = conf->paths;
if (!shouldDeleteFile) {
const char *root = ap_xsendfile_get_orginal_path(r);
if (root) {
xsendfile_path_t *newpath;

patharr = apr_array_make(r->pool, conf->paths->nelts + 1, sizeof(xsendfile_path_t));
newpath = apr_array_push(patharr);
newpath->path = root;
newpath->allowFileDelete = 0;
apr_array_cat(patharr, conf->paths);
}
}

if (patharr->nelts == 0) {
return APR_EBADPATH;
}
paths = (const char**)patharr->elts;

paths = (const xsendfile_path_t*)patharr->elts;
for (i = 0; i < patharr->nelts; ++i) {
if (shouldDeleteFile && !paths[i].allowFileDelete){
continue;
}

if ((rv = apr_filepath_merge(
path,
paths[i],
paths[i].path,
file,
APR_FILEPATH_TRUENAME | APR_FILEPATH_NOTABOVEROOT,
r->pool
Expand Down Expand Up @@ -275,6 +294,7 @@ static apr_status_t ap_xsendfile_output_filter(ap_filter_t *f, apr_bucket_brigad
char *translated = NULL;

int errcode;
int shouldDeleteFile = 0;

#ifdef _DEBUG
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: output_filter for %s", r->the_request);
Expand All @@ -301,13 +321,32 @@ static apr_status_t ap_xsendfile_output_filter(ap_filter_t *f, apr_bucket_brigad
alright, look for x-sendfile
*/
file = (char*)apr_table_get(r->headers_out, AP_XSENDFILE_HEADER);
apr_table_unset(r->headers_out, AP_XSENDFILE_HEADER);

/* cgi/fastcgi will put the stuff into err_headers_out */
if (!file || !*file) {
file = (char*)apr_table_get(r->err_headers_out, AP_XSENDFILE_HEADER);
apr_table_unset(r->err_headers_out, AP_XSENDFILE_HEADER);
}

/*
so...there is no X-SendFile header, check if there is an X-Sendfile-Temporary header
*/
if (!file || !*file) {
shouldDeleteFile = 1;
file = (char*)apr_table_get(r->headers_out, AP_XSENDFILETEMPORARY_HEADER);
}
/*
Maybe X-Sendfile-Temporary is set via cgi in error_headers_out?
*/
if (!file || !*file) {
file = (char*)apr_table_get(r->err_headers_out, AP_XSENDFILETEMPORARY_HEADER);
}

/* Remove any X-Sendfile headers */
apr_table_unset(r->headers_out, AP_XSENDFILE_HEADER);
apr_table_unset(r->err_headers_out, AP_XSENDFILE_HEADER);
apr_table_unset(r->headers_out, AP_XSENDFILETEMPORARY_HEADER);
apr_table_unset(r->err_headers_out, AP_XSENDFILETEMPORARY_HEADER);

/* nothing there :p */
if (!file || !*file) {
#ifdef _DEBUG
Expand Down Expand Up @@ -358,7 +397,13 @@ static apr_status_t ap_xsendfile_output_filter(ap_filter_t *f, apr_bucket_brigad
}

/* lookup/verification of the given path */
rv = ap_xsendfile_get_filepath(r, conf, file, &translated);
rv = ap_xsendfile_get_filepath(
r,
conf,
file,
shouldDeleteFile,
&translated
);
if (rv != OK) {
ap_log_rerror(
APLOG_MARK,
Expand All @@ -384,6 +429,7 @@ static apr_status_t ap_xsendfile_output_filter(ap_filter_t *f, apr_bucket_brigad
&fd,
translated,
APR_READ | APR_BINARY
| (shouldDeleteFile ? APR_DELONCLOSE : 0) //if this is a temporary file, delete on close
#if APR_HAS_SENDFILE
| (coreconf->enable_sendfile != ENABLE_SENDFILE_OFF ? APR_SENDFILE_ENABLED : 0)
#endif
Expand Down Expand Up @@ -605,7 +651,7 @@ static const command_rec xsendfile_command_table[] = {
OR_FILEINFO,
"On|Off - Unescape/url-decode the value of the header (default: On)"
),
AP_INIT_TAKE1(
AP_INIT_TAKE12(
"XSendFilePath",
xsendfile_cmd_path,
NULL,
Expand Down

4 comments on commit f2a8c1f

@ajitteli
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can u please suggest me how to configure x-sendfile-temporary in apache2 virtual host? I have configured virtual host like:
<VirtualHost *:80>
ServerName blogApp.shalini.com
DocumentRoot /home/shalini/xbass/public
RailsEnv development
<Directory "/home/shalini/xbass/public">
XsendFileTemporary on
XSendFileTemporaryPath /home/shalini/xbass/tmp/rawdatadownloads/

When I restarted the apache server it is showing the below error:

Syntax error on line 6 of /etc/apache2/sites-enabled/blogApp.shalini.com:
Invalid command 'XSendFileTemporary', perhaps misspelled or defined by a module not included in the server configuration
Action 'configtest' failed.
The Apache error log may have more information.
...fail!

@jrhee
Copy link
Contributor Author

@jrhee jrhee commented on f2a8c1f Dec 22, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation explains how to set up your apache config: https://github.com/nmaier/mod_xsendfile/blob/master/docs/Readme.html
Instead of:
XsendFileTemporary on
XSendFileTemporaryPath /home/shalini/xbass/tmp/rawdatadownloads/
Do:
XSendFile on
XSendFile /home/shalini/xbass/tmp/rawdatadownloads AllowFileDelete

@jrhee
Copy link
Contributor Author

@jrhee jrhee commented on f2a8c1f Dec 22, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, if you want to send/delete (send a temporary file) your headers should look like:
header("'X-Sendfile-Temporary: $path_to_somefile");
Rather than the syntax for sending a file you do not wish to delete:
header("'X-Sendfile: $path_to_somefile");

@ajitteli
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first i have given:
XSendFile on
XSendFilePath /home/shalini/xbass/tmp/rawdatadownloads AllowFileDelete

its not deleting the file immediately after the download is completed.

2nd i have given:

XsendFileTemporary on
XSendFilePath /home/shalini/xbass/tmp/rawdatadownloads/ AllowFileDelete

giving the error:
Syntax error on line 6 of /etc/apache2/sites-enabled/blogApp.shalini.com:
Invalid command 'XSendFileTemporary', perhaps misspelled or defined by a module not included in the server configuration
Action 'configtest' failed.
The Apache error log may have more information.
...fail!

Please sign in to comment.