Server IP : 15.235.198.142 / Your IP : 216.73.216.34 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ballsack 6.8.0-45-generic #45-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 30 12:02:04 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/rhodeworks/wp-content/plugins/nextgen-gallery/src/DataStorage/ |
Upload File : |
<?php namespace Imagely\NGG\DataStorage; // 0.9.10 is compatible with PHP 8.0 but requires 7.2.0 as its minimum. if ( version_compare( phpversion(), '7.2.0', '>=' ) ) { require_once NGG_PLUGIN_DIR . 'lib' . DIRECTORY_SEPARATOR . 'pel-0.9.12/autoload.php'; } else { require_once NGG_PLUGIN_DIR . 'lib' . DIRECTORY_SEPARATOR . 'pel-0.9.9/autoload.php'; } use Imagely\NGG\Display\I18N; use lsolesen\pel\PelDataWindow; use lsolesen\pel\PelJpeg; use lsolesen\pel\PelTiff; use lsolesen\pel\PelExif; use lsolesen\pel\PelIfd; use lsolesen\pel\PelTag; use lsolesen\pel\PelEntryShort; use lsolesen\pel\PelInvalidArgumentException; use lsolesen\pel\PelIfdException; use lsolesen\pel\PelInvalidDataException; use lsolesen\pel\PelJpegInvalidMarkerException; class EXIFWriter { /** * @param $filename * @return array|null */ public static function read_metadata( $filename ) { if ( ! self::is_jpeg_file( $filename ) ) { return null; } $retval = null; try { $data = new PelDataWindow( @file_get_contents( $filename ) ); $exif = new PelExif(); if ( PelJpeg::isValid( $data ) ) { $jpeg = new PelJpeg(); @$jpeg->load( $data ); $exif = $jpeg->getExif(); if ( null === $exif ) { $exif = new PelExif(); $jpeg->setExif( $exif ); $tiff = new PelTiff(); $exif->setTiff( $tiff ); } else { $tiff = $exif->getTiff(); } } elseif ( PelTiff::isValid( $data ) ) { $tiff = new PelTiff(); $tiff->load( $data ); } else { return null; } $ifd0 = $tiff->getIfd(); if ( null === $ifd0 ) { $ifd0 = new PelIfd( PelIfd::IFD0 ); $tiff->setIfd( $ifd0 ); } $tiff->setIfd( $ifd0 ); $exif->setTiff( $tiff ); $retval = [ 'exif' => $exif, 'iptc' => null, ]; @getimagesize( $filename, $iptc ); if ( ! empty( $iptc['APP13'] ) ) { $retval['iptc'] = $iptc['APP13']; } } catch ( PelIfdException $exception ) { return null; } catch ( PelInvalidArgumentException $exception ) { return null; } catch ( PelInvalidDataException $exception ) { return null; } catch ( PelJpegInvalidMarkerException $exception ) { return null; } catch ( \Exception $exception ) { return null; } finally { return $retval; } } /** * @param $origin_file * @param $destination_file * @return bool|int FALSE on failure or (int) number of bytes written */ public static function copy_metadata( $origin_file, $destination_file ) { if ( ! self::is_jpeg_file( $origin_file ) ) { return false; } // Read existing data from the source file. $metadata = self::read_metadata( $origin_file ); if ( ! empty( $metadata ) && is_array( $metadata ) ) { return self::write_metadata( $destination_file, $metadata ); } else { return false; } } /** * @param $filename * @param $metadata * @return bool|int FALSE on failure or (int) number of bytes written. */ public static function write_metadata( $filename, $metadata ) { if ( ! self::is_jpeg_file( $filename ) || ! is_array( $metadata ) ) { return false; } try { // Prevent the orientation tag from ever being anything other than normal horizontal. /** @var PelExif $exif */ $exif = $metadata['exif']; $tiff = $exif->getTiff(); $ifd0 = $tiff->getIfd(); $orientation = new PelEntryShort( PelTag::ORIENTATION, 1 ); $ifd0->addEntry( $orientation ); $tiff->setIfd( $ifd0 ); $exif->setTiff( $tiff ); $metadata['exif'] = $exif; // Copy EXIF data to the new image and write it. $new_image = new PelJpeg( $filename ); $new_image->setExif( $metadata['exif'] ); $new_image->saveFile( $filename ); // Copy IPTC / APP13 to the new image and write it. if ( $metadata['iptc'] ) { return self::write_IPTC( $filename, $metadata['iptc'] ); } } catch ( PelInvalidArgumentException $exception ) { return false; } catch ( PelInvalidDataException $exception ) { error_log( "Could not write data to {$filename}" ); error_log( print_r( $exception, true ) ); return false; } // This should never happen, but this line satisfies phpstan. return false; } // In case bcmath isn't enabled we use these simple wrappers. static function bcadd( $one, $two, $scale = null ) { if ( ! function_exists( 'bcadd' ) ) { return floatval( $one ) + floatval( $two ); } else { return bcadd( $one, $two, $scale ); } } static function bcmul( $one, $two, $scale = null ) { if ( ! function_exists( 'bcmul' ) ) { return floatval( $one ) * floatval( $two ); } else { return bcmul( $one, $two, $scale ); } } static function bcpow( $one, $two, $scale = null ) { if ( ! function_exists( 'bcpow' ) ) { return floatval( $one ) ** floatval( $two ); } else { return bcpow( $one, $two, $scale ); } } /** * Use bcmath as a replacement to hexdec() to handle numbers than PHP_INT_MAX. Also validates the $hex parameter using ctypes. * * @param string $hex * @return float|int|string|null */ public static function bchexdec( $hex ) { // Ensure $hex is actually a valid hex number and won't generate deprecated conversion warnings on PHP 7.4+. if ( ! ctype_xdigit( $hex ) ) { return null; } $decimal = 0; $length = strlen( $hex ); for ( $i = 1; $i <= $length; $i++ ) { $decimal = self::bcadd( $decimal, self::bcmul( strval( hexdec( $hex[ $i - 1 ] ) ), self::bcpow( '16', strval( $length - $i ) ) ) ); } return $decimal; } /** * @param string $filename * @param array $data * @return bool|int FALSE on failure or (int) number of bytes written */ public static function write_IPTC( $filename, $data ) { if ( ! self::is_jpeg_file( $filename ) ) { return false; } $length = strlen( $data ) + 2; // Avoid invalid APP13 regions. if ( $length > 0xFFFF ) { return false; } // Wrap existing data in segment container we can embed new content in. $data = chr( 0xFF ) . chr( 0xED ) . chr( ( $length >> 8 ) & 0xFF ) . chr( $length & 0xFF ) . $data; $new_file_contents = @file_get_contents( $filename ); if ( ! $new_file_contents || strlen( $new_file_contents ) <= 0 ) { return false; } $new_file_contents = substr( $new_file_contents, 2 ); // Create new image container wrapper. $new_iptc = chr( 0xFF ) . chr( 0xD8 ); // Track whether content was modified. $new_fields_added = ! $data; // This can cause errors if incorrectly pointed at a non-JPEG file. try { // Loop through each JPEG segment in search of region 13. while ( ( self::bchexdec( substr( $new_file_contents, 0, 2 ) ) & 0xFFF0 ) === 0xFFE0 ) { $segment_length = ( hexdec( substr( $new_file_contents, 2, 2 ) ) & 0xFFFF ); $segment_number = ( hexdec( substr( $new_file_contents, 1, 1 ) ) & 0x0F ); // Not a segment we're interested in. if ( $segment_length <= 2 ) { return false; } $current_segment = substr( $new_file_contents, 0, $segment_length + 2 ); if ( ( 13 <= $segment_number ) && ( ! $new_fields_added ) ) { $new_iptc .= $data; $new_fields_added = true; if ( 13 === $segment_number ) { $current_segment = ''; } } $new_iptc .= $current_segment; $new_file_contents = substr( $new_file_contents, $segment_length + 2 ); } } catch ( \Exception $exception ) { return false; } if ( ! $new_fields_added ) { $new_iptc .= $data; } if ( $file = @fopen( $filename, 'wb' ) ) { return @fwrite( $file, $new_iptc . $new_file_contents ); } else { return false; } } /** * Determines if the file extension is .jpg or .jpeg * * @param $filename * @return bool */ public static function is_jpeg_file( $filename ) { $extension = I18N::mb_pathinfo( $filename, PATHINFO_EXTENSION ); return in_array( strtolower( $extension ), [ 'jpeg', 'jpg', 'jpeg_backup', 'jpg_backup' ] ); } }