Include file (header) using htaccess - .htaccess

I want to include a certain file with every page-call.
For simplicity, assume I have a header which should be pre-pended to every file.
(Eg. a php script which checks all sorts of user agent stuff.)
I could use mod_rewrite to send all requests to this file, and then use PHP to include the requested page into the file, but that could be a headache with paths and whatnot, and I would rather not use mod_rewrite if not needed.
I recall there being a 'include' call in htaccess, but the only thing I can find in a search is ServerSideIncludes - which is not what I need. SSI (I gather) scans the document looking for a call, whereas I need to include this file before going onto the file being called.

Aside from SSI's there's also a PHP-specific option for including header/footer file with every PHP page so this solution may be too limit for you:
In .htaccess:
php_value auto_prepend_file /www/root/header.php
php_value auto_append_file /www/root/footer.php

Related

Include another htaccess file from .htaccess

Is it possible to do include rules from another htaccess file in .htaccess ?
.htaccess
RewriteEngine On
RewriteCond ...
RewriteRule ...
Include .htaccess1
.
.
Include .htaccess2
Doing this gives a 500. Include not allowed here
Is there a way to do this ? Because I need this pretty badly.
You can't include rules, statements, definitions, or directives from other files from an htaccess file. The Include directive can't be used inside an htaccess file. Part of the point of an htaccess file is to act similarly to a <Directory> block but be self contained and unable to access things outside of the directory itself (subdirectories are ok) but more specifically nothing outside of the document root. This way, someone doing malicious things won't be able to point requests or include files/content from other directories by hacking the htaccess file.
In the scope of mod_rewrite specifically, there are options for the RewriteOptions that allow inheriting rewrite rules from the htaccess file from a parent directory, but nothing to arbitrarily include rules from anywhere.
I know this may be a little late, but instead if you are attempting to implement an IP ban, or similar type of dynamic rule content, use the very last rule in your .htaccess file to point the request at a single .php or similar languaged script that performs this function (your single script can load the dynamic rules in your own format and make that same decision as Apache would have depending on what your actually trying to accomplish) then passes the request on to the actual page being requested. It adds a layer to the whole request processing, but gives the same dynamic function to all pages without the need to generate direct rules for the server and attempting to have Apache make the decisions for you.
Just thought I would add this thought for anyone else who may stumble across this post looking for something similar.
It is possible - in 2-3 steps...
Create your file of IPs to Deny. It could be a .php file, .txt file, even .csv file.
Create a .php (or language of your choice) script, which purpose is to output a file named ".htaccess".
Every time you update your file of IPs to Deny, run the said 2) .php script, and output a new .htaccess, to each of your Domains.
If you have statements in addition to IPs to Deny, hard code them in your .php script to output first. See https://www.askapache.com/htaccess/
The .php script could generically look like:
$output = "statement1".PHP_EOL;
$output .= "statement2".PHP_EOL;
$output .= "statement3".PHP_EOL;
...
Then, when you're ready for the DENY portion:
$denyList = file_get_contents("the/list/of/IPs.txt"); // or .php etc.
$ArrayDenyList = explode(PHP_EOL,$denyList); // or your line ending character, if necessary
foreach($ArrayDenyList as $key =>$value) {
$output .= 'Deny from '.$value.PHP_EOL;
}
Then write the file: (you probably have a standard way):
$handle = fopen(.htaccess,"w"); //complete path if in another domain
fwrite($handle,$output);
fclose($handle);
echo "Success - <p>";
If you have more than one Domain, then have an Array of those Domain name's path, and foreach that Array, and fwrite to each path.
If some Domains already have .htaccess requirements, put that in a readable .txt file... do a file_get_contents(on that), "output =" that, add the "Deny's, then "output .= ..." each in a "foreach()" loop.
Anyway... you've done all these things before... just apply each technique to this scenario.
An .htaccess file can't "include()" other files, but a .php script can, and .php scripts can output files named ".htaccess", that can be built by script.
The above method works, and I started doing it when I needed to create rows of "RewriteRule" for each of my catalog of products! Every time I add a new product, I run my script that outputs a fresh .htaccess file... built from my SQL table of products. Similar to my .php script that "fwrite"s my sitemap.xml.
(I hope no .php punctuation or "$"s got lost in this typing.)
You can create server side script like PHP ".htaccess.php" and inside put your includes. Of course, you must configure apache:
AccessFileName .htaccess.php

.htaccess for download of file if query string matches

I have a PDF section that I want to give users the option to either view the file in their browser, or download it to their computer. I do not want to duplicate the files so have hit upon the idea of using a query string to tell the server the force the file to download, e.g.
FileName
In my .htaccess file for the pdfs folder, what do I need to put force the file to download if the query string is present?
What I have at the moment forces every pdf to download (instead of view):
<Files *.pdf>
ForceType applicaton/octet-stream
</Files>
You can do something like this with mod_rewrite:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^view=download$
RewriteRule .*\.pdf$ - [L,T=applicaton/octet-stream]
http://httpd.apache.org/docs/current/rewrite/flags.html#flag_t
P.S.
Depending on your rewrite logic (if you have any) you may need to remove the L, flag.
The above rule will work for URLs that end with .pdf and having view=download as query string EXACTLY. This means that it will work for example.com/some/file/here/hello.pdf?view=download but will not work for example.com/some/file/here/hello.pdf?view=download&var1=param1. To have it working for such scenario as well you will have to adjust the rule accordingly (but considering the URL examples you have provided in your Question, it should not happen).

How do I use .htaccess to limit file uploads to .pdf?

I have a simple upload form that allows a file to be uploaded to a folder in the site. I don't want to allow anything but .pdf files to be uploaded. However, I cannot modify the form at all to limit the upload. And I can't use PHP on the back end to limit it either. Javascript is unsecure because a user can turn it off. How can I limit the upload to a .pdf file with .htaccess?
As far as I know, it isn't possible. You could, however, restrict the files being returned, and force their mime type to be application/pdf, so they will be treated like PDFs, even if they aren't. If this was combined with JavaScript, it would help honest users (ex, if someone accidentally selects a .jpg they will get a warning right away), and it will make attacks more difficult.
It seems like the third-party mod_upload might be able to help, though.
To restrict the output types, you could use a .htaccess file similar to this:
# Prevent request to non-.pdf files
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ! \.pdf$
RewriteRule (.*) $1 [F]
# Tell the browser that this is a PDF
Header set Content-Type application/pdf
# Hint that the browser shouldn't try to auto-detect the content type
Header set X-Content-Type-Options nosniff
(note: I wrote those from memory, so make sure to test them before you trust them…)

How to specify named subfolders in htaccess?

I have a folder structure like this /img/products/{product name}/ and then the sub folders hi, low, and thumb.
I want to use htacess to force-download any files in a 'hi' or 'low' subfolder (but not 'thumb').
I was hoping something like this would work:
<FilesMatch "\(.*)(\/hi|\/low)(.*)">
ForceType applicaton/octet-stream
</FilesMatch>
Now I'm not great with regex, but that seems to work in regex testers against paths like
/img/products/active/low/something.jpg
However it's not working on the site.
Any suggestions?
Thanks
Pete
This probably should have been a ServerFault question based on what I think that you're trying to do, but since you actually can't do what you're trying to do (the way I think you're trying to do it), I'll provide two alternatives; one that likely won't work, and another that involves a PHP script (which should hopefully be alright for you, since your question history shows you asking something about PHP before).
The Problem:
First, what I think you're trying to do, so you can correct me if I'm wrong:
# Apply ForceType to anything that's in a path that matches this
<FilesMatch "img/products/[^/]+/(hi|low)/[^/]+$">
ForceType applicaton/octet-stream
</FilesMatch>
However, this won't work, because FilesMatch only examines the filename, under the assumption that you could either appropriately place the .htaccess file, or combine the directive with a Directory statement in the server or virtual server configuration.
In your case though, this isn't possible (Well, I assume anyway, maybe you do have access to the necessary configurations, but since your question is tagged .htaccess I'm guessing probably not), given that copying a .htaccess file to every folder isn't realistic.
The Solutions:
As it turns out, mod_rewrite, along with performing all sorts of voodoo in the way of filename resolution, also gives you extensions of other Apache functionality that you would not necessarily have been able to use otherwise. Case in point, we can set the MIME type using the T flag, making the easiest solution this:
RewriteEngine On
# Force the MIME-type, but don't actually perform a rewrite
RewriteRule ^img/products/[^/]+/(hi|low)/[^/]+$ - [T=application/octet-stream]
This actually works pretty well, but chances are good that your Apache installation thinks that it knows better than you, and includes a mimes.types file in the main configuration that maps the jpg extension to image/jpeg. This value takes precedence over the RewriteRule, making it ineffective in that case.
The other solution is to create a small script that acts as the go-between, passing the appropriate headers and image data from the server to the client. You would then use mod_rewrite to pass the request on to that script:
RewriteEngine On
# For an added bit of sanity, make the test pattern even more restrictive
RewriteRule ^img/products/[A-Za-z._-]+/(hi|low)/[A-Za-z._-]\.[A-Za-z]+$ imageDownloader.php
As for the script itself, to keep this answer from getting ridiculously long, I suggest taking a look at this answer or one of the other questions on this topic, keeping in mind that it's imperative that you screen the filenames that can be downloaded for reasons of security. Note that you would be able to get the original request path from $_SERVER['REQUEST_URI'], and could use that to locate the proper image.

Having huge redirect list in .htaccess a Problem?

I want to redirect every post 301 redirect, but I have over 3000 posts.
If I list
Redirect permanent /blog/2010/07/post.html http://new.blog.com/2010/07/23/post/
Redirect permanent /blog/2010/07/post1.html http://new.blog.com/2010/07/24/post1/
Redirect permanent /blog/2010/07/post2.html http://new.blog.com/2010/07/25/post2/
Redirect permanent /blog/2010/07/post3.html http://new.blog.com/2010/07/26/post3/
Redirect per......
for over 3000 url redirect command in .htaccess would this eat my server resource or cause some problem? Im not sure how .htaccess work but if the server is looking at these lists each time user requests for page, I would guess it will be a resource hog.
I can't use RedirectMatch because I added date variable in my new url. Do you have any other suggestions redirecting these posts? Or am I just fine?
Thanks!
I am not an Apache expert, so I cannot speak to whether or not having 3,000 redirects in .htaccess is a problem (though my gut tells me it probably is a bad idea). However, as a simpler solution to your problem, why not use mod_rewrite to do your redirects?
RewriteRule ^/blog/(.+)/(.+)/(.+).html$ http://new.blog.com/$1/$2/$3/ [R=permanent]
This uses a regex to match old URLs and rewrite them to new ones. The [R=permanent] instructs mod_rewrite to issue a 301 with the new URL instead of silently rewriting the request internally.
In your example, it looks like you've added the day of the post to the URL, which does not exist in the old URL. Since you obviously cannot use a regexp to divine the day an arbitrary post was made, this method may not work for you. If you can drop the day from the URL, then you're good to go.
Edit: The first time I read your question, I missed the last paragraph. ("I can't use RedirectMatch because I added date variable in my new url.") In this case, you can use mod_rewrite's RewriteMap to lookup the day component of a post.
You have two options:
Use a hashmap to perform fast lookups in a static file. This means all your old URLs will work, but any new posts cannot be accessed using the old URL scheme.
Use a script to grab the day.
In option one, create a file called posts.txt and put:
/yyyy/mm/pppp dd
...for each post where yyyy is the year of the post, mm is the month, and pppp is the post name (without the .html).
When you're done, run:
$ httxt2dbm -i posts.txt -o posts.map
Then we add to to the server/virtual server config: (Note the path is a filesystem path, not a URL.)
RewriteMap postday dbm:/path/to/file/posts.map
RewriteRule ^/blog/(.+)/(.+)/(.+).html$ http://new.blog.com/$1/$2/${postday:$1/$2/$3}/$3/ [R=permanent]
In option two, use pgm:/path/to/script/lookup.whatever as your RewriteMap. See the mod_rewrite documentation for more info about using a script.
Doing the lookup in mod_rewrite is better than just redirecting to a script which looks up the date and then redirects to the final destination because you should never redirect more than once. Issuing a 301 or 302 incurs a round trip cost, which increases the latency of your page load time.
If you have some way in code to determine the day of a post, you can generate the rewrite on the fly. You can setup a mod_rewrite pattern, something like .html and set up a front controller pattern to calculate the new url from the old and issue the 301 header.
With php as an example:
$_SERVER['REQUEST_URI']
will contain the requested url and
header("Location: http://new.blog.com/$y/$m/$d/$title/",TRUE,301);
will send a redirect.
That's... a lot of redirects. But the first thing I would tell you, and probably the only thing I can tell you without qualification, is that you should run some tests and see what the access times for your blog are like, and also look at the server's CPU and memory usage while you're doing it. If they're fairly low even with that giant list of redirects, you're okay as long as your blog doesn't experience a sudden increase in traffic. (I strongly suspect the 3000 rewrites will be slowing Apache down a lot, though)
That being said, I would second josh's suggestion of replacing the redirects with something dynamic. Like animuson said, if you're willing to drop the day from the URL, it'll be easy to set up a RewriteRule directive to handle the redirection. Otherwise, you could do it with a PHP script, or generally some code in whatever scripting language you (can) use. If you're using one of the popular blog engines, it probably contains code to do this already. Basically you could do something like
RewriteRule .* /blog/index.php
and just let the PHP script sort out which post was requested. It has access to the database so it'll be able to do that, and then you can either display the post directly from the PHP script, or to recover your original redirection behavior, you can send a Location header with the correct URL.
An alternative would be to use RewriteMap, which lets you write a RewriteRule where the target is determined by a program or file of your choice instead of being directly specified in the configuration file. As one option, you can specify a text file that contains the old and new URLs, and Apache will handle searching the file for the appropriate line for any given request. Read the documentation (linked above) for the full details. I will mention that this isn't used very often, and I'm not sure how much faster it would be compared to just having 3000 redirects.
Last tip: Apache can be significantly faster if you're able to move the configuration directives (like Redirect) into the server or virtual host configuration file, and disable reading of .htaccess entirely. I would guess that moving 3000 directives from .htaccess into the virtual host configuration could make your server considerably faster. But even moving the directives into the vhost config file probably wouldn't produce as much of a speedup as using a single RewriteRule.
It's never a good idea to make a massive list of Redirects. A better programming technique is to simply redirect the pages without that date variable then have a small PHP snippet that detects if it's missing and redirects to the URL with it included. The long list looks tacky and slows down Apache because it's checking that URL (any every other URL that might not even be affected by this) against each line. If it were only 5 or so, I'd say fine, but 3,000 is a definite NO.
Although I'm not a big fan of this method, a better choice would be to redirect all those URLs normally using a single match statement, redirecting them to the page without the date part, or with a dash or something, then include a small PHP snippet to check if the date is valid and if not, rewrite the path again to the correctly formed URL.
Honestly, if you didn't have that part there before, you don't need it now, and it will probably just confuse the search engines changing the URL for 3,000 posts. You don't really need a date in the URL, a good title is much more meaningful not only to users, but also to search engines, than a bunch of numbers.

Resources