/** * Render the image to the output. */ public function render() { if (!$this->media || !$this->media->canShow()) { Log::addMediaLog('Image Builder error: >' . I18N::translate('Missing or private media object.')); $this->renderError(); } $serverFilename = $this->media->getServerFilename(); if (!file_exists($serverFilename)) { Log::addMediaLog('Image Builder error: >' . I18N::translate('The media object does not exist.') . '< for path >' . $serverFilename . '<'); $this->renderError(); } $mimetype = $this->media->mimeType(); $imgsize = $this->media->getImageAttributes(); $filetime = $this->media->getFiletime(); $filetimeHeader = gmdate('D, d M Y H:i:s', $filetime) . ' GMT'; $expireHeader = gmdate('D, d M Y H:i:s', WT_TIMESTAMP + $this->getExpireOffset()) . ' GMT'; $type = Functions::isImageTypeSupported($imgsize['ext']); $usewatermark = false; // if this image supports watermarks and the watermark module is intalled... if ($type) { $usewatermark = $this->isShowWatermark(); } // determine whether we have enough memory to watermark this image if ($usewatermark) { if (!FunctionsMedia::hasMemoryForImage($serverFilename)) { // not enough memory to watermark this file $usewatermark = false; } } $etag = $this->media->getEtag(); // parse IF_MODIFIED_SINCE header from client $if_modified_since = 'x'; if (!empty(Filter::server('HTTP_IF_MODIFIED_SINCE'))) { $if_modified_since = preg_replace('/;.*$/', '', Filter::server('HTTP_IF_MODIFIED_SINCE')); } // parse IF_NONE_MATCH header from client $if_none_match = 'x'; if (!empty(Filter::server('HTTP_IF_NONE_MATCH'))) { $if_none_match = str_replace('"', '', Filter::server('HTTP_IF_NONE_MATCH')); } // add caching headers. allow browser to cache file, but not proxy header('Last-Modified: ' . $filetimeHeader); header('ETag: "' . $etag . '"'); header('Expires: ' . $expireHeader); header('Cache-Control: max-age=' . $this->getExpireOffset() . ', s-maxage=0, proxy-revalidate'); // if this file is already in the user’s cache, don’t resend it // first check if the if_modified_since param matches if ($if_modified_since === $filetimeHeader) { // then check if the etag matches if ($if_none_match === $etag) { http_response_code(304); return; } } // send headers for the image header('Content-Type: ' . $mimetype); header('Content-Disposition: filename="' . addslashes(basename($this->media->getFilename())) . '"'); if ($usewatermark) { // generate the watermarked image $imCreateFunc = 'imagecreatefrom' . $type; $imSendFunc = 'image' . $type; if (function_exists($imCreateFunc) && function_exists($imSendFunc)) { $im = $imCreateFunc($serverFilename); $im = $this->applyWatermark($im); // send the image $imSendFunc($im); imagedestroy($im); return; } else { // this image is defective. log it Log::addMediaLog('Image Builder error: >' . I18N::translate('This media file is broken and cannot be watermarked.') . '< in file >' . $serverFilename . '< memory used: ' . memory_get_usage()); } } // determine filesize of image (could be original or watermarked version) $filesize = filesize($serverFilename); // set content-length header, send file header('Content-Length: ' . $filesize); // Some servers disable fpassthru() and readfile() if (function_exists('readfile')) { readfile($serverFilename); } else { $fp = fopen($serverFilename, 'rb'); if (function_exists('fpassthru')) { fpassthru($fp); } else { while (!feof($fp)) { echo fread($fp, 65536); } } fclose($fp); } }
/** * Get the filename on the server - for those (very few!) functions which actually * need the filename, such as mediafirewall.php and the PDF reports. * * @param string $which * * @return string */ public function getServerFilename($which = 'main') { $MEDIA_DIRECTORY = $this->tree->getPreference('MEDIA_DIRECTORY'); $THUMBNAIL_WIDTH = $this->tree->getPreference('THUMBNAIL_WIDTH'); if ($this->isExternal() || !$this->file) { // External image, or (in the case of corrupt GEDCOM data) no image at all return $this->file; } elseif ($which == 'main') { // Main image return WT_DATA_DIR . $MEDIA_DIRECTORY . $this->file; } else { // Thumbnail $file = WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $this->file; // Does the thumbnail exist? if (file_exists($file)) { return $file; } // Does a user-generated thumbnail exist? $user_thumb = preg_replace('/\\.[a-z0-9]{3,5}$/i', '.png', $file); if (file_exists($user_thumb)) { return $user_thumb; } // Does the folder exist for this thumbnail? if (!is_dir(dirname($file)) && !File::mkdir(dirname($file))) { Log::addMediaLog('The folder ' . dirname($file) . ' could not be created for ' . $this->getXref()); return $file; } // Is there a corresponding main image? $main_file = WT_DATA_DIR . $MEDIA_DIRECTORY . $this->file; if (!file_exists($main_file)) { Log::addMediaLog('The file ' . $main_file . ' does not exist for ' . $this->getXref()); return $file; } // Try to create a thumbnail automatically try { $imgsize = getimagesize($main_file); // Image small enough to be its own thumbnail? if ($imgsize[0] > 0 && $imgsize[0] <= $THUMBNAIL_WIDTH) { try { copy($main_file, $file); Log::addMediaLog('Thumbnail created for ' . $main_file . ' (copy of main image)'); } catch (\ErrorException $ex) { Log::addMediaLog('Thumbnail could not be created for ' . $main_file . ' (copy of main image)'); } } else { if (FunctionsMedia::hasMemoryForImage($main_file)) { try { switch ($imgsize['mime']) { case 'image/png': $main_image = imagecreatefrompng($main_file); break; case 'image/gif': $main_image = imagecreatefromgif($main_file); break; case 'image/jpeg': $main_image = imagecreatefromjpeg($main_file); break; default: return $file; // Nothing else we can do :-( } if ($main_image) { // How big should the thumbnail be? $width = $THUMBNAIL_WIDTH; $height = round($imgsize[1] * ($width / $imgsize[0])); $thumb_image = imagecreatetruecolor($width, $height); // Create a transparent background, instead of the default black one imagesavealpha($thumb_image, true); imagefill($thumb_image, 0, 0, imagecolorallocatealpha($thumb_image, 0, 0, 0, 127)); // Shrink the image imagecopyresampled($thumb_image, $main_image, 0, 0, 0, 0, $width, $height, $imgsize[0], $imgsize[1]); switch ($imgsize['mime']) { case 'image/png': imagepng($thumb_image, $file); break; case 'image/gif': imagegif($thumb_image, $file); break; case 'image/jpeg': imagejpeg($thumb_image, $file); break; } imagedestroy($main_image); imagedestroy($thumb_image); Log::addMediaLog('Thumbnail created for ' . $main_file); } } catch (\ErrorException $ex) { Log::addMediaLog('Failed to create thumbnail for ' . $main_file); } } else { Log::addMediaLog('Not enough memory to create thumbnail for ' . $main_file); } } } catch (\ErrorException $ex) { // Not an image, or not a valid image? } return $file; } }
$type = isImageTypeSupported($imgsize['ext']); $usewatermark = false; // if this image supports watermarks and the watermark module is intalled... if ($type) { // if this is not a thumbnail, or WATERMARK_THUMB is true if ($which === 'main' || $WT_TREE->getPreference('WATERMARK_THUMB')) { // if the user’s priv’s justify it... if (Auth::accessLevel($WT_TREE) > $WT_TREE->getPreference('SHOW_NO_WATERMARK')) { // add a watermark $usewatermark = true; } } } // determine whether we have enough memory to watermark this image if ($usewatermark) { if (!FunctionsMedia::hasMemoryForImage($serverFilename)) { // not enough memory to watermark this file $usewatermark = false; } } $watermarkfile = ''; $generatewatermark = false; if ($usewatermark) { if ($which === 'thumb') { $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/thumb/' . $media->getFilename(); } else { $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/' . $media->getFilename(); } if (!file_exists($watermarkfile)) { // no saved watermark file exists // generate the watermark file