From ad7a5dec869ca1064edaeca24cf54b65b871cdc6 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 13 May 2020 19:52:53 -0300 Subject: [PATCH 1/7] Cmake settings. --- CMakeLists.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3299bb5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.16.5) + +project(mod_xsendfile) + +link_directories(${APACHE2_PATH}/bin) +link_directories(${APACHE2_PATH}/lib) + +include_directories(${APACHE2_PATH}/include) + +add_library(mod_xsendfile MODULE mod_xsendfile.c) + +if (_DEBUG) +add_definitions(-D_DEBUG=${_DEBUG}) +endif() + +target_link_libraries(mod_xsendfile libhttpd libaprutil-1 libapr-1) +set_target_properties(mod_xsendfile PROPERTIES PREFIX "" SUFFIX ".so") + +if (NOT INSTALL_DIRECTORY) + set(INSTALL_DIRECTORY ${APACHE2_PATH}/modules) +endif () + +install(TARGETS mod_xsendfile DESTINATION ${INSTALL_DIRECTORY}) From 754e2153f010fe93129037dfb97e866aba36ed69 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 13 May 2020 19:55:22 -0300 Subject: [PATCH 2/7] Adding the 'XSendFilePathRoot' option (server files related to root) --- mod_xsendfile.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/mod_xsendfile.c b/mod_xsendfile.c index 863ed26..a6b6738 100644 --- a/mod_xsendfile.c +++ b/mod_xsendfile.c @@ -72,6 +72,7 @@ typedef struct xsendfile_conf_t { xsendfile_conf_active_t ignoreETag; xsendfile_conf_active_t ignoreLM; xsendfile_conf_active_t unescape; + const char *rootpath; apr_array_header_t *paths; apr_array_header_t *temporaryPaths; } xsendfile_conf_t; @@ -92,6 +93,8 @@ static xsendfile_conf_t *xsendfile_config_create(apr_pool_t *p) { conf->enabled = XSENDFILE_UNSET; + // optional settings + conf->rootpath = NULL; conf->paths = apr_array_make(p, 1, sizeof(xsendfile_path_t)); return conf; @@ -102,6 +105,7 @@ static void *xsendfile_config_server_create(apr_pool_t *p, server_rec *s) { } #define XSENDFILE_CFLAG(x) conf->x = overrides->x != XSENDFILE_UNSET ? overrides->x : base->x +#define XSENDFILE_CPATH(x) conf->x = overrides->x != NULL ? overrides->x : base->x static void *xsendfile_config_merge(apr_pool_t *p, void *basev, void *overridesv) { xsendfile_conf_t *base = (xsendfile_conf_t *)basev; @@ -115,6 +119,8 @@ static void *xsendfile_config_merge(apr_pool_t *p, void *basev, void *overridesv XSENDFILE_CFLAG(ignoreLM); XSENDFILE_CFLAG(unescape); + // optional settings + XSENDFILE_CPATH(rootpath); conf->paths = apr_array_append(p, overrides->paths, base->paths); return (void*)conf; @@ -175,6 +181,17 @@ static const char *xsendfile_cmd_path(cmd_parms *cmd, void *pdc, return NULL; } +static const char *xsendfile_root_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 + ); + conf->rootpath = apr_pstrdup(cmd->pool, path); + return NULL; +} + /* little helper function to get the original request path code borrowed from request.c and util_script.c @@ -231,6 +248,13 @@ static const char *ap_xsendfile_get_orginal_path(request_rec *rec) { return rv; } +/* + Root path based conf or environ. +*/ +static const char *ap_xsendfile_get_root_path(xsendfile_conf_t *conf, request_rec *rec) { + return conf->rootpath != NULL ? conf->rootpath : ap_xsendfile_get_orginal_path(rec); +} + /* little helper function to build the file path if available */ @@ -246,7 +270,7 @@ static apr_status_t ap_xsendfile_get_filepath(request_rec *r, patharr = conf->paths; if (!shouldDeleteFile) { - const char *root = ap_xsendfile_get_orginal_path(r); + const char *root = ap_xsendfile_get_root_path(conf, r); if (root) { xsendfile_path_t *newpath; @@ -683,6 +707,13 @@ static const command_rec xsendfile_command_table[] = { RSRC_CONF|ACCESS_CONF, "Allow to serve files from that Path. Must be absolute" ), + AP_INIT_TAKE12( + "XSendFilePathRoot", + xsendfile_root_path, + NULL, + RSRC_CONF|ACCESS_CONF, + "Allow to serve files relative that root." + ), { NULL } }; static void xsendfile_register_hooks(apr_pool_t *p) { From 399c6bf4beb9bc4066b7e189b5e86dc0fbc9f505 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 14 May 2020 15:09:14 -0300 Subject: [PATCH 3/7] Rename apache path var (APACHE2_ROOT) --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3299bb5..3eb5129 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,10 @@ cmake_minimum_required(VERSION 3.16.5) project(mod_xsendfile) -link_directories(${APACHE2_PATH}/bin) -link_directories(${APACHE2_PATH}/lib) +link_directories(${APACHE2_ROOT}/bin) +link_directories(${APACHE2_ROOT}/lib) -include_directories(${APACHE2_PATH}/include) +include_directories(${APACHE2_ROOT}/include) add_library(mod_xsendfile MODULE mod_xsendfile.c) @@ -17,7 +17,7 @@ target_link_libraries(mod_xsendfile libhttpd libaprutil-1 libapr-1) set_target_properties(mod_xsendfile PROPERTIES PREFIX "" SUFFIX ".so") if (NOT INSTALL_DIRECTORY) - set(INSTALL_DIRECTORY ${APACHE2_PATH}/modules) + set(INSTALL_DIRECTORY ${APACHE2_ROOT}/modules) endif () install(TARGETS mod_xsendfile DESTINATION ${INSTALL_DIRECTORY}) From 07b7d9b975feeed13d79e1c8222c5e37dc7ccbdd Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 14 May 2020 18:45:34 -0300 Subject: [PATCH 4/7] Verification of the existence of the file. --- mod_xsendfile.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mod_xsendfile.c b/mod_xsendfile.c index a6b6738..0862da2 100644 --- a/mod_xsendfile.c +++ b/mod_xsendfile.c @@ -307,7 +307,15 @@ static apr_status_t ap_xsendfile_get_filepath(request_rec *r, APR_FILEPATH_TRUENAME | APR_FILEPATH_NOTABOVEROOT, r->pool )) == OK) { - break; + // The path is only valid if it exists. + // If it doesn't continue until you find a valid path on the white-list. + apr_finfo_t info; + rv = apr_stat(&info, *path, APR_FINFO_CSIZE, r->pool); + if (rv == OK) { + break; + } else { + continue; + } } } if (rv != OK) { @@ -741,4 +749,4 @@ module AP_MODULE_DECLARE_DATA xsendfile_module = { xsendfile_register_hooks }; -/* vim: set ts=2 sw=2 et : */ +/* vim: set ts=2 sw=2 et : */ \ No newline at end of file From 2e35f494424a404e8ef96cb9c59f02d29abb58d8 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 14 May 2020 19:10:22 -0300 Subject: [PATCH 5/7] Rename XSendFilePathRoot tor XSendFileRootPath. --- mod_xsendfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_xsendfile.c b/mod_xsendfile.c index 0862da2..23f1a11 100644 --- a/mod_xsendfile.c +++ b/mod_xsendfile.c @@ -716,7 +716,7 @@ static const command_rec xsendfile_command_table[] = { "Allow to serve files from that Path. Must be absolute" ), AP_INIT_TAKE12( - "XSendFilePathRoot", + "XSendFileRootPath", xsendfile_root_path, NULL, RSRC_CONF|ACCESS_CONF, From 021bbab9e9a93f7934c092ea5fcc2bc028f64b79 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 15 May 2020 16:56:51 -0300 Subject: [PATCH 6/7] x86 / x64 / Releases. --- bin/Apache24/Win32/mod_xsendfile.so | Bin 50176 -> 14336 bytes bin/Apache24/Win64/mod_xsendfile.so | Bin 49664 -> 15360 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/Apache24/Win32/mod_xsendfile.so b/bin/Apache24/Win32/mod_xsendfile.so index 3ac95f39ac59f1c31e6506748fc4112a923f2ff5..8bfbe7be694e1c57daca1619f57fc2a058ebbf4e 100644 GIT binary patch literal 14336 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 literal 50176 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

nPY@+ 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%0D~NKGvpk7FP`xd%`%LX)zc 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 diff --git a/bin/Apache24/Win64/mod_xsendfile.so b/bin/Apache24/Win64/mod_xsendfile.so index 3dc8777dff1e6ce81cf86d3ec9abbc69e1b1d4d7..742b58991f65c89e5585f26b73b1b7cde9dd39d0 100644 GIT binary patch literal 15360 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 literal 49664 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 Date: Sun, 17 May 2020 14:52:43 -0300 Subject: [PATCH 7/7] Convert readme html to md --- docs/Readme.html | 427 -------------------------------------------- docs/Readme.md | 453 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 453 insertions(+), 427 deletions(-) delete mode 100644 docs/Readme.html create mode 100644 docs/Readme.md diff --git a/docs/Readme.html b/docs/Readme.html deleted file mode 100644 index 26c2eff..0000000 --- a/docs/Readme.html +++ /dev/null @@ -1,427 +0,0 @@ - - - - - mod_xsendfile for Apache2 - - - - -

-
-

mod_xsendfile for Apache2

-
- -
-

Overview

- -

mod_xsendfile is a small Apache2 module that - processes X-SENDFILE headers output handlers might have registered.

- -

If it encounters the presence of such header it will discard all output and send the file specified by that header instead using Apache internals including all optimizations like caching-headers and sendfile or mmap if configured.

- -

It is useful for processing script-output of e.g. php, perl, python or - any *cgi.

- -

Useful?

- -

Yep, it is useful.

- -
    -
  • Some applications require checking for special privileges.
  • -
  • Other have to lookup values first (e.g.. from a DB) in order to correctly process a download request.
  • -
  • Or store values (download-counters come into mind).
  • -
  • etc.
  • -
- -

Benefits

-
    -
  • Uses apache internals
  • -
  • Optimal delivery through sendfile and mmap (if available).
  • -
  • Sets correct cache headers such as Etag and If-Modified-Since as if the file was statically served.
  • -
  • Processes cache headers such as If-None-Match or If-Modified-Since.
  • -
  • Support for ranges.
  • -
-
- -
-

Installation

-
    -
  1. Grab the source.
  2. -
  3. Compile and install -
      -
    • In general:
      - apxs -cia mod_xsendfile.c
    • -
    • Debian/Ubuntu uses apxs2:
      - apxs2 -cia mod_xsendfile.c
    • -
    • Mac users might want to build fat binaries:
      - apxs -cia -Wc,"-arch i386 -arch x86_64" -Wl,"-arch i386 -arch x86_64" mod_xsendfile.c
    • -
    -
  4. -
  5. Restart apache
  6. -
  7. That's all.
  8. -
-
- -
-

Configuration

- -

Headers

-
    -
  • X-SENDFILE - Send the file referenced by this headers instead of the current response body
  • -
  • X-SENDFILE-TEMPORARY - Like X-SENDFILE, but the file will be deleted afterwards. The file must originate from a path that has the AllowFileDelete flag set.
  • -
- -

XSendFile

- - - - - - - - - - - - - - - - - - - - -
DescriptionEnables or disables header processing
SyntaxXSendFile on|off
DefaultXSendFile off
Contextserver config, virtual host, directory, .htaccess
- -

Setting XSendFile on will enable processing.

- -

The file specified in X-SENDFILE header will be sent instead of the handler output.

- -

The value (file name) given by the header is assmumed to be url-encoded, i.e. unescaping/url-decoding will be performed. See XSendFileUnescape.
- If you happen to store files using already url-encoded file names, you must "double" encode the names... %20 -> %2520

- -

If the response lacks the X-SENDFILE header the module will not perform any processing.

- -

XSendFileIgnoreEtag

- - - - - - - - - - - - - - - - - - - - -
DescriptionIgnore script provided Etag headers
SyntaxXSendFileIgnoreEtag on|off
DefaultXSendFileIgnoreEtag off
Contextserver config, virtual host, directory, .htaccess
- -

Setting XSendFileIgnoreEtag on will ignore all ETag headers the original output handler may have set.
- This is helpful for applications that will generate such headers even for empty content.

- -

XSendFileIgnoreLastModified

- - - - - - - - - - - - - - - - - - - - -
DescriptionIgnore script provided LastModified headers
SyntaxXSendFileIgnoreLastModified on|off
DefaultXSendFileIgnoreLastModified off
Contextserver config, virtual host, directory, .htaccess
- -

Setting XSendFileIgnoreLastModified on will ignore all Last-Modified headers the original output handler may have set.
- This is helpful for applications that will generate such headers even for empty content.

- -

XSendFileUnescape

- - - - - - - - - - - - - - - - - - - - -
DescriptionUnescape/url-decode the value of the header
SyntaxXSendFileUnescape on|off
DefaultXSendFileUnescape on
Contextserver config, virtual host, directory, .htaccess
- -

Setting XSendFileUnescape off will restore the pre-1.0 behavior of using the raw header value, instead of trying to unescape/url-decode first.
- Headers may only contain a certain ASCII subset, as dictated by the corresponding RFCs/protocol. Hence you should escape/url-encode (and have XSendFile unescape/url-decode) the header value. Failing to keep within the bounds of that ASCII subset might cause errors, depending on your application framework.

-

Hence this setting is meant only for backwards-compatibility with legacy applications expecting the old behavior; new applications should url-encode the value correctly and leave XSendFileUnescape on. Of course, if your paths are always ASCII, then (usually) no special encoding is required.

- -

XSendFilePath

- - - - - - - - - - - - - - - - - - - - -
DescriptionWhite-list more paths
SyntaxXSendFilePath <absolute path> [AllowFileDelete]
DefaultNone
Contextserver config, virtual host, directory
- -

XSendFilePath allow you to add additional paths to some kind of white list. All files within these paths are allowed to get served through mod_xsendfile.

-

Provide an absolute path as Parameter to this directive.

-

If the optional AllowFileDelete flag is specified, then files under this path can be served using the X-SENDFILE-TEMPORARY header, and will then be deleted once the file is delievered. - Hence you should only set the AllowFileDelete flag for paths that do not hold any files that shouldn't be deleted!

-

You may provide more than one path.

-

Remarks - Relative paths

-

The current working directory (if it can be determined) will be always checked first.

-

If you provide relative paths via the X-SendFile header, then all whitelist items will be checked until a seamingly valid combination is found, i.e. the result is within the bounds of the whitelist item; it isn't checked at this point if the path in question actually exists.
- Considering you whitelisted /tmp/pool and /tmp/pool2 and your script working directory is /var/www.

-

X-SendFile: file

-
    -
  1. /var/www/file - Within bounds of /var/www, OK
  2. -
-

X-SendFile: ../pool2/file

-
    -
  1. /var/www/../pool2/file = /var/pool2/file - Not within bounds of /var/www
  2. -
  3. /tmp/pool/../pool2/file = /tmp/pool2/file - Not within bounds of /tmp/pool
  4. -
  5. /tmp/pool2/../pool2/file = /tmp/pool2/file - Within bounds of /tmp/pool2, OK
  6. -
-

You still can only access paths that are whitelisted. However you have might expect a different behavior here, hence the documentation.

-

Please note: It is recommended to always use absolute paths.

- -

Remarks - Inheritance

-

The white list "inherits" entries from higher level configuration.
-

XSendFilePath /tmp
-<VirtualHost *>
-  ServerName someserver
-  XSendFilePath /home/userxyz
-</VirtualHost>
-<VirtualHost *>
-  ServerName anotherserver
-  XSendFilePath /var/www/somesite/
-  <Directory /var/www/somesite/fastcgis>
-    XSendFilePath /var/www/shared
-  </Directory>
-</VirtualHost>
-

Above example will give: -

    -
  • *
      -
    • /tmp
    • -
  • -
  • someserver
      -
    • /tmp
    • -
    • /home/userxyz
    • -
  • -
  • another
      -
    • /tmp
    • -
    • /var/www/somesite
    • -
    • /var/www/shared (for scripts* located in /var/www/somesite/fastcgis)
    • -
  • -
-

*) Scripts, in this context, mean the actual script-starters. E.g. PHP as a handler will use the .php itself, while in CGI mode refers to the starter.

-

Windows users must include the drive letter to those paths as well. Tests show that it has to be in upper-case.

- -

Example

- -

.htaccess

- -
<Files out.php>
-XSendFile on
-</Files>
- -

out.php

- -

<?php
- -
...
- - if (
$user->isLoggedIn())
- - {
- -     
header("X-Sendfile: $path_to_somefile");
- -     
header("Content-Type: application/octet-stream");
- -     
header("Content-Disposition: attachment; filename=\"$somefile\"");
- -     exit;
- - }
- -
?>
- -
<h1>Permission denied</h1>
- - <p>Login first!</p>

- -

Limitations / Issues / Security considerations

- -
    - -
  • The Content-Encoding - header - if present - will be dropped, as the module - cannot know if it was set by intention of the programmer or the - handler. E.g. php with output compression enabled will set this header, - but the replacement file send via mod_xsendfile is most likely not - compressed.
  • - -
  • The header (X-SENDFILE) is not case-sensitive.
  • - -
  • X-Sendfile will also happily send files that are otherwise protected (e.g. Deny from all).
    -
-
- -
-

Credits

- -

The idea comes from lighttpd - - A fast web server - with minimal memory footprint.

- -

The module itself was inspired by many other Apache2 modules - such as mod_rewrite, mod_headers and obviously core.c.

- -

License

- -

Copyright 2006-2012 by Nils Maier

- -

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.

- -

You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0

- -

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- -

See the License for the specific language governing permissions and - limitations under the License.

- -

Changes

-

Version 1.0

-
    -
  • Unescape/url-decode header value to support non-ascii file names
  • -
  • XSendFileUnescape setting, to support legacy applications
  • -
  • X-SENDFILE-TEMPORARY header and corresponding AllowFileDelete flag
  • -
  • Fix: Actually look into the backend-provided headers for Last-Modified
  • -
-

Version 0.12

-
    -
  • Now incorrect headers will be dropped early
  • -
-

Version 0.11.1

-
    -
  • Fixed some documentation bugs
  • -
  • Built win32 binaries against latest httpd using MSVC9
  • -
  • Updated MSVC Project files
  • -
-

Version 0.11

-
    -
  • Fixed large file support
  • -
-

Version 0.10

-
    -
  • Won't override Etag/Last-Modified if already set.
  • -
  • New Configuration directive: XSendFileIgnoreEtag
  • -
  • New Configuration directive: XSendFileIgnoreLastModified
  • -
  • New Configuration directive: XSendFilePath
  • -
  • Removed Configuration directive: XSendFileAllowAbove
    - Use XSendFilePath instead.
  • -
  • Improved header handling for FastCGI/CGI output (removing duplicate headers).
  • -
-

Version 0.9

-
    -
  • New configuration directive: XSendFileAllowAbove
  • -
  • Initial FastCGI/CGI support
  • -
  • Filter only added when needed
  • -
-

Version 0.8

-
    -
  • This is the initial public release.
  • -
-
-
- - diff --git a/docs/Readme.md b/docs/Readme.md new file mode 100644 index 0000000..fb21d5d --- /dev/null +++ b/docs/Readme.md @@ -0,0 +1,453 @@ +
+ +
+ +# mod_xsendfile for Apache2 + +
+ +
+ +## Overview + +mod_xsendfile is a small Apache2 module that processes X-SENDFILE headers output handlers might have registered. + +If it encounters the presence of such header it will discard all output and send the file specified by that header instead using Apache internals including all optimizations like caching-headers and sendfile or mmap if configured. + +It is useful for processing script-output of e.g. php, perl, python or any *cgi. + +## Useful? + +Yep, it is useful. + +* Some applications require checking for special privileges. +* Other have to lookup values first (e.g.. from a DB) in order to correctly process a download request. +* Or store values (download-counters come into mind). +* etc. + +### Benefits + +* Uses apache internals +* Optimal delivery through sendfile and mmap (if available). +* Sets correct cache headers such as Etag and If-Modified-Since as if the file was statically served. +* Processes cache headers such as If-None-Match or If-Modified-Since. +* Support for ranges. + +
+ +
+ +## Installation + +1. Grab the source. +2. Compile and install + * In general: + `apxs -cia mod_xsendfile.c` + * Debian/Ubuntu uses apxs2: + `apxs2 -cia mod_xsendfile.c` + * Mac users might want to build fat binaries: + `apxs -cia -Wc,"-arch i386 -arch x86_64" -Wl,"-arch i386 -arch x86_64" mod_xsendfile.c` +3. Restart apache +4. That's all. + +
+ +
+ +## Configuration + +### Headers + +* `X-SENDFILE` - Send the file referenced by this headers instead of the current response body +* `X-SENDFILE-TEMPORARY` - Like `X-SENDFILE`, but the file will be deleted afterwards. The file must originate from a path that has the `AllowFileDelete` flag set. + +### XSendFile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionEnables or disables header processing
SyntaxXSendFile on|off
DefaultXSendFile off
Contextserver config, virtual host, directory, .htaccess
+ +Setting `XSendFile on` will enable processing. + +The file specified in `X-SENDFILE` header will be sent instead of the handler output. + +The value (file name) given by the header is assmumed to be url-encoded, i.e. unescaping/url-decoding will be performed. See [XSendFileUnescape](#XSendFileUnescape). +If you happen to store files using already url-encoded file names, you must "double" encode the names... `%20 -> %2520` + +If the response lacks the `X-SENDFILE` header the module will not perform any processing. + +### XSendFileIgnoreEtag + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionIgnore script provided Etag headers
SyntaxXSendFileIgnoreEtag on|off
DefaultXSendFileIgnoreEtag off
Contextserver config, virtual host, directory, .htaccess
+ +Setting `XSendFileIgnoreEtag on` will ignore all ETag headers the original output handler may have set. +This is helpful for applications that will generate such headers even for empty content. + +### XSendFileIgnoreLastModified + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionIgnore script provided LastModified headers
SyntaxXSendFileIgnoreLastModified on|off
DefaultXSendFileIgnoreLastModified off
Contextserver config, virtual host, directory, .htaccess
+ +Setting `XSendFileIgnoreLastModified on` will ignore all Last-Modified headers the original output handler may have set. +This is helpful for applications that will generate such headers even for empty content. + +### XSendFileUnescape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionUnescape/url-decode the value of the header
SyntaxXSendFileUnescape on|off
DefaultXSendFileUnescape on
Contextserver config, virtual host, directory, .htaccess
+ +Setting `XSendFileUnescape off` will restore the pre-1.0 behavior of using the raw header value, instead of trying to unescape/url-decode first. +Headers may only contain a certain ASCII subset, as dictated by the corresponding RFCs/protocol. Hence you should escape/url-encode (and have XSendFile unescape/url-decode) the header value. Failing to keep within the bounds of that ASCII subset might cause errors, depending on your application framework. + +Hence this setting is meant only for backwards-compatibility with legacy applications expecting the old behavior; new applications should url-encode the value correctly and leave `XSendFileUnescape on`. Of course, if your paths are always ASCII, then (usually) no special encoding is required. + +### XSendFilePath + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionWhite-list more paths
SyntaxXSendFilePath `` [`AllowFileDelete`]
DefaultNone
Contextserver config, virtual host, directory
+ +XSendFilePath allow you to add additional paths to some kind of white list. All files within these paths are allowed to get served through mod_xsendfile. + +Provide an absolute path as Parameter to this directive. + +If the optional `AllowFileDelete` flag is specified, then files under this path can be served using the `X-SENDFILE-TEMPORARY` header, and will then be deleted once the file is delievered. Hence you should only set the `AllowFileDelete` flag for paths that do not hold any files that shouldn't be deleted! + +You may provide more than one path. + +#### Remarks - Relative paths + +The current working directory (if it can be determined) will be always checked first. + +If you provide relative paths via the X-SendFile header, then all whitelist items will be checked until a seamingly valid combination is found, i.e. the result is within the bounds of the whitelist item; it isn't checked at this point if the path in question actually exists. +Considering you whitelisted `/tmp/pool` and `/tmp/pool2` and your script working directory is `/var/www`. + +`X-SendFile: file` + +1. `/var/www/file` - Within bounds of `/var/www`, OK + +`X-SendFile: ../pool2/file` + +1. `/var/www/../pool2/file = /var/pool2/file` - Not within bounds of `/var/www` +2. `/tmp/pool/../pool2/file = /tmp/pool2/file` - Not within bounds of `/tmp/pool` +3. `/tmp/pool2/../pool2/file = /tmp/pool2/file` - Within bounds of `/tmp/pool2`, OK + +You still can only access paths that are whitelisted. However you have might expect a different behavior here, hence the documentation. + +**Please note:** It is recommended to always use absolute paths. + +#### Remarks - Inheritance + +The white list "inherits" entries from higher level configuration. + +
XSendFilePath /tmp
+
+  ServerName someserver
+  XSendFilePath /home/userxyz
+
+
+  ServerName anotherserver
+  XSendFilePath /var/www/somesite/
+  
+    XSendFilePath /var/www/shared
+  
+
+ +Above example will give: + +* * + * `/tmp` +* someserver + * `/tmp` + * `/home/userxyz` +* another + * `/tmp` + * `/var/www/somesite` + * `/var/www/shared` (for scripts* located in /var/www/somesite/fastcgis) + +*) Scripts, in this context, mean the actual script-starters. E.g. PHP as a handler will use the .php itself, while in CGI mode refers to the starter. + +_Windows_ users must include the drive letter to those paths as well. Tests show that it has to be in upper-case. + +### Example + +`.htaccess` + +

+XSendFile on
+
+ +`out.php` + +`... +if ($user->isLoggedIn()) +{ +    header("X-Sendfile: $path_to_somefile"); +    header("Content-Type: application/octet-stream"); +    header("Content-Disposition: attachment; filename=\"$somefile\""); +    exit; +} +?> +

Permission denied

+

Login first!

` + +## Limitations / Issues / Security considerations + +* The `Content-Encoding` header - if present - will be dropped, as the module cannot know if it was set by intention of the programmer or the handler. E.g. php with output compression enabled will set this header, but the replacement file send via mod_xsendfile is most likely not compressed. +* The header (X-SENDFILE) is not case-sensitive. +* **X-Sendfile will also happily send files that are otherwise protected (e.g. Deny from all).** + +
+ +
+ +## Credits + +The idea comes from [lighttpd](http://www.lighttpd.net/) - A fast web server with minimal memory footprint. + +The module itself was inspired by many other Apache2 modules such as mod_rewrite, mod_headers and obviously core.c. + +## License + +**Copyright 2006-2012 by Nils Maier** + +Licensed under the _Apache License, Version 2.0_ (the "License"); you may not use this file except in compliance with the License. + +You may obtain a copy of the License at +[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and limitations under the License. + +## Changes + +### Version 1.0 + +* Unescape/url-decode header value to support non-ascii file names +* `XSendFileUnescape` setting, to support legacy applications +* `X-SENDFILE-TEMPORARY` header and corresponding `AllowFileDelete` flag +* Fix: Actually look into the backend-provided headers for Last-Modified + +### Version 0.12 + +* Now incorrect headers will be dropped early + +### Version 0.11.1 + +* Fixed some documentation bugs +* Built win32 binaries against latest httpd using MSVC9 +* Updated MSVC Project files + +### Version 0.11 + +* Fixed large file support + +### Version 0.10 + +* Won't override Etag/Last-Modified if already set. +* New Configuration directive: XSendFileIgnoreEtag +* New Configuration directive: XSendFileIgnoreLastModified +* New Configuration directive: XSendFilePath +* Removed Configuration directive: XSendFileAllowAbove + Use XSendFilePath instead. +* Improved header handling for FastCGI/CGI output (removing duplicate headers). + +### Version 0.9 + +* New configuration directive: XSendFileAllowAbove +* Initial FastCGI/CGI support +* Filter only added when needed + +### Version 0.8 + +* This is the initial public release. + +
+ +