We currently use an image resizer that was written in PHP. The resizing script takes advantage of caching, and writes the generated resized images to a cache directory (aptly named cache/).
The process is such that a rewritten URL, for example:
domain.com/img/250x250/some-image.jpg
Will be re-written to:
domain.com/image.php?width=250&height=250&src=some-image.jpg&function=resizeCrop
Inside image.php, we make a check to see whether a file matches the resize in the cache/ dir. All cached images are stored with a name of cachFunctionWidth_height_originalName, so for the given example the generated image file inside cache/ would be named resizecrop250_250_some-image.jpg
At the moment, we're utilizing PHP's fpassthru() function to output the file to the browser if it exists. If it doesn't we use a combination of GD functions and algorithms to output the file to the browser.
My question is whether it will be possible for us to bypass the image.php completely if a resized image exists in the cache directory using HTACCESS (it's a Linux server). Essentially, we need to check for a bastardized name form before serving rewriting.
For example, here's some pseudo-code of what we'd like to achieve, but I don't think it's possible:
User requests file > domain.com/img/250x250/some-image.jpg
Check if file cache/resizecrop250_250_some-image.jpg exists
If it does, rewrite to cache/resizecrop250_250_some-image.jpg
If it doesn't, rewrite to domain.com/image.php?width=250&height=250&src=some-image.jpg&function=resizeCrop
If this is not possible through HTACCESS, any other suggestions would also be welcome.
I believe using mod_rewrite it is possible. Consider following rule:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# check if constructed image name exists in cache directory
RewriteCond %{DOCUMENT_ROOT}/cache/resizecrop$1_$2_$3 -f
# exists, redirect to cache/constructed-image-file-name
RewriteRule ^img/([0-9]+)x([0-9]+)/([^.]+\.(?:jpe?g|gif|bmp|png))$ /cache/resizecrop$1_$2_$3 [L,NC]
# doesn't exist then forward to image.php with required query parameters
RewriteRule ^img/([0-9]+)x([0-9]+)/([^.]+\.(?:jpe?g|gif|bmp|png))$ /image.php?width=$1&height=$2&src=$3&function=resizeCrop [L,NC]
Related
I would like to check if users are logged in to access image files.
Images would have this form
https://domain.com/folders/imagename.jpg
I tried this in the .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI}\.jpg
RewriteRule ^(.*)\.jpg$ /protect.php
And this in my protect.php file
<?php
if(rcp_is_active()){
header('Content-Type: image/jpg');
readfile($imageurl);
}
else{
readfile("https://placeholdit.imgix.net/~text?txtsize=38&txt=Forbidden&w=400&h=400")
}
?>
My question:
How should I complete my .htaccess file to pass the filename.jpg to the php file?
Update your .htaccess RewriteRule to pass the matched filename to the PHP script as follows (your RewriteCondition is superfluous):
RewriteEngine On
RewriteRule ^((.*)\.jpg)$ /protect.php/$1
Then you can access the passes value using $_SERVER['PATH_INFO'] or $_SERVER['PATH_TRANSLATED'] (then Apache tries to map it to the real path according to document root, see mod_cgi and RFC 3875 for more information about this). For this to work AcceptPathInfo needs to be enabled in Apache httpd (the default).
or use
RewriteRule ^((.*)\.jpg)$ /protect.php?filename=$1
and use $_GET['filename']. Especially here, beware for directory traversal attacks (e.g., someone uses /protect.php?filename=../../someother-file.jpg). I usually apply realpath to normalize the path and check that it starts with the folder which contains the files or the document root ($_SERVER['DOCUMENT_ROOT']).
In both cases also make sure you only deliver allowed files (e.g., what happens if an attacker uses /protect.php/protect.php). This might leak sensitive data.
PS: Maybe you also want to make the response non-cacheable or provide a Content-Length.
PSS: Even for the forbidden case you also need to provide a proper Content-Type - or use a redirect (header('Status: 302'); and header("Location: https://placeholdit.imgix.net/~text?txtsize=38&txt=Forbidden&w=400&h=400");) so that you don't need to re-request that image again and again.
Please forgive me, but I'm VERY new to PHP, and even worse with url rewrites.
I'd like to write a PHP script that will dynamically output an image that will then be used as a signature on a forum that I belong to.
I have a base PHP file that I'm working with and will be editing that so I'm able to host it for other users of this forum.
The information will be stored in a database, and I'd like to call the PHP script with a PNG URL
Example:
http://somedomain.com/somecode.png
rewriting that to
http://somedomain.com/sig_img.php?img=somecode
Where somecode is the database table primary index.
I don't really need help with the PHP script (yet), but I have no clue where to begin with the .htaccess mod_rewrite code.
Thank you all for any assistance!
Assuming that mod_rewrite is enabled, something like this should work:
<Location />
RewriteEngine On
# ensure requested resource is not a file.
RewriteCond %{SCRIPT_FILENAME} !-f
# ensure requested resource is not a directory.
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*\.png)$ sig_img.php?img=$1 [NC,L]
</Location>
This will redirect any request that is a not a file or directory to the script sig_img.php with the requested filename as the parameter. You may want to restrict this to only .PNG file requests, in which case please read about the options.
Make sure you treat the request as untrusted and parameterise the input; don't just concatenate $_GET['img'] into your query string.
I'm not the best with mod rewrite so if anybody can help me out here that would be great.
I'm using a markdown processor script and it's using rewrite to grab any files that end with a markdown file type. However, I'd like this script to grab any files within a folder, rather than any files that end with the markdown file type.
Here's the htaccess:
# display Markdown as HTML by default
RewriteEngine on
RewriteRule .+\.(markdown|mdown|md|mkd)$ /static/includes/markdown/render.php
RewriteRule .+\.(markdown|mdown|md|mkd)\-text$ /static/includes/markdown/render.php [L]
Is there a way to grab all files within a folder called (let's say) "folder" and eliminate the file type on the end?
So maybe have a URL like
website.com/home
that actually is
website.com/home.md
and is processed with the markdown script?
Hope this makes sense.
The re-write module and it's .htaccess files actually work on a per folder basis. Usually one would have a main .htaccess file in the web root of a site/server. However you can add numerous .htaccess files throughout your site's folder structure giving each individual folder specific rules.
All you would have to do is add another .htaccess file to your markdown folder and enable it to parse URL's without file extensions, forwarding it to a script which will be able to detect what original file was requested -
RewriteEngine on
RewriteRule ^(.*)$ /static/includes/markdown/render.php?file=$1 [L,QSA]
Basically what is happening here is that any file requested within this folder will be passed through your render.php file.
Now in your render.php file, you would have a $_GET parameter of file containing the original URL. For a url of http://example.com/markdown/foo, your render.php would have foo in the file parameter -
/static/includes/markdown/render.php?file=foo
If you set the correct headers in render.php it will be able to print out any format of file, hiding it's extension in a "fake" URL.
Ok, I am starting to wonder if this is even possible. I have been pouring over htaccess tutorials and examples and I just can't seem to get it working right.
I have a script that creates dynamic images running in a directory on a friends website. I have access to / but the actual directory I am using is in /mydir/. In order to display the images they are output to png via PHP. I have the following RewriteRule setup to take the filename requested and run a PHP script. Each filename represents a separate file with a serialized object used in the display.php script
RewriteRule ^(.*)\.jpg$ display.php?file=$1
That part is working fine, however if someone requests a file that doesn't exist it just throws PHP errors because the script gets called but there is no object for it to use.
What I am trying to do now, and utterly failing at, is to have it check if the file exists in ./Cache/ directory then run the script as usual and if not then the server can just throw a standard 404.
I have tried things like
RewriteCond %{REQUEST_URI} ^(.*)\.jpg$
RewriteCond %{DOCUMENT ROOT}/img/Cache/%1.jpg -f
and other combinations of REQUEST_URI, REQUEST_URL, SCRIPT_FILENAME, SCRIPT_NAME, etc. I can't seem to come up with the proper variable and regex expression to handle this so I am turning to you guys for help. The biggest problem is not knowing what is actually in each of those variables so I can see where I am going wrong. I would kill for some kind of var_dump(),
Use this rule:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/mydir/img/Cache/$1.jpg -f
RewriteRule ^(.*)\.jpg$ display.php?file=$1 [L]
This needs to be placed into .htaccess file in /mydir/img folder
If you move this folder somewhere else or rename parent folder, you will need update it as well in RewriteCond line.
If you wish you can try this approach, which is more flexible (no need to specify parent folder names) but I cannot guarantee that this will work on your setup (but it DOES work on my PC):
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ^(.*)/([^/]+)\.jpg$
RewriteCond %1/Cache/%2.jpg -f
RewriteRule ^(.*)\.jpg display.php?file=$1 [L]
Here the current physical folder is determined automatically from requested URL. But if you have symbolic links or some other settings, it may produce incorrect results. Plus .. it has 1 more Condition .. which makes it a bit slower (1 extra regex to check).
I would use the PHP file to check it:
use file_exists in your PHP and if it does not exist, use header("HTTP/1.0 404 Not Found"); or header('Location to a 404 image
I have a website, which has numerous subdirectories already. (All existing in server's filesystem)
I want to create new "virtual" sub-dirs with htaccess, but I only want the htaccess rule work for directories, listed in DB, and not existing in filesystem.
i.e.
File system has: /dir1/ & /dir2/
MySQL database has record for 'dir3' & 'dir4'
And I want:
A: mysite.com/dir1/ and mysite.com/dir2/ display existing old content
B: mysite.com/dir3/ and mysite.com/dir4/ display content from MySQL provided by PHP sctipt via redirect like:
mysite.com/myscript.php?dir=dir3
C: mysite.com/dir5/ display 404 error (Dir does not exist in DB nor in Database)
Basically I want .htaccess to work like this:
IF DIR Exists in DB - apply the rewrite rule and show content from myscript.php?dir=DIR
ELSE don't apply any rule.
I can create a separate php script, which can return 0/1 when given dir name exist in DB or not, but how do I make mod_rewrite get the data from that script?
Is it possible with htaccess/PHP at all?
Option 1: Make following htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ _redirect.php/$1 [L]
Which will redirect all dirs and files that don't exist physically to php script. Inside that script you can manually parse requested url and check your mysql table what to do next - forward or return 404.
Option 2: If your table with folders doesn't change often and/or you need speed, generate your htaccess file from php after table has changed, and map there all virtual folders from db.
You can't do a check like that in .htaccess afaik. I would try to hardcode the old content folders into the .htaccess and use a pattern to rewrite the rest.