| Server IP : 152.53.162.115 / Your IP : 216.73.217.85 Web Server : Apache/2 System : Linux host 6.12.0-55.40.1.el10_0.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Oct 21 05:54:51 EDT 2025 x86_64 User : pbshosting ( 1005) PHP Version : 8.3.30 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/pbshosting/domains/rajeevjayadevan.in/private_html/wp-content/plugins/mmww/code/ |
Upload File : |
<?php
class MMWWEXIFReader {
private $exif;
private $wpmeta;
function __construct( $init ) {
if ( is_array( $init ) ) {
$this->exif = $init;
} else {
$this->wpmeta = wp_read_image_metadata( $init );
// fetch additional info from exif if available
if ( function_exists( 'exif_read_data' ) ) {
$this->exif = @exif_read_data( $init, 'IFD0,FILE,EXIF,COMMENT' );
}
if ( ! empty( $this->exif ) ) {
$this->exif = array_merge( $this->exif, $this->wpmeta );
}
}
}
function __destruct() {
unset ( $this->exif );
}
public function get_metadata() {
$meta = [];
$exif = $this->exif;
if ( ! empty( $exif ) ) {
if ( ! empty ( $exif['UndefinedTag:0xEA1C'] ) &&
! empty( $exif['Title'] ) && $exif['Title'][0] == chr( 0x3f )
) {
$meta['warning'] = __( 'EXIF metadata corrupted by Microsoft Windows properties defect', 'mmww' );
/* deal with the bogus junk that MS's property editor puts into EXIF */
if ( ! empty( $exif['ImageDescription'] ) ) {
// Assume the title is stored in ImageDescription
$tempString = substr( trim( $exif['ImageDescription'] ), 0, 80 );
$meta['title'] = mb_convert_encoding( $tempString, 'ISO-8859-1', 'UTF-8' );
if ( ! empty( $exif['COMPUTED']['UserComment'] ) && trim( $exif['COMPUTED']['UserComment'] ) != $meta['title'] ) {
$tempString = trim( $exif['COMPUTED']['UserComment'] );
} else {
$tempString = trim( $exif['ImageDescription'] );
}
$meta['description'] = mb_convert_encoding( $tempString, 'ISO-8859-1', 'UTF-8' );
} elseif ( ! empty( $exif['Comments'] ) ) {
$tempString = trim( $exif['Comments'] );
$meta['description'] = mb_convert_encoding( $tempString, 'ISO-8859-1', 'UTF-8' );
$meta['title'] = '';
}
}
/* do the version */
if ( ! empty( $exif['ExifVersion'] ) ) {
$meta['exifversion'] = floatval( $exif['ExifVersion'] ) / 100 . '';
}
if ( ! empty( $exif['Copyright'] ) && strlen( $exif['Copyright'] ) > 0 ) {
$meta['copyright'] = mb_convert_encoding( trim( $exif['Copyright'] ), 'ISO-8859-1', 'UTF-8' );
}
if ( ( ! empty( $exif['GPSLongitudeRef'] ) ) &&
( ! empty( $exif['GPSLongitude'] ) ) &&
( ! empty( $exif['GPSLatitudeRef'] ) ) &&
( ! empty( $exif['GPSLatitude'] ) )
) {
// looks like we have valid lat/long data
$meta['longitude'] = $this->getGPS( $exif['GPSLongitudeRef'], $exif['GPSLongitude'] );
$meta['latitude'] = $this->getGPS( $exif['GPSLatitudeRef'], $exif['GPSLatitude'] );
}
if ( ! empty( $exif['GPSAltitude'] ) ) {
$meta['altitude'] = round( wp_exif_frac2dec( $exif['GPSAltitude'] ), 1 );
}
if ( ! empty ( $meta['altitude'] ) && ! empty( $exif['GPSAltitudeRef'] ) ) {
if ( intval( $exif['GPSAltitudeRef'] ) != 0 ) {
$meta['altitude'] = '-' . $meta['altitude'];
}
}
if ( ! empty( $exif['SubjectDistance'] ) ) {
$meta['subject_distance'] = round( wp_exif_frac2dec( $exif['SubjectDistance'] ), 1 );
}
if ( ! empty( $exif['ExposureBiasValue'] ) ) {
$meta['exposure_bias'] = round( wp_exif_frac2dec( $exif['ExposureBiasValue'] ), 1 );
}
if ( ! empty( $exif['GPSImgDirection'] ) ) {
$meta['direction'] = round( wp_exif_frac2dec( $exif['GPSImgDirection'] ), 1 );
}
/* T for true or M for magnetic direction */
if ( ! empty( $meta['direction'] ) && ! empty( $exif['GPSImgDirectionRef'] ) ) {
$meta['direction'] .= $exif['GPSImgDirectionRef'];
}
if ( ! empty( $exif['Model'] ) ) {
$meta['camera'] = mb_convert_encoding( trim( $exif['Model'] ), 'ISO-8859-1', 'UTF-8' );
}
if ( ! empty( $exif['DateTimeDigitized'] ) ) {
/* Time and timezone offset (offset not handled by WordPress as of 6.9.
* see https://exiftool.org/TagNames/EXIF.html */
$meta['created_timestamp'] = $this->getTime( $exif['DateTimeDigitized'], isset($exif['UndefinedTag:0x9011']) ? $exif['UndefinedTag:0x9011'] : null );
}
if ( empty( $meta['created_timestamp'] ) && ! empty( $exif['FileDateTime'] ) ) {
$meta['created_timestamp'] = $exif['FileDateTime'];
}
if ( ! empty( $exif['FocalLength'] ) ) {
$meta['focal_length'] = wp_exif_frac2dec( $exif['FocalLength'] );
}
if ( ! empty( $exif['FocalLengthIn35mmFilm'] ) ) {
$meta['focal_length35'] = wp_exif_frac2dec( $exif['FocalLengthIn35mmFilm'] );
}
if ( array_key_exists( 'Flash', $exif ) ) {
/* translators: renderings of the EXIF flash codes*/
$flash_data = [
0x0 => _x( 'No Flash', 'flash', 'mmww' ),
0x1 => _x( 'Fired', 'flash', 'mmww' ),
0x5 => _x( 'Fired, Return not detected', 'flash', 'mmww' ),
0x7 => _x( 'Fired, Return detected', 'flash', 'mmww' ),
0x8 => _x( 'On, Did not fire', 'flash', 'mmww' ),
0x9 => _x( 'On, Fired', 'flash', 'mmww' ),
0xd => _x( 'On, Return not detected', 'flash', 'mmww' ),
0xf => _x( 'On, Return detected', 'flash', 'mmww' ),
0x10 => _x( 'Off, Did not fire', 'flash', 'mmww' ),
0x14 => _x( 'Off, Did not fire, Return not detected', 'flash', 'mmww' ),
0x18 => _x( 'Auto, Did not fire', 'flash', 'mmww' ),
0x19 => _x( 'Auto, Fired', 'flash', 'mmww' ),
0x1d => _x( 'Auto, Fired, Return not detected', 'flash', 'mmww' ),
0x1f => _x( 'Auto, Fired, Return detected', 'flash', 'mmww' ),
0x20 => _x( 'No flash function', 'flash', 'mmww' ),
0x30 => _x( 'Off, No flash function', 'flash', 'mmww' ),
0x41 => _x( 'Fired, Red-eye reduction', 'flash', 'mmww' ),
0x45 => _x( 'Fired, Red-eye reduction, Return not detected', 'flash', 'mmww' ),
0x47 => _x( 'Fired, Red-eye reduction, Return detected', 'flash', 'mmww' ),
0x49 => _x( 'On, Red-eye reduction', 'flash', 'mmww' ),
0x4d => _x( 'On, Red-eye reduction, Return not detected', 'flash', 'mmww' ),
0x4f => _x( 'On, Red-eye reduction, Return detected', 'flash', 'mmww' ),
0x50 => _x( 'Off, Red-eye reduction', 'flash', 'mmww' ),
0x58 => _x( 'Auto, Did not fire, Red-eye reduction', 'flash', 'mmww' ),
0x59 => _x( 'Auto, Fired, Red-eye reduction', 'flash', 'mmww' ),
0x5d => _x( 'Auto, Fired, Red-eye reduction, Return not detected', 'flash', 'mmww' ),
0x5f => _x( 'Auto, Fired, Red-eye reduction, Return detected', 'flash', 'mmww' ),
];
$meta['flash'] = $flash_data[ intval( $exif['Flash'] ) ];
}
if ( array_key_exists( 'SceneCaptureType', $exif ) ) {
/* translators: renderings of the EXIF scene capture type http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html*/
$scenecap_data = [
0 => _x( 'Standard', 'scene_capture_type', 'mmww' ),
1 => _x( 'Landscape', 'scene_capture_type', 'mmww' ),
2 => _x( 'Portrait', 'scene_capture_type', 'mmww' ),
3 => _x( 'Night', 'scene_capture_type', 'mmww' ),
];
$meta['scene_capture_type'] = $scenecap_data[ intval( $exif['SceneCaptureType'] ) ];
}
if ( array_key_exists( 'Sharpness', $exif ) ) {
/* translators: renderings of the EXIF sharpness type http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html*/
$sharp_data = [
0 => _x( 'Normal', 'sharpness', 'mmww' ),
1 => _x( 'Soft', 'sharpness', 'mmww' ),
2 => _x( 'Hard', 'sharpness', 'mmww' ),
];
$meta['sharpness'] = $sharp_data[ intval( $exif['Sharpness'] ) ];
}
if ( array_key_exists( 'LightSource', $exif ) ) {
/* translators: renderings of the EXIF light source codes http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html#LightSource*/
$light_source_data = [
0 => _x( 'Unknown', 'light_source', 'mmww' ),
1 => _x( 'Daylight', 'light_source', 'mmww' ),
2 => _x( 'Fluorescent', 'light_source', 'mmww' ),
3 => _x( 'Tungsten', 'light_source', 'mmww' ),
4 => _x( 'Flash', 'light_source', 'mmww' ),
9 => _x( 'Fine weather', 'light_source', 'mmww' ),
10 => _x( 'Cloudy weather', 'light_source', 'mmww' ),
11 => _x( 'Shade', 'light_source', 'mmww' ),
12 => _x( 'Daylight fluorescent', 'light_source', 'mmww' ),
13 => _x( 'Day white fluorescent', 'light_source', 'mmww' ),
14 => _x( 'Cool white fluorescent', 'light_source', 'mmww' ),
15 => _x( 'White fluorescent', 'light_source', 'mmww' ),
17 => _x( 'Standard light A', 'light_source', 'mmww' ),
18 => _x( 'Standard light B', 'light_source', 'mmww' ),
19 => _x( 'Standard light C', 'light_source', 'mmww' ),
20 => _x( 'D55', 'light_source', 'mmww' ),
21 => _x( 'D65', 'light_source', 'mmww' ),
22 => _x( 'D75', 'light_source', 'mmww' ),
23 => _x( 'D50', 'light_source', 'mmww' ),
24 => _x( 'ISO studio tungsten', 'light_source', 'mmww' ),
255 => _x( 'Other light source', 'light_source', 'mmww' ),
];
$meta['lightsource'] = $light_source_data[ intval( $exif['LightSource'] ) ];
}
if ( array_key_exists( 'MeteringMode', $exif ) ) {
/* translators: these are human-readable renderings of the EXIF metering mode codes */
$metering_mode_data = [
0 => _x( 'Unknown', 'metering_mode', 'mmww' ),
1 => _x( 'Average', 'metering_mode', 'mmww' ),
2 => _x( 'Center weighted average', 'metering_mode', 'mmww' ),
3 => _x( 'Spot', 'metering_mode', 'mmww' ),
4 => _x( 'Multi Spot', 'metering_mode', 'mmww' ),
5 => _x( 'Pattern', 'metering_mode', 'mmww' ),
6 => _x( 'Partial', 'metering_mode', 'mmww' ),
255 => _x( 'Other', 'metering_mode', 'mmww' ),
];
$meta['meteringmode'] = $metering_mode_data[ intval( $exif['MeteringMode'] ) ];
}
if ( array_key_exists( 'SensingMethod', $exif ) ) {
/* translators: these are human-readable renderings of the EXIF sensor type codes */
$sensing_method_data = [
2 => _x( 'One-chip color area sensor', 'sensing_method', 'mmww' ),
3 => _x( 'Two-chip color area sensor', 'sensing_method', 'mmww' ),
4 => _x( 'Three-chip color area sensor', 'sensing_method', 'mmww' ),
5 => _x( 'Color sequential area sensor', 'sensing_method', 'mmww' ),
7 => _x( 'Trilinear sensor', 'sensing_method', 'mmww' ),
8 => _x( 'Color sequential linear sensor', 'sensing_method', 'mmww' ),
];
$meta['sensingmethod'] = $sensing_method_data[ intval( $exif['SensingMethod'] ) ];
}
if ( array_key_exists( 'ExposureMode', $exif ) ) {
/* translators: these are human-readable renderings of the EXIF exposure mode codes */
$exposure_mode_data = [
0 => _x( 'Auto', 'exposure_mode', 'mmww' ),
1 => _x( 'Manual', 'exposure_mode', 'mmww' ),
2 => _x( 'Auto bracket', 'exposure_mode', 'mmww' ),
];
$meta['exposuremode'] = $exposure_mode_data[ intval( $exif['ExposureMode'] ) ];
}
if ( array_key_exists( 'ExposureProgram', $exif ) ) {
/* translators: these are human-readable renderings of the EXIF exposure program codes */
$exposure_program_data = [
1 => _x( 'Manual', 'exposure_program', 'mmww' ),
2 => _x( 'Normal Program', 'exposure_program', 'mmww' ),
3 => _x( 'Aperture Priority', 'exposure_program', 'mmww' ),
4 => _x( 'Shutter Priority', 'exposure_program', 'mmww' ),
5 => _x( 'Creative Program', 'exposure_program', 'mmww' ),
6 => _x( 'Action Program', 'exposure_program', 'mmww' ),
7 => _x( 'Portrait Mode', 'exposure_program', 'mmww' ),
8 => _x( 'Landscape Mode', 'exposure_program', 'mmww' ),
];
$meta['exposure_program'] = $exposure_program_data[ intval( $exif['ExposureProgram'] ) ];
}
if ( ! empty( $exif['BrightnessValue'] ) ) {
$meta['brightness'] = round( wp_exif_frac2dec( $exif['BrightnessValue'] ), 2 );
}
if ( ! empty( $exif['FNumber'] ) ) {
$meta['fstop'] = 'f/' . round( wp_exif_frac2dec( $exif['FNumber'] ), 1 );
}
if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
$isoitem = $exif['ISOSpeedRatings'];
/* there's a bug where this is sometimes an array and sometimes a scalar */
if ( is_array( $isoitem ) ) {
$isoitems = [];
foreach ( $isoitem as $isodetail ) {
$isoitems[] = sprintf( '%d', $isodetail );
}
$val = implode( '/', $isoitems );
} else {
$val = sprintf( '%d', $isoitem );
}
$meta['iso'] = $val;
}
if ( ! empty( $exif['ExposureTime'] ) ) {
$exposure = wp_exif_frac2dec( $exif['ExposureTime'] );
if ( $exposure < 0.51 ) {
$meta['shutter'] = '1/' . round( ( 1.0 / $exposure ), 1 );
} else if ( $exposure < 2.01 ) {
$meta['shutter'] = round( $exposure, 1 );
} else {
$meta['shutter'] = round( $exposure, 0 );
}
}
}
return $meta;
}
/**
* Convert timezone and offset to UNIX timestamp.
*
* If the offset to UTC is provided, use it.
* If not, assume the time is in local time and offset it to UTC.
*
* @param string $time A timestamp like '2025:12:17 12:34'. Note colons in dates. Exif is wierd.
* @param string $offset An offset to UTC like '+5:30' or null, or empty.
*
* @return false|int
*/
private function getTime( $time, $offset = null ) {
list( $dat, $tim ) = explode( ' ', trim( $time ) );
list( $y, $m, $d ) = explode( ':', $dat );
$str = "$y-$m-$d $tim";
if ( is_string ($offset) && strlen ($offset) > 0 ) {
$str .= trim( $offset ?: '' );
return strtotime( $str );
} else {
$result = strtotime( $str );
try {
return MMWWMedia::offset_timestamp_by_zone( $result, false );
} catch ( Exception $e ) {
return $result;
}
}
}
/**
* Convert a GPS exif reference to decimal degrees
*
* EXIF represents values with rational numbers in strings.
* For example the string "9/2" is used to represent 3.5.
*
* @param string $ref N, E, S, W
* @param array $c One to three strings of rational numbers: degrees, degrees/minutes, or degrees/minutes/seconds.
*
* @return float Degrees.
*/
private function getGPS( $ref, $c ) {
// south, west, or negative altitude
$sign = ( $ref[0] == 'S' || $ref[0] == 'W' ) ? - 1 : 1;
$val = 0.0;
while ( $r = array_pop( $c ) ) {
$val *= (1.0/ 60.0);
$val += wp_exif_frac2dec( $r );
}
return round( $sign * $val, 6 );
}
}