.htaccess Rewriterule Regex to apply only to files with certain words in it

I have the following code in my .htaccess file which puts a watermark on all my WordPress uploads. I am trying to work out how I can change the Regex to make it only apply to files that end with a certain filename.

RewriteRule (.*)wp-content/uploads/(.*.(jpe?g|gif|png))$ $1watermark.php?p=br&q=90&src=wp-content/uploads/$2

If there are files within the /uploads/ directory that end in example: ORIGINAL.jpg (full file name sunset-ORIGINAL.jpg) or ORIGINAL.gif, I want only those to have the watermark applied.

Read More

Is this something I can do with modifying the .htaccess Rewrite rule or should I be trying to achieve it inside the watermark.php file?

The code for watermark.php can be found here & below:

//we tell the server to treat this file as if it wore an image
header('Content-type: image/jpeg');
//image file path
$img = $_GET['src'];
//watermark position
$p = $_GET['p']; if(!$p) $p = 'br';
/*
p can be anything from the following list:
tl = top left
tc = top center
tr = top right
cl = center left
c = center of the image
cr = center right
bl = bottom left
bc = bottom center
br = bottom right
*/
//watermarked image quality
$q = $_GET['q'];
//if the quality field is missing or is not on the 0 to 100 scale then we set the quality to 93
if(!$q || $q<0 || $q>100) $q = '93';


$filetype = substr($img,strlen($img)-4,4);
$filetype = strtolower($filetype);
if($filetype == ".gif") $image = @imagecreatefromgif($img);
if($filetype == ".jpg") $image = @imagecreatefromjpeg($img);
if($filetype == ".png") $image = @imagecreatefrompng($img);
if (!$image) die();

//getting the image size for the original image
$img_w = imagesx($image);
$img_h = imagesy($image);
//if the filename has 150x150 in it's name then we don't apply the watermark
if (eregi("150x150", $img)) {
    imagejpeg($image, null, $q); die();
} else {
    $watermark = @imagecreatefrompng('watermark.png');
}
/*
//if you want to use the watermark only on bigger images then use this instead of the condition above
if ($img_w < "150") {//if image width is less then 150 pixels
    imagejpeg($image, null, $q); die();
} else {
    $watermark = @imagecreatefrompng('watermark.png');
}
*/

//getting the image size for the watermark
$w_w = imagesx($watermark);
$w_h = imagesy($watermark);

if($p == "tl") {
    $dest_x = 0;
    $dest_y = 0;
} elseif ($p == "tc") {
    $dest_x = ($img_w - $w_w)/2;
    $dest_y = 0;
} elseif ($p == "tr") {
    $dest_x = $img_w - $w_w;
    $dest_y = 0;
} elseif ($p == "cl") {
    $dest_x = 0;
    $dest_y = ($img_h - $w_h)/2;
} elseif ($p == "c") {
    $dest_x = ($img_w - $w_w)/2;
    $dest_y = ($img_h - $w_h)/2;
} elseif ($p == "cr") {
    $dest_x = $img_w - $w_w;
    $dest_y = ($img_h - $w_h)/2;
} elseif ($p == "bl") {
    $dest_x = 0;
    $dest_y = $img_h - $w_h;
} elseif ($p == "bc") {
    $dest_x = ($img_w - $w_w)/2;
    $dest_y = $img_h - $w_h;
} elseif ($p == "br") {
    $dest_x = $img_w - $w_w;
    $dest_y = $img_h - $w_h;
}

imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $w_w, $w_h);
imagejpeg($image, null, $q);
imagedestroy($image);
imagedestroy($watermark);

Related posts

Leave a Reply

1 comment

  1. Is this something I can do with modifying the .htaccess Rewrite rule
    or should I be trying to achieve it inside the watermark.php file?

    From an architectural standpoint, it’s better to just have the RewriteRule act on calling watermark.php and then add the robustness to watermark.php to differentiate which files should be acted on or ignored.

    The reason being as cool as .htaccess & related RewriteRule logic is, it really should only be used to quickly direct a web request from one thing to another. Adding a layer of “Is this file a JPEG? Okay, do this…” logic is a bit too much. It might be done, but the reality is it would all be better handled in one PHP script.

    And then within PHP you can add whatever robust levels of logic you best feel are need to decide if actions can be taken.

    Okay, looking at your code, look at these lines:

    $filetype = substr($img,strlen($img)-4,4);
    $filetype = strtolower($filetype);
    if($filetype == ".gif") $image = @imagecreatefromgif($img);
    if($filetype == ".jpg") $image = @imagecreatefromjpeg($img);
    if($filetype == ".png") $image = @imagecreatefrompng($img);
    if (!$image) die();
    

    $filetype is basically a file extension, right? And you only want to act on .gif, .jpg & .png files, right? Well look at this line:

    if (!$image) die();
    

    The logic to handle that is already there. This script will only act on files that are .gif, .jpg & .png files so there is no need to do any more work on that side.

    But I will say the logic in the script can be improved, but that is a whole other topic. As it stands, you are fine to send non-image files to this script since it will just die() if the file is not a .gif, .jpg & .png file anyway.

    EDIT: Okay, I saw in your comments you want the watermark.php script to only act on files that have the name ORIGINAL at the end of the name & before the extension, correct? Then you can modify watermark.php like this. First, find this line:

    //image file path
    $img = $_GET['src'];
    

    And then add a regex to check for the ORIGINAL at the end of .gif, .jpg & .png files like this:

    //image file path
    $img = $_GET['src'];
    // Check if the image has a '.gif', '.jpg' or '.png' extension.
    preg_match('/(?:ORIGINAL).(gif|jpg|png)$/', $img, $matches);
    if (empty($matches)) die();
    

    That said, this watermark.php has a major issue if you ask me: While it acts on GIF, JPEG & PNG files, the end product will all be a JPEG file as shown here on this line at the top:

    header('Content-type: image/jpeg');
    

    And this line at the bottom:

    imagejpeg($image, null, $q);
    

    Are you sure you want that? If I were you I would rework that code so a PNG stays a PNG, a GIF stays a GIF and a JPEG stays a JPEG. But that is out of the scope of this question & can be a nice project for you to tackle of you also feel the needs to be reworked.