pcuser42
pcuser42

Reputation: 85

PHP code running twice under certain conditions

I'm having this strange issue where when certain conditions are met my PHP code is run twice. My code adds a watermark to a JPEG image (done in PHP to allow me to change the watermark quickly if necessary), and resized if requested. To speed up requests the processed images are cached. Whenever the image is loaded I'm incrementing a view counter, however when the following happens the counter is increased by 2:

Here's my code:

<?php
require_once("../config.php");
if (empty($_GET['photoid'])) {
    header("Location: /photos");
    die();
}
$photoId = intval($_GET['photoid']);
$photo = getPhotoData($photoId);
if ($photo == null) {
    http_response_code(404);
    echo "That photo doesn't exist.";
} else {
    $filename = $photo['photo_filename'];

    $largePath = "large/";
    $cachePath = $largePath . "view_cache/";
    $cache = false;

    if (!isset($_GET['admin']) && !isset($_GET['thumb']) && !isset($_GET['tile'])) {
        incrementPhotoViewCount($photoId);
    }

    if (isset($_GET['height'])) {
        list($originalWidth, $originalHeight) = getimagesize($largePath . $photo['photo_filename']);
        $height = min(intval($_GET['height']), $originalHeight);
        if (file_exists($cachePath . $height . "h" . $filename)) {
            $im = imagecreatefromjpeg($cachePath . $height . "h" . $filename);
            $cache = true;
        } else {
            $im = resizeImage($largePath . $photo['photo_filename'], $originalWidth, $height);
        }
    } else if (isset($_GET['width'])) {
        list($originalWidth, $originalHeight) = getimagesize($largePath . $photo['photo_filename']);
        $width = min(intval($_GET['width']), $originalWidth);
        if (file_exists($cachePath . $width . "w" . $filename)) {
            $im = imagecreatefromjpeg($cachePath . $width . "w" . $filename);
            $cache = true;
        } else {
            $im = resizeImage($largePath . $photo['photo_filename'], $width, $originalHeight);
        }
    } else {
        if (file_exists($cachePath . $filename)) {
            $im = imagecreatefromjpeg($cachePath . $filename);
            $cache = true;
        } else {
            $im = imagecreatefromjpeg($largePath . $photo['photo_filename']);
        }
    }

    if (!$cache && ((!isset($height) || $height > 400) && (!isset($width) || $width > 350))) {
        $watermark = imagecreatefrompng("../images/watermark.png");

        //Preserve original watermark transparency
        imagealphablending($watermark, true); // setting alpha blending on
        imagesavealpha($watermark, true); // save alphablending setting (important)

        //Set the margins for the watermark and get the height/width of the stamp image
        $marginLeft = 20;
        $marginBottom = 20;
        $sx = imagesx($watermark);
        $sy = imagesy($watermark);

        //Merge the stamp onto our photo
        imagecopy($im, $watermark, $marginLeft, imagesy($im) - $sy - $marginBottom, 0, 0, $sx, $sy);
    }

    //Output the image and free memory
    header("Content-Type: image/jpeg");
    imagejpeg($im);
    if (!$cache) {
        if (isset($_GET['height'])) {
            imagejpeg($im, $cachePath . $height . "h" . $filename);
        } else if (isset($_GET['width'])) {
            imagejpeg($im, $cachePath . $width . "w" . $filename);
        } else {
            imagejpeg($im, $cachePath . $filename);
        }
    }
    imagedestroy($im);
}

function resizeImage($file, $w, $h, $crop = false) {
    list($width, $height) = getimagesize($file);
    $r = $width / $height;
    if ($crop) {
        if ($width > $height) {
            $width = ceil($width-($width*abs($r-$w/$h)));
        } else {
            $height = ceil($height-($height*abs($r-$w/$h)));
        }
        $newwidth = $w;
        $newheight = $h;
    } else {
        if ($w/$h > $r) {
            $newwidth = $h*$r;
            $newheight = $h;
        } else {
            $newheight = $w/$r;
            $newwidth = $w;
        }
    }
    $src = imagecreatefromjpeg($file);
    $dst = imagecreatetruecolor($newwidth, $newheight);
    imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);

    return $dst;
}

Here's the code that updates the view counter:

function incrementPhotoViewCount($photoId) {
    $photoId = intval($photoId);

    if (!($stmt = $GLOBALS['mysqli']->prepare("UPDATE `Photo` SET `view_count` = `view_count` + 1 WHERE `photo_id` = ?"))) {
        error_log("Prepare failed: (" . $GLOBALS['mysqli']->errno . ") " . $GLOBALS['mysqli']->error);
        return false;
    }

    if (!$stmt->bind_param("i", $photoId)) {
        error_log("Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error);
        return false;
    }

    if (!$stmt->execute()) {
        echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
        return false;
    }
}

What's going on here?

Upvotes: 0

Views: 149

Answers (1)

pcuser42
pcuser42

Reputation: 85

Some extra late-night Googling answered my question - turns out Firefox has a bug which causes it to load dynamically generated images twice when loaded directly. It's fine when loaded through an <img> tag, and all other browsers behave normally. Something to look at for anyone else having this issue :)

Upvotes: 1

Related Questions