function seems_utf8($str) { mbstring_binary_safe_encoding(); $length = strlen($str); reset_mbstring_encoding(); for ($i = 0; $i < $length; $i++) { $c = ord($str[$i]); if ($c < 0x80) { $n = 0; } elseif (($c & 0xe0) == 0xc0) { $n = 1; } elseif (($c & 0xf0) == 0xe0) { $n = 2; } elseif (($c & 0xf8) == 0xf0) { $n = 3; } elseif (($c & 0xfc) == 0xf8) { $n = 4; } elseif (($c & 0xfe) == 0xfc) { $n = 5; } else { return false; } // Does not match any model for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ? if (++$i == $length || (ord($str[$i]) & 0xc0) != 0x80) { return false; } } } return true; }
/** * array (size=23) * 0 => * array (size=11) * 'filename' => string 'akismet/' (length=8) * 'stored_filename' => string 'akismet/' (length=8) * 'size' => int 0 * 'compressed_size' => int 0 * 'mtime' => int 1443138698 * 'comment' => string '' (length=0) * 'folder' => boolean true * 'index' => int 0 * 'status' => string 'ok' (length=2) * 'crc' => int 0 * 'content' => string '' (length=0) * 1 => * array (size=11) * 'filename' => string 'akismet/akismet.php' (length=19) * 'stored_filename' => string 'akismet/akismet.php' (length=19) * 'size' => int 2438 * 'compressed_size' => int 1184 * 'mtime' => int 1443138698 * 'comment' => string '' (length=0) * 'folder' => boolean false * 'index' => int 1 * 'status' => string 'ok' (length=2) * 'crc' => int 1640791883 * 'content' => string '' */ public static function read($filePath) { if (function_exists('mbstring_binary_safe_encoding')) { mbstring_binary_safe_encoding(); } $archive = new PclZip($filePath); $archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING); if (function_exists('reset_mbstring_encoding')) { reset_mbstring_encoding(); } return $archive_files; }
/** * Write a string to a file * * @param string $file Remote path to the file where to write the data. * @param string $contents The data to write. * @param int $mode (optional) The file permissions as octal number, usually 0644. * @return bool False upon failure. */ function put_contents($file, $contents, $mode = false) { $fp = @fopen($file, 'wb'); if (!$fp) { return false; } mbstring_binary_safe_encoding(); $data_length = strlen($contents); $bytes_written = fwrite($fp, $contents); reset_mbstring_encoding(); fclose($fp); if ($data_length !== $bytes_written) { return false; } $this->chmod($file, $mode); return true; }
private function bwg_wp_read_image_metadata($file) { if (!file_exists($file)) { return false; } list(, , $sourceImageType) = getimagesize($file); $meta = array('aperture' => 0, 'credit' => '', 'camera' => '', 'caption' => '', 'created_timestamp' => 0, 'copyright' => '', 'focal_length' => 0, 'iso' => 0, 'shutter_speed' => 0, 'title' => '', 'orientation' => 0); if (is_callable('iptcparse')) { getimagesize($file, $info); if (!empty($info['APP13'])) { $iptc = iptcparse($info['APP13']); if (!empty($iptc['2#105'][0])) { $meta['title'] = trim($iptc['2#105'][0]); } elseif (!empty($iptc['2#005'][0])) { $meta['title'] = trim($iptc['2#005'][0]); } if (!empty($iptc['2#120'][0])) { $caption = trim($iptc['2#120'][0]); if (empty($meta['title'])) { mbstring_binary_safe_encoding(); $caption_length = strlen($caption); reset_mbstring_encoding(); if ($caption_length < 80) { $meta['title'] = $caption; } else { $meta['caption'] = $caption; } } elseif ($caption != $meta['title']) { $meta['caption'] = $caption; } } if (!empty($iptc['2#110'][0])) { $meta['credit'] = trim($iptc['2#110'][0]); } elseif (!empty($iptc['2#080'][0])) { $meta['credit'] = trim($iptc['2#080'][0]); } if (!empty($iptc['2#055'][0]) and !empty($iptc['2#060'][0])) { $meta['created_timestamp'] = strtotime($iptc['2#055'][0] . ' ' . $iptc['2#060'][0]); } if (!empty($iptc['2#116'][0])) { $meta['copyright'] = trim($iptc['2#116'][0]); } } } if (is_callable('exif_read_data') && in_array($sourceImageType, apply_filters('wp_read_image_metadata_types', array(IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM)))) { $exif = @exif_read_data($file); if (empty($meta['title']) && !empty($exif['Title'])) { $meta['title'] = trim($exif['Title']); } if (!empty($exif['ImageDescription'])) { mbstring_binary_safe_encoding(); $description_length = strlen($exif['ImageDescription']); reset_mbstring_encoding(); if (empty($meta['title']) && $description_length < 80) { $meta['title'] = trim($exif['ImageDescription']); if (empty($meta['caption']) && !empty($exif['COMPUTED']['UserComment']) && trim($exif['COMPUTED']['UserComment']) != $meta['title']) { $meta['caption'] = trim($exif['COMPUTED']['UserComment']); } } elseif (empty($meta['caption']) && trim($exif['ImageDescription']) != $meta['title']) { $meta['caption'] = trim($exif['ImageDescription']); } } elseif (empty($meta['caption']) && !empty($exif['Comments']) && trim($exif['Comments']) != $meta['title']) { $meta['caption'] = trim($exif['Comments']); } if (empty($meta['credit'])) { if (!empty($exif['Artist'])) { $meta['credit'] = trim($exif['Artist']); } elseif (!empty($exif['Author'])) { $meta['credit'] = trim($exif['Author']); } } if (empty($meta['copyright']) && !empty($exif['Copyright'])) { $meta['copyright'] = trim($exif['Copyright']); } if (!empty($exif['FNumber'])) { $meta['aperture'] = round(wp_exif_frac2dec($exif['FNumber']), 2); } if (!empty($exif['Model'])) { $meta['camera'] = trim($exif['Model']); } if (empty($meta['created_timestamp']) && !empty($exif['DateTimeDigitized'])) { $meta['created_timestamp'] = wp_exif_date2ts($exif['DateTimeDigitized']); } if (!empty($exif['FocalLength'])) { $meta['focal_length'] = (string) wp_exif_frac2dec($exif['FocalLength']); } if (!empty($exif['ISOSpeedRatings'])) { $meta['iso'] = is_array($exif['ISOSpeedRatings']) ? reset($exif['ISOSpeedRatings']) : $exif['ISOSpeedRatings']; $meta['iso'] = trim($meta['iso']); } if (!empty($exif['ExposureTime'])) { $meta['shutter_speed'] = (string) wp_exif_frac2dec($exif['ExposureTime']); } if (!empty($exif['Orientation'])) { $meta['orientation'] = $exif['Orientation']; } } foreach (array('title', 'caption', 'credit', 'copyright', 'camera', 'iso') as $key) { if ($meta[$key] && !seems_utf8($meta[$key])) { $meta[$key] = utf8_encode($meta[$key]); } } foreach ($meta as &$value) { if (is_string($value)) { $value = wp_kses_post($value); } } return $meta; }
/** * @param string $path * @param bool $include_hidden * @param bool $recursive * @return bool|array */ public function dirlist($path = '.', $include_hidden = true, $recursive = false) { if ($this->is_file($path)) { $limit_file = basename($path); $path = dirname($path) . '/'; } else { $limit_file = false; } mbstring_binary_safe_encoding(); $list = $this->ftp->dirlist($path); if (empty($list) && !$this->exists($path)) { reset_mbstring_encoding(); return false; } $ret = array(); foreach ($list as $struc) { if ('.' == $struc['name'] || '..' == $struc['name']) { continue; } if (!$include_hidden && '.' == $struc['name'][0]) { continue; } if ($limit_file && $struc['name'] != $limit_file) { continue; } if ('d' == $struc['type']) { if ($recursive) { $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); } else { $struc['files'] = array(); } } // Replace symlinks formatted as "source -> target" with just the source name if ($struc['islink']) { $struc['name'] = preg_replace('/(\\s*->\\s*.*)$/', '', $struc['name']); } $ret[$struc['name']] = $struc; } reset_mbstring_encoding(); return $ret; }
/** * Update or append the requested file with the supplied contents. * * @since 1.15.0 * * @param string $file Full path to config file to update. * @param string $contents Contents to write to the file. * @param bool $append Optional. Set to true to append contents to the file. Defaults to false. * @return bool|WP_Error Boolean true on success, WP_Error object otherwise. */ public static function write($file, $contents, $append = false) { $callable = array(); if (ITSEC_Lib_Utility::is_callable_function('fopen') && ITSEC_Lib_Utility::is_callable_function('fwrite') && ITSEC_Lib_Utility::is_callable_function('flock')) { $callable[] = 'fopen'; } if (ITSEC_Lib_Utility::is_callable_function('file_put_contents')) { $callable[] = 'file_put_contents'; } if (empty($callable)) { return new WP_Error('itsec-lib-file-write-no-callable-functions', sprintf(__('%s could not be written. Both the fopen/fwrite/flock and file_put_contents functions are disabled on the server. This is a server configuration issue that must be resolved before iThemes Security can write files.', 'it-l10n-better-wp-security'), $file)); } if (ITSEC_Lib_Directory::is_dir($file)) { return new WP_Error('itsec-lib-file-write-path-exists-as-directory', sprintf(__('%s could not be written as a file. The requested path already exists as a directory. The directory must be removed or a new file name must be chosen before the file can be written.', 'it-l10n-better-wp-security'), $file)); } if (!ITSEC_Lib_Directory::is_dir(dirname($file))) { $result = ITSEC_Lib_Directory::create(dirname($file)); if (is_wp_error($result)) { return $result; } } $file_existed = self::is_file($file); $success = false; // Different permissions to try in case the starting set of permissions are prohibiting write. $trial_perms = array(false, 0644, 0664, 0666); foreach ($trial_perms as $perms) { if (false !== $perms) { if (!isset($original_file_perms)) { $original_file_perms = self::get_permissions($file); } self::chmod($file, $perms); } if (in_array('fopen', $callable)) { if ($append) { $mode = 'ab'; } else { $mode = 'wb'; } if (false !== ($fh = @fopen($file, $mode))) { flock($fh, LOCK_EX); mbstring_binary_safe_encoding(); $data_length = strlen($contents); $bytes_written = @fwrite($fh, $contents); reset_mbstring_encoding(); @flock($fh, LOCK_UN); @fclose($fh); if ($data_length === $bytes_written) { $success = true; } } } if (!$success && in_array('file_put_contents', $callable)) { if ($append) { $flags = FILE_APPEND; } else { $flags = 0; } mbstring_binary_safe_encoding(); $data_length = strlen($contents); $bytes_written = @file_put_contents($file, $contents, $flags); reset_mbstring_encoding(); if ($data_length === $bytes_written) { $success = true; } } if ($success) { if (!$file_existed) { // Set default file permissions for the new file. self::chmod($file, self::get_default_permissions()); } else { if (isset($original_file_perms) && !is_wp_error($original_file_perms)) { // Reset the original file permissions if they were modified. self::chmod($file, $original_file_perms); } } return true; } if (!$file_existed) { // If the file is new, there is no point attempting different permissions. break; } } return new WP_Error('itsec-lib-file-write-file-put-contents-failed', sprintf(__('%s could not be written. This could be due to a permissions issue. Ensure that PHP runs as a user that has permission to write to this location.', 'it-l10n-better-wp-security'), $file)); }
/** * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the PclZip library. * Assumes that WP_Filesystem() has already been called and set up. * * @since 3.0.0 * @see unzip_file * @access private * * @global WP_Filesystem_Base $wp_filesystem Subclass * * @param string $file Full path and filename of zip archive * @param string $to Full path on the filesystem to extract archive to * @param array $needed_dirs A partial list of required folders needed to be created. * @return mixed WP_Error on failure, True on success */ function _unzip_file_pclzip($file, $to, $needed_dirs = array()) { global $wp_filesystem; mbstring_binary_safe_encoding(); require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php'); $archive = new PclZip($file); $archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING); reset_mbstring_encoding(); // Is the archive valid? if ( !is_array($archive_files) ) return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true)); if ( 0 == count($archive_files) ) return new WP_Error( 'empty_archive_pclzip', __( 'Empty archive.' ) ); $uncompressed_size = 0; // Determine any children directories needed (From within the archive) foreach ( $archive_files as $file ) { if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Skip the OS X-created __MACOSX directory continue; $uncompressed_size += $file['size']; $needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname($file['filename']) ); } /* * disk_free_space() could return false. Assume that any falsey value is an error. * A disk that has zero free bytes has bigger problems. * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. */ if ( defined( 'DOING_CRON' ) && DOING_CRON ) { $available_space = @disk_free_space( WP_CONTENT_DIR ); if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) return new WP_Error( 'disk_full_unzip_file', __( 'Could not copy files. You may have run out of disk space.' ), compact( 'uncompressed_size', 'available_space' ) ); } $needed_dirs = array_unique($needed_dirs); foreach ( $needed_dirs as $dir ) { // Check the parent folders of the folders all exist within the creation array. if ( untrailingslashit($to) == $dir ) // Skip over the working directory, We know this exists (or will exist) continue; if ( strpos($dir, $to) === false ) // If the directory is not within the working directory, Skip it continue; $parent_folder = dirname($dir); while ( !empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs) ) { $needed_dirs[] = $parent_folder; $parent_folder = dirname($parent_folder); } } asort($needed_dirs); // Create those directories if need be: foreach ( $needed_dirs as $_dir ) { // Only check to see if the dir exists upon creation failure. Less I/O this way. if ( ! $wp_filesystem->mkdir( $_dir, FS_CHMOD_DIR ) && ! $wp_filesystem->is_dir( $_dir ) ) return new WP_Error( 'mkdir_failed_pclzip', __( 'Could not create directory.' ), substr( $_dir, strlen( $to ) ) ); } unset($needed_dirs); // Extract the files from the zip foreach ( $archive_files as $file ) { if ( $file['folder'] ) continue; if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files continue; if ( ! $wp_filesystem->put_contents( $to . $file['filename'], $file['content'], FS_CHMOD_FILE) ) return new WP_Error( 'copy_failed_pclzip', __( 'Could not copy file.' ), $file['filename'] ); } return true; }
/** * Strips any invalid characters based on value/charset pairs. * * @since 4.2.0 * @access protected * * @param array $data Array of value arrays. Each value array has the keys * 'value' and 'charset'. An optional 'ascii' key can be * set to false to avoid redundant ASCII checks. * @return array|WP_Error The $data parameter, with invalid characters removed from * each value. This works as a passthrough: any additional keys * such as 'field' are retained in each value array. If we cannot * remove invalid characters, a WP_Error object is returned. */ protected function strip_invalid_text($data) { $db_check_string = false; foreach ($data as &$value) { $charset = $value['charset']; if (is_array($value['length'])) { $length = $value['length']['length']; $truncate_by_byte_length = 'byte' === $value['length']['type']; } else { $length = false; // Since we have no length, we'll never truncate. // Initialize the variable to false. true would take us // through an unnecessary (for this case) codepath below. $truncate_by_byte_length = false; } // There's no charset to work with. if (false === $charset) { continue; } // Column isn't a string. if (!is_string($value['value'])) { continue; } $needs_validation = true; if ('latin1' === $charset || !isset($value['ascii']) && $this->check_ascii($value['value'])) { $truncate_by_byte_length = true; $needs_validation = false; } if ($truncate_by_byte_length) { mbstring_binary_safe_encoding(); if (false !== $length && strlen($value['value']) > $length) { $value['value'] = substr($value['value'], 0, $length); } reset_mbstring_encoding(); if (!$needs_validation) { continue; } } // utf8 can be handled by regex, which is a bunch faster than a DB lookup. if (('utf8' === $charset || 'utf8mb3' === $charset || 'utf8mb4' === $charset) && function_exists('mb_strlen')) { $regex = '/ ( (?: [\\x00-\\x7F] # single-byte sequences 0xxxxxxx | [\\xC2-\\xDF][\\x80-\\xBF] # double-byte sequences 110xxxxx 10xxxxxx | \\xE0[\\xA0-\\xBF][\\x80-\\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 | [\\xE1-\\xEC][\\x80-\\xBF]{2} | \\xED[\\x80-\\x9F][\\x80-\\xBF] | [\\xEE-\\xEF][\\x80-\\xBF]{2}'; if ('utf8mb4' === $charset) { $regex .= ' | \\xF0[\\x90-\\xBF][\\x80-\\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 | [\\xF1-\\xF3][\\x80-\\xBF]{3} | \\xF4[\\x80-\\x8F][\\x80-\\xBF]{2} '; } $regex .= '){1,40} # ...one or more times ) | . # anything else /x'; $value['value'] = preg_replace($regex, '$1', $value['value']); if (false !== $length && mb_strlen($value['value'], 'UTF-8') > $length) { $value['value'] = mb_substr($value['value'], 0, $length, 'UTF-8'); } continue; } // We couldn't use any local conversions, send it to the DB. $value['db'] = $db_check_string = true; } unset($value); // Remove by reference. if ($db_check_string) { $queries = array(); foreach ($data as $col => $value) { if (!empty($value['db'])) { // We're going to need to truncate by characters or bytes, depending on the length value we have. if ('byte' === $value['length']['type']) { // Using binary causes LEFT() to truncate by bytes. $charset = 'binary'; } else { $charset = $value['charset']; } if (is_array($value['length'])) { $queries[$col] = $this->prepare("CONVERT( LEFT( CONVERT( %s USING {$charset} ), %.0f ) USING {$this->charset} )", $value['value'], $value['length']['length']); } else { if ('binary' !== $charset) { // If we don't have a length, there's no need to convert binary - it will always return the same result. $queries[$col] = $this->prepare("CONVERT( CONVERT( %s USING {$charset} ) USING {$this->charset} )", $value['value']); } } unset($data[$col]['db']); } } $sql = array(); foreach ($queries as $column => $query) { if (!$query) { continue; } $sql[] = $query . " AS x_{$column}"; } $this->check_current_query = false; $row = $this->get_row("SELECT " . implode(', ', $sql), ARRAY_A); if (!$row) { return new WP_Error('wpdb_strip_invalid_text_failure'); } foreach (array_keys($data) as $column) { $data[$column]['value'] = $row["x_{$column}"]; } } return $data; }
/** * Strips any invalid characters based on value/charset pairs. * * @since 4.2.0 * @access protected * * @param array $data Array of value arrays. Each value array has the keys * 'value' and 'charset'. An optional 'ascii' key can be * set to false to avoid redundant ASCII checks. * @return array|WP_Error The $data parameter, with invalid characters removed from * each value. This works as a passthrough: any additional keys * such as 'field' are retained in each value array. If we cannot * remove invalid characters, a WP_Error object is returned. */ protected function strip_invalid_text($data) { $db_check_string = false; foreach ($data as &$value) { $charset = $value['charset']; if (is_array($value['length'])) { $length = $value['length']['length']; } else { $length = false; } // There's no charset to work with. if (false === $charset) { continue; } // Column isn't a string. if (!is_string($value['value'])) { continue; } $truncate_by_byte_length = 'byte' === $value['length']['type']; $needs_validation = true; if ('latin1' === $charset || !isset($value['ascii']) && $this->check_ascii($value['value'])) { $truncate_by_byte_length = true; $needs_validation = false; } if ($truncate_by_byte_length) { mbstring_binary_safe_encoding(); if (false !== $length && strlen($value['value']) > $length) { $value['value'] = substr($value['value'], 0, $length); } reset_mbstring_encoding(); if (!$needs_validation) { continue; } } // utf8 can be handled by regex, which is a bunch faster than a DB lookup. if (('utf8' === $charset || 'utf8mb3' === $charset || 'utf8mb4' === $charset) && function_exists('mb_strlen')) { $regex = '/ ( (?: [\\x00-\\x7F] # single-byte sequences 0xxxxxxx | [\\xC2-\\xDF][\\x80-\\xBF] # double-byte sequences 110xxxxx 10xxxxxx | \\xE0[\\xA0-\\xBF][\\x80-\\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 | [\\xE1-\\xEC][\\x80-\\xBF]{2} | \\xED[\\x80-\\x9F][\\x80-\\xBF] | [\\xEE-\\xEF][\\x80-\\xBF]{2}'; if ('utf8mb4' === $charset) { $regex .= ' | \\xF0[\\x90-\\xBF][\\x80-\\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 | [\\xF1-\\xF3][\\x80-\\xBF]{3} | \\xF4[\\x80-\\x8F][\\x80-\\xBF]{2} '; } $regex .= '){1,40} # ...one or more times ) | . # anything else /x'; $value['value'] = preg_replace($regex, '$1', $value['value']); if (false !== $length && mb_strlen($value['value'], 'UTF-8') > $length) { $value['value'] = mb_substr($value['value'], 0, $length, 'UTF-8'); } continue; } // We couldn't use any local conversions, send it to the DB. $value['db'] = $db_check_string = true; } unset($value); // Remove by reference. if ($db_check_string) { $queries = array(); foreach ($data as $col => $value) { if (!empty($value['db'])) { if (!isset($queries[$value['charset']])) { $queries[$value['charset']] = array(); } // We're going to need to truncate by characters or bytes, depending on the length value we have. if ('byte' === $value['length']['type']) { // Split the CONVERT() calls by charset, so we can make sure the connection is right $queries[$value['charset']][$col] = $this->prepare("CONVERT( LEFT( CONVERT( %s USING binary ), %d ) USING {$value['charset']} )", $value['value'], $value['length']['length']); } else { $queries[$value['charset']][$col] = $this->prepare("LEFT( CONVERT( %s USING {$value['charset']} ), %d )", $value['value'], $value['length']['length']); } unset($data[$col]['db']); } } $connection_charset = $this->charset; foreach ($queries as $charset => $query) { if (!$query) { continue; } // Change the charset to match the string(s) we're converting if ($charset !== $connection_charset) { $connection_charset = $charset; $this->set_charset($this->dbh, $charset); } $this->check_current_query = false; $sql = array(); foreach ($query as $column => $column_query) { $sql[] = $column_query . " AS x_{$column}"; } $row = $this->get_row("SELECT " . implode(', ', $sql), ARRAY_A); if (!$row) { $this->set_charset($this->dbh, $connection_charset); return new WP_Error('wpdb_strip_invalid_text_failure'); } foreach (array_keys($query) as $column) { $data[$column]['value'] = $row["x_{$column}"]; } } // Don't forget to change the charset back! if ($connection_charset !== $this->charset) { $this->set_charset($this->dbh); } } return $data; }
public function zip_export_data($is_backup = false) { $uploads_path = $this->get_wp_upload_dir(); $zip_path = $this->get_upload_dir(); if ($is_backup) { $zip_path = $uploads_path . 'tmm_backup/'; } $tables = $this->get_wp_tables(); $zip_filename = $zip_path . self::folder_key . '.zip'; global $wpdb; file_put_contents($zip_path . 'wpdb.prfx', $wpdb->prefix); mbstring_binary_safe_encoding(); require_once ABSPATH . 'wp-admin/includes/class-pclzip.php'; $zip = new PclZip($zip_filename); if (!empty($tables)) { foreach ($tables as $table) { $file = $table . '.dat'; $zip->add($zip_path . $file, PCLZIP_OPT_REMOVE_PATH, $zip_path); $file = $table . '.dsc'; $zip->add($zip_path . $file, PCLZIP_OPT_REMOVE_PATH, $zip_path); } } $zip->add($zip_path . 'wpdb.prfx', PCLZIP_OPT_REMOVE_PATH, $zip_path); @$zip->create(); reset_mbstring_encoding(); foreach ($tables as $table) { if (file_exists($zip_path . $table . '.dsc')) { unlink($zip_path . $table . '.dsc'); } if (file_exists($zip_path . $table . '.dat')) { unlink($zip_path . $table . '.dat'); } } if (file_exists($zip_path . 'wpdb.prfx')) { unlink($zip_path . 'wpdb.prfx'); } if (!$is_backup) { wp_die($this->get_zip_file_url()); } }
/** * Encode the Unicode values to be used in the URI. * * @since 1.5.0 * * @param string $utf8_string * @param int $length Max length of the string * @return string String with Unicode encoded for URI. */ function utf8_uri_encode( $utf8_string, $length = 0 ) { $unicode = ''; $values = array(); $num_octets = 1; $unicode_length = 0; mbstring_binary_safe_encoding(); $string_length = strlen( $utf8_string ); reset_mbstring_encoding(); for ($i = 0; $i < $string_length; $i++ ) { $value = ord( $utf8_string[ $i ] ); if ( $value < 128 ) { if ( $length && ( $unicode_length >= $length ) ) break; $unicode .= chr($value); $unicode_length++; } else { if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3; $values[] = $value; if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) break; if ( count( $values ) == $num_octets ) { if ($num_octets == 3) { $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]); $unicode_length += 9; } else { $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]); $unicode_length += 6; } $values = array(); $num_octets = 1; } } } return $unicode; }
function export_zip_file($file, $source) { if (file_exists($file)) { unlink($file); } mbstring_binary_safe_encoding(); // PclZip ships with WordPress require_once ABSPATH . 'wp-admin/includes/class-pclzip.php'; $archive = new PclZip($file); if ($response = $archive->create($source, PCLZIP_OPT_REMOVE_PATH, dirname($source))) { reset_mbstring_encoding(); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename=' . basename($file)); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); readfile($file); unlink($file); die; } else { $this->errors[] = __('PclZip returned zero bytes.', 'child-theme-configurator'); } }
/** * Truncate string as utf8 * * @see http://jetpack.wp-a2z.org/oik_api/mbstring_binary_safe_encoding/ * @link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php * @link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/functions.php */ private static function truncate_utf8($str, $regexp = NULL, $replace = '', $len = IP_GEO_BLOCK_MAX_STR_LEN) { // remove unnecessary characters $str = preg_replace('/[\\x00-\\x1f\\x7f]/', '', $str); if ($regexp) { $str = preg_replace($regexp, $replace, $str); } // limit the length of the string if (function_exists('mb_strcut')) { mbstring_binary_safe_encoding(); // @since 3.7.0 if (strlen($str) > $len) { $str = mb_strcut($str, 0, $len) . '…'; } reset_mbstring_encoding(); // @since 3.7.0 } else { // https://core.trac.wordpress.org/ticket/25259 mbstring_binary_safe_encoding(); // @since 3.7.0 $original = strlen($str); $str = substr($str, 0, $len); $length = strlen($str); reset_mbstring_encoding(); // @since 3.7.0 if ($length !== $original) { // bit pattern from seems_utf8() in wp-includes/formatting.php static $code = array(array(0x80, 0x0), array(0xe0, 0xc0), array(0xf0, 0xe0), array(0xf8, 0xf0), array(0xfc, 0xf8), array(0xfe, 0xfc)); // truncate extra characters $len = min($length, 6); for ($i = 0; $i < $len; $i++) { $c = ord($str[$length - 1 - $i]); for ($j = $i; $j < 6; $j++) { if (($c & $code[$j][0]) == $code[$j][1]) { mbstring_binary_safe_encoding(); // @since 3.7.0 $str = substr($str, 0, $length - (int) ($j > 0) - $i); reset_mbstring_encoding(); // @since 3.7.0 // validate whole characters $str = self::validate_utf8($str); return '…' !== $str ? "{$str}…" : '…'; } } } // $str may not fit utf8 return '…'; } } // validate whole characters return self::validate_utf8($str); }
/** * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the PclZip library. * Assumes that WP_Filesystem() has already been called and set up. * * @since 3.0.0 * @see unzip_file * @access private * * @param string $file Full path and filename of zip archive * @param string $to Full path on the filesystem to extract archive to * @param array $needed_dirs A partial list of required folders needed to be created. * @return mixed WP_Error on failure, True on success */ function _unzip_file_pclzip($file, $to, $needed_dirs = array()) { global $wp_filesystem; mbstring_binary_safe_encoding(); require_once ABSPATH . 'wp-admin/includes/class-pclzip.php'; $archive = new PclZip($file); $archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING); reset_mbstring_encoding(); // Is the archive valid? if (!is_array($archive_files)) { return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true)); } if (0 == count($archive_files)) { return new WP_Error('empty_archive', __('Empty archive.')); } // Determine any children directories needed (From within the archive) foreach ($archive_files as $file) { if ('__MACOSX/' === substr($file['filename'], 0, 9)) { // Skip the OS X-created __MACOSX directory continue; } $needed_dirs[] = $to . untrailingslashit($file['folder'] ? $file['filename'] : dirname($file['filename'])); } $needed_dirs = array_unique($needed_dirs); foreach ($needed_dirs as $dir) { // Check the parent folders of the folders all exist within the creation array. if (untrailingslashit($to) == $dir) { // Skip over the working directory, We know this exists (or will exist) continue; } if (strpos($dir, $to) === false) { // If the directory is not within the working directory, Skip it continue; } $parent_folder = dirname($dir); while (!empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs)) { $needed_dirs[] = $parent_folder; $parent_folder = dirname($parent_folder); } } asort($needed_dirs); // Create those directories if need be: foreach ($needed_dirs as $_dir) { if (!$wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && !$wp_filesystem->is_dir($_dir)) { // Only check to see if the dir exists upon creation failure. Less I/O this way. return new WP_Error('mkdir_failed', __('Could not create directory.'), $_dir); } } unset($needed_dirs); // Extract the files from the zip foreach ($archive_files as $file) { if ($file['folder']) { continue; } if ('__MACOSX/' === substr($file['filename'], 0, 9)) { // Don't extract the OS X-created __MACOSX directory files continue; } if (!$wp_filesystem->put_contents($to . $file['filename'], $file['content'], FS_CHMOD_FILE)) { return new WP_Error('copy_failed', __('Could not copy file.'), $to . $file['filename']); } } return true; }
/** * Send an HTTP request to a URI. * * Please note: The only URI that are supported in the HTTP Transport implementation * are the HTTP and HTTPS protocols. * * @access public * @since 2.7.0 * * @param string $url The request URL. * @param string|array $args { * Optional. Array or string of HTTP request arguments. * * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', or 'PUT'. * Some transports technically allow others, but should not be * assumed. Default 'GET'. * @type int $timeout How long the connection should stay open in seconds. Default 5. * @type int $redirection Number of allowed redirects. Not supported by all transports * Default 5. * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. * Default '1.0'. * @type string $user-agent User-agent value sent. * Default WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ). * @type bool $reject_unsafe_urls Whether to pass URLs through wp_http_validate_url(). * Default false. * @type bool $blocking Whether the calling code requires the result of the request. * If set to false, the request will be sent to the remote server, * and processing returned to the calling code immediately, the caller * will know if the request succeeded or failed, but will not receive * any response from the remote server. Default true. * @type string|array $headers Array or string of headers to send with the request. * Default empty array. * @type array $cookies List of cookies to send with the request. Default empty array. * @type string|array $body Body to send with the request. Default null. * @type bool $compress Whether to compress the $body when sending the request. * Default false. * @type bool $decompress Whether to decompress a compressed response. If set to false and * compressed content is returned in the response anyway, it will * need to be separately decompressed. Default true. * @type bool $sslverify Whether to verify SSL for the request. Default true. * @type string sslcertificates Absolute path to an SSL certificate .crt file. * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. * @type bool $stream Whether to stream to a file. If set to true and no filename was * given, it will be droped it in the WP temp dir and its name will * be set using the basename of the URL. Default false. * @type string $filename Filename of the file to write to when streaming. $stream must be * set to true. Default null. * @type int $limit_response_size Size in bytes to limit the response to. Default null. * * } * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. * A WP_Error instance upon error. */ public function request($url, $args = array()) { $defaults = array('method' => 'GET', 'timeout' => apply_filters('http_request_timeout', 5), 'redirection' => apply_filters('http_request_redirection_count', 5), 'httpversion' => apply_filters('http_request_version', '1.0'), 'user-agent' => apply_filters('http_headers_useragent', 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url')), 'reject_unsafe_urls' => apply_filters('http_request_reject_unsafe_urls', false), 'blocking' => true, 'headers' => array(), 'cookies' => array(), 'body' => null, 'compress' => false, 'decompress' => true, 'sslverify' => true, 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', 'stream' => false, 'filename' => null, 'limit_response_size' => null); // Pre-parse for the HEAD checks. $args = wp_parse_args($args); // By default, Head requests do not cause redirections. if (isset($args['method']) && 'HEAD' == $args['method']) { $defaults['redirection'] = 0; } $r = wp_parse_args($args, $defaults); /** * Filters the arguments used in an HTTP request. * * @since 2.7.0 * * @param array $r An array of HTTP request arguments. * @param string $url The request URL. */ $r = apply_filters('http_request_args', $r, $url); // The transports decrement this, store a copy of the original value for loop purposes. if (!isset($r['_redirection'])) { $r['_redirection'] = $r['redirection']; } /** * Filters whether to preempt an HTTP request's return value. * * Returning a non-false value from the filter will short-circuit the HTTP request and return * early with that value. A filter should return either: * * - An array containing 'headers', 'body', 'response', 'cookies', and 'filename' elements * - A WP_Error instance * - boolean false (to avoid short-circuiting the response) * * Returning any other value may result in unexpected behaviour. * * @since 2.9.0 * * @param false|array|WP_Error $preempt Whether to preempt an HTTP request's return value. Default false. * @param array $r HTTP request arguments. * @param string $url The request URL. */ $pre = apply_filters('pre_http_request', false, $r, $url); if (false !== $pre) { return $pre; } if (function_exists('wp_kses_bad_protocol')) { if ($r['reject_unsafe_urls']) { $url = wp_http_validate_url($url); } if ($url) { $url = wp_kses_bad_protocol($url, array('http', 'https', 'ssl')); } } $arrURL = @parse_url($url); if (empty($url) || empty($arrURL['scheme'])) { return new WP_Error('http_request_failed', __('A valid URL was not provided.')); } if ($this->block_request($url)) { return new WP_Error('http_request_failed', __('User has blocked requests through HTTP.')); } // If we are streaming to a file but no filename was given drop it in the WP temp dir // and pick its name using the basename of the $url if ($r['stream']) { if (empty($r['filename'])) { $r['filename'] = get_temp_dir() . basename($url); } // Force some settings if we are streaming to a file and check for existence and perms of destination directory $r['blocking'] = true; if (!wp_is_writable(dirname($r['filename']))) { return new WP_Error('http_request_failed', __('Destination directory for file streaming does not exist or is not writable.')); } } if (is_null($r['headers'])) { $r['headers'] = array(); } // WP allows passing in headers as a string, weirdly. if (!is_array($r['headers'])) { $processedHeaders = WP_Http::processHeaders($r['headers']); $r['headers'] = $processedHeaders['headers']; } // Setup arguments $headers = $r['headers']; $data = $r['body']; $type = $r['method']; $options = array('timeout' => $r['timeout'], 'useragent' => $r['user-agent'], 'blocking' => $r['blocking'], 'hooks' => new WP_HTTP_Requests_Hooks($url, $r)); // Ensure redirects follow browser behaviour. $options['hooks']->register('requests.before_redirect', array(get_class(), 'browser_redirect_compatibility')); if ($r['stream']) { $options['filename'] = $r['filename']; } if (empty($r['redirection'])) { $options['follow_redirects'] = false; } else { $options['redirects'] = $r['redirection']; } // Use byte limit, if we can if (isset($r['limit_response_size'])) { $options['max_bytes'] = $r['limit_response_size']; } // If we've got cookies, use and convert them to Requests_Cookie. if (!empty($r['cookies'])) { $options['cookies'] = WP_Http::normalize_cookies($r['cookies']); } // SSL certificate handling if (!$r['sslverify']) { $options['verify'] = false; $options['verifyname'] = false; } else { $options['verify'] = $r['sslcertificates']; } // All non-GET/HEAD requests should put the arguments in the form body. if ('HEAD' !== $type && 'GET' !== $type) { $options['data_format'] = 'body'; } /** * Filters whether SSL should be verified for non-local requests. * * @since 2.8.0 * * @param bool $ssl_verify Whether to verify the SSL connection. Default true. */ $options['verify'] = apply_filters('https_ssl_verify', $options['verify']); // Check for proxies. $proxy = new WP_HTTP_Proxy(); if ($proxy->is_enabled() && $proxy->send_through_proxy($url)) { $options['proxy'] = new Requests_Proxy_HTTP($proxy->host() . ':' . $proxy->port()); if ($proxy->use_authentication()) { $options['proxy']->use_authentication = true; $options['proxy']->user = $proxy->username(); $options['proxy']->pass = $proxy->password(); } } // Avoid issues where mbstring.func_overload is enabled mbstring_binary_safe_encoding(); try { $requests_response = Requests::request($url, $headers, $data, $type, $options); // Convert the response into an array $http_response = new WP_HTTP_Requests_Response($requests_response, $r['filename']); $response = $http_response->to_array(); // Add the original object to the array. $response['http_response'] = $http_response; } catch (Requests_Exception $e) { $response = new WP_Error('http_request_failed', $e->getMessage()); } reset_mbstring_encoding(); /** * Fires after an HTTP API response is received and before the response is returned. * * @since 2.8.0 * * @param array|WP_Error $response HTTP response or WP_Error object. * @param string $context Context under which the hook is fired. * @param string $class HTTP transport used. * @param array $args HTTP request arguments. * @param string $url The request URL. */ do_action('http_api_debug', $response, 'response', 'Requests', $r, $url); if (is_wp_error($response)) { return $response; } if (!$r['blocking']) { return array('headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array(), 'http_response' => null); } /** * Filters the HTTP API response immediately before the response is returned. * * @since 2.9.0 * * @param array $response HTTP response. * @param array $r HTTP request arguments. * @param string $url The request URL. */ return apply_filters('http_response', $response, $r, $url); }
/** * @access public * * @param string $file * @param string $contents * @param int|bool $mode * @return bool */ public function put_contents($file, $contents, $mode = false) { $temp = wp_tempnam($file); if (!($temphandle = @fopen($temp, 'w+'))) { unlink($temp); return false; } // The FTP class uses string functions internally during file download/upload mbstring_binary_safe_encoding(); $bytes_written = fwrite($temphandle, $contents); if (false === $bytes_written || $bytes_written != strlen($contents)) { fclose($temphandle); unlink($temp); reset_mbstring_encoding(); return false; } fseek($temphandle, 0); // Skip back to the start of the file being written to $ret = $this->ftp->fput($file, $temphandle); reset_mbstring_encoding(); fclose($temphandle); unlink($temp); $this->chmod($file, $mode); return $ret; }
/** * Encode the Unicode values to be used in the URI. * * @since 1.5.0 * * @param string $utf8_string * @param int $length Max length of the string * @return string String with Unicode encoded for URI. */ function utf8_uri_encode($utf8_string, $length = 0) { $unicode = ''; $values = array(); $num_octets = 1; $unicode_length = 0; mbstring_binary_safe_encoding(); $string_length = strlen($utf8_string); reset_mbstring_encoding(); for ($i = 0; $i < $string_length; $i++) { $value = ord($utf8_string[$i]); if ($value < 128) { if ($length && $unicode_length >= $length) { break; } $unicode .= chr($value); $unicode_length++; } else { if (count($values) == 0) { if ($value < 224) { $num_octets = 2; } elseif ($value < 240) { $num_octets = 3; } else { $num_octets = 4; } } $values[] = $value; if ($length && $unicode_length + $num_octets * 3 > $length) { break; } if (count($values) == $num_octets) { for ($j = 0; $j < $num_octets; $j++) { $unicode .= '%' . dechex($values[$j]); } $unicode_length += $num_octets * 3; $values = array(); $num_octets = 1; } } } return $unicode; }
/** * Get extended image metadata, exif or iptc as available. * * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso * created_timestamp, focal_length, shutter_speed, and title. * * The IPTC metadata that is retrieved is APP13, credit, byline, created date * and time, caption, copyright, and title. Also includes FNumber, Model, * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime. * * @todo Try other exif libraries if available. * @since 2.5.0 * * @param string $file * @return bool|array False on failure. Image metadata array on success. */ function wp_read_image_metadata($file) { if (!file_exists($file)) { return false; } list(, , $sourceImageType) = getimagesize($file); /* * EXIF contains a bunch of data we'll probably never need formatted in ways * that are difficult to use. We'll normalize it and just extract the fields * that are likely to be useful. Fractions and numbers are converted to * floats, dates to unix timestamps, and everything else to strings. */ $meta = array('aperture' => 0, 'credit' => '', 'camera' => '', 'caption' => '', 'created_timestamp' => 0, 'copyright' => '', 'focal_length' => 0, 'iso' => 0, 'shutter_speed' => 0, 'title' => '', 'orientation' => 0, 'keywords' => array()); $iptc = array(); /* * Read IPTC first, since it might contain data not available in exif such * as caption, description etc. */ if (is_callable('iptcparse')) { getimagesize($file, $info); if (!empty($info['APP13'])) { $iptc = iptcparse($info['APP13']); // Headline, "A brief synopsis of the caption." if (!empty($iptc['2#105'][0])) { $meta['title'] = trim($iptc['2#105'][0]); /* * Title, "Many use the Title field to store the filename of the image, * though the field may be used in many ways." */ } elseif (!empty($iptc['2#005'][0])) { $meta['title'] = trim($iptc['2#005'][0]); } if (!empty($iptc['2#120'][0])) { // description / legacy caption $caption = trim($iptc['2#120'][0]); mbstring_binary_safe_encoding(); $caption_length = strlen($caption); reset_mbstring_encoding(); if (empty($meta['title']) && $caption_length < 80) { // Assume the title is stored in 2:120 if it's short. $meta['title'] = $caption; } $meta['caption'] = $caption; } if (!empty($iptc['2#110'][0])) { // credit $meta['credit'] = trim($iptc['2#110'][0]); } elseif (!empty($iptc['2#080'][0])) { // creator / legacy byline $meta['credit'] = trim($iptc['2#080'][0]); } if (!empty($iptc['2#055'][0]) && !empty($iptc['2#060'][0])) { // created date and time $meta['created_timestamp'] = strtotime($iptc['2#055'][0] . ' ' . $iptc['2#060'][0]); } if (!empty($iptc['2#116'][0])) { // copyright $meta['copyright'] = trim($iptc['2#116'][0]); } if (!empty($iptc['2#025'][0])) { // keywords array $meta['keywords'] = array_values($iptc['2#025']); } } } /** * Filter the image types to check for exif data. * * @since 2.5.0 * * @param array $image_types Image types to check for exif data. */ if (is_callable('exif_read_data') && in_array($sourceImageType, apply_filters('wp_read_image_metadata_types', array(IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM)))) { $exif = @exif_read_data($file); if (!empty($exif['ImageDescription'])) { mbstring_binary_safe_encoding(); $description_length = strlen($exif['ImageDescription']); reset_mbstring_encoding(); if (empty($meta['title']) && $description_length < 80) { // Assume the title is stored in ImageDescription $meta['title'] = trim($exif['ImageDescription']); } if (empty($meta['caption']) && !empty($exif['COMPUTED']['UserComment'])) { $meta['caption'] = trim($exif['COMPUTED']['UserComment']); } if (empty($meta['caption'])) { $meta['caption'] = trim($exif['ImageDescription']); } } elseif (empty($meta['caption']) && !empty($exif['Comments'])) { $meta['caption'] = trim($exif['Comments']); } if (empty($meta['credit'])) { if (!empty($exif['Artist'])) { $meta['credit'] = trim($exif['Artist']); } elseif (!empty($exif['Author'])) { $meta['credit'] = trim($exif['Author']); } } if (empty($meta['copyright']) && !empty($exif['Copyright'])) { $meta['copyright'] = trim($exif['Copyright']); } if (!empty($exif['FNumber'])) { $meta['aperture'] = round(wp_exif_frac2dec($exif['FNumber']), 2); } if (!empty($exif['Model'])) { $meta['camera'] = trim($exif['Model']); } if (empty($meta['created_timestamp']) && !empty($exif['DateTimeDigitized'])) { $meta['created_timestamp'] = wp_exif_date2ts($exif['DateTimeDigitized']); } if (!empty($exif['FocalLength'])) { $meta['focal_length'] = (string) wp_exif_frac2dec($exif['FocalLength']); } if (!empty($exif['ISOSpeedRatings'])) { $meta['iso'] = is_array($exif['ISOSpeedRatings']) ? reset($exif['ISOSpeedRatings']) : $exif['ISOSpeedRatings']; $meta['iso'] = trim($meta['iso']); } if (!empty($exif['ExposureTime'])) { $meta['shutter_speed'] = (string) wp_exif_frac2dec($exif['ExposureTime']); } if (!empty($exif['Orientation'])) { $meta['orientation'] = $exif['Orientation']; } } foreach (array('title', 'caption', 'credit', 'copyright', 'camera', 'iso') as $key) { if ($meta[$key] && !seems_utf8($meta[$key])) { $meta[$key] = utf8_encode($meta[$key]); } } foreach ($meta['keywords'] as $key => $keyword) { if (!seems_utf8($keyword)) { $meta['keywords'][$key] = utf8_encode($keyword); } } $meta = wp_kses_post_deep($meta); /** * Filter the array of meta data read from an image's exif data. * * @since 2.5.0 * @since 4.4.0 The `$iptc` parameter was added. * * @param array $meta Image meta data. * @param string $file Path to image file. * @param int $sourceImageType Type of image. * @param array $iptc IPTC data. */ return apply_filters('wp_read_image_metadata', $meta, $file, $sourceImageType, $iptc); }
/** * @param string $file * @param string $contents * @param bool|int $mode * @return bool */ public function put_contents($file, $contents, $mode = false) { $tempfile = wp_tempnam($file); $temp = fopen($tempfile, 'wb+'); if (!$temp) { return false; } mbstring_binary_safe_encoding(); $data_length = strlen($contents); $bytes_written = fwrite($temp, $contents); reset_mbstring_encoding(); if ($data_length !== $bytes_written) { fclose($temp); unlink($tempfile); return false; } fseek($temp, 0); // Skip back to the start of the file being written to $ret = @ftp_fput($this->link, $file, $temp, FTP_BINARY); fclose($temp); unlink($tempfile); $this->chmod($file, $mode); return $ret; }
function export_zip() { if (($child = $this->get('child')) && ($dir = $this->css->is_file_ok(dirname($this->css->get_child_target('style.css')), 'search')) && ($version = preg_replace("%[^\\w\\.\\-]%", '', $this->get('version')))) { // use php system upload dir to store temp files so that we can use pclzip $tmpdir = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); $file = trailingslashit($tmpdir) . $child . '-' . $version . '.zip'; mbstring_binary_safe_encoding(); require_once ABSPATH . 'wp-admin/includes/class-pclzip.php'; $archive = new PclZip($file); if ($archive->create($dir, PCLZIP_OPT_REMOVE_PATH, dirname($dir)) == 0) { return FALSE; } reset_mbstring_encoding(); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename=' . basename($file)); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); readfile($file); unlink($file); die; } }
/** * Send an HTTP request to a URI. * * Please note: The only URI that are supported in the HTTP Transport implementation * are the HTTP and HTTPS protocols. * * @access public * @since 2.7.0 * * @global string $wp_version * * @param string $url The request URL. * @param string|array $args { * Optional. Array or string of HTTP request arguments. * * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', or 'PUT'. * Some transports technically allow others, but should not be * assumed. Default 'GET'. * @type int $timeout How long the connection should stay open in seconds. Default 5. * @type int $redirection Number of allowed redirects. Not supported by all transports * Default 5. * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. * Default '1.0'. * @type string $user-agent User-agent value sent. * Default WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ). * @type bool $reject_unsafe_urls Whether to pass URLs through {@see wp_http_validate_url()}. * Default false. * @type bool $blocking Whether the calling code requires the result of the request. * If set to false, the request will be sent to the remote server, * and processing returned to the calling code immediately, the caller * will know if the request succeeded or failed, but will not receive * any response from the remote server. Default true. * @type string|array $headers Array or string of headers to send with the request. * Default empty array. * @type array $cookies List of cookies to send with the request. Default empty array. * @type string|array $body Body to send with the request. Default null. * @type bool $compress Whether to compress the $body when sending the request. * Default false. * @type bool $decompress Whether to decompress a compressed response. If set to false and * compressed content is returned in the response anyway, it will * need to be separately decompressed. Default true. * @type bool $sslverify Whether to verify SSL for the request. Default true. * @type string sslcertificates Absolute path to an SSL certificate .crt file. * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. * @type bool $stream Whether to stream to a file. If set to true and no filename was * given, it will be droped it in the WP temp dir and its name will * be set using the basename of the URL. Default false. * @type string $filename Filename of the file to write to when streaming. $stream must be * set to true. Default null. * @type int $limit_response_size Size in bytes to limit the response to. Default null. * * } * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. * A WP_Error instance upon error. */ public function request($url, $args = array()) { global $wp_version; $defaults = array('method' => 'GET', 'timeout' => apply_filters('http_request_timeout', 5), 'redirection' => apply_filters('http_request_redirection_count', 5), 'httpversion' => apply_filters('http_request_version', '1.0'), 'user-agent' => apply_filters('http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo('url')), 'reject_unsafe_urls' => apply_filters('http_request_reject_unsafe_urls', false), 'blocking' => true, 'headers' => array(), 'cookies' => array(), 'body' => null, 'compress' => false, 'decompress' => true, 'sslverify' => true, 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', 'stream' => false, 'filename' => null, 'limit_response_size' => null); // Pre-parse for the HEAD checks. $args = wp_parse_args($args); // By default, Head requests do not cause redirections. if (isset($args['method']) && 'HEAD' == $args['method']) { $defaults['redirection'] = 0; } $r = wp_parse_args($args, $defaults); /** * Filter the arguments used in an HTTP request. * * @since 2.7.0 * * @param array $r An array of HTTP request arguments. * @param string $url The request URL. */ $r = apply_filters('http_request_args', $r, $url); // The transports decrement this, store a copy of the original value for loop purposes. if (!isset($r['_redirection'])) { $r['_redirection'] = $r['redirection']; } /** * Filter whether to preempt an HTTP request's return value. * * Returning a non-false value from the filter will short-circuit the HTTP request and return * early with that value. A filter should return either: * * - An array containing 'headers', 'body', 'response', 'cookies', and 'filename' elements * - A WP_Error instance * - boolean false (to avoid short-circuiting the response) * * Returning any other value may result in unexpected behaviour. * * @since 2.9.0 * * @param false|array|WP_Error $preempt Whether to preempt an HTTP request's return value. Default false. * @param array $r HTTP request arguments. * @param string $url The request URL. */ $pre = apply_filters('pre_http_request', false, $r, $url); if (false !== $pre) { return $pre; } if (function_exists('wp_kses_bad_protocol')) { if ($r['reject_unsafe_urls']) { $url = wp_http_validate_url($url); } if ($url) { $url = wp_kses_bad_protocol($url, array('http', 'https', 'ssl')); } } $arrURL = @parse_url($url); if (empty($url) || empty($arrURL['scheme'])) { return new WP_Error('http_request_failed', __('A valid URL was not provided.')); } if ($this->block_request($url)) { return new WP_Error('http_request_failed', __('User has blocked requests through HTTP.')); } /* * Determine if this is a https call and pass that on to the transport functions * so that we can blacklist the transports that do not support ssl verification */ $r['ssl'] = $arrURL['scheme'] == 'https' || $arrURL['scheme'] == 'ssl'; // Determine if this request is to OUR install of WordPress. $homeURL = parse_url(get_bloginfo('url')); $r['local'] = 'localhost' == $arrURL['host'] || isset($homeURL['host']) && $homeURL['host'] == $arrURL['host']; unset($homeURL); /* * If we are streaming to a file but no filename was given drop it in the WP temp dir * and pick its name using the basename of the $url. */ if ($r['stream'] && empty($r['filename'])) { $r['filename'] = get_temp_dir() . wp_unique_filename(get_temp_dir(), basename($url)); } /* * Force some settings if we are streaming to a file and check for existence and perms * of destination directory. */ if ($r['stream']) { $r['blocking'] = true; if (!wp_is_writable(dirname($r['filename']))) { return new WP_Error('http_request_failed', __('Destination directory for file streaming does not exist or is not writable.')); } } if (is_null($r['headers'])) { $r['headers'] = array(); } if (!is_array($r['headers'])) { $processedHeaders = self::processHeaders($r['headers'], $url); $r['headers'] = $processedHeaders['headers']; } if (isset($r['headers']['User-Agent'])) { $r['user-agent'] = $r['headers']['User-Agent']; unset($r['headers']['User-Agent']); } if (isset($r['headers']['user-agent'])) { $r['user-agent'] = $r['headers']['user-agent']; unset($r['headers']['user-agent']); } if ('1.1' == $r['httpversion'] && !isset($r['headers']['connection'])) { $r['headers']['connection'] = 'close'; } // Construct Cookie: header if any cookies are set. self::buildCookieHeader($r); // Avoid issues where mbstring.func_overload is enabled. mbstring_binary_safe_encoding(); if (!isset($r['headers']['Accept-Encoding'])) { if ($encoding = WP_Http_Encoding::accept_encoding($url, $r)) { $r['headers']['Accept-Encoding'] = $encoding; } } if (!is_null($r['body']) && '' != $r['body'] || 'POST' == $r['method'] || 'PUT' == $r['method']) { if (is_array($r['body']) || is_object($r['body'])) { $r['body'] = http_build_query($r['body'], null, '&'); if (!isset($r['headers']['Content-Type'])) { $r['headers']['Content-Type'] = 'application/x-www-form-urlencoded; charset=' . get_option('blog_charset'); } } if ('' === $r['body']) { $r['body'] = null; } if (!isset($r['headers']['Content-Length']) && !isset($r['headers']['content-length'])) { $r['headers']['Content-Length'] = strlen($r['body']); } } $response = $this->_dispatch_request($url, $r); reset_mbstring_encoding(); if (is_wp_error($response)) { return $response; } // Append cookies that were used in this request to the response if (!empty($r['cookies'])) { $cookies_set = wp_list_pluck($response['cookies'], 'name'); foreach ($r['cookies'] as $cookie) { if (!in_array($cookie->name, $cookies_set) && $cookie->test($url)) { $response['cookies'][] = $cookie; } } } return $response; }
/** * Get extended image metadata, exif or iptc as available. * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso * created_timestamp, focal_length, shutter_speed, and title. * The IPTC metadata that is retrieved is APP13, credit, byline, created date * and time, caption, copyright, and title. Also includes FNumber, Model, * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime. * @todo Try other exif libraries if available. * @since 2.5.0 * * @param string $file * * @return bool|array False on failure. Image metadata array on success. */ function wp_read_image_metadata($file) { if (!is_file($file)) { return false; } list(, , $sourceImageType) = getimagesize($file); $meta = array(); /* * Read IPTC first, since it might contain data not available in exif such * as caption, description etc. */ if (is_callable('iptcparse')) { getimagesize($file, $info); if (!empty($info['APP13'])) { $iptc = iptcparse($info['APP13']); // Headline, "A brief synopsis of the caption." if (!empty($iptc['2#105'][0])) { $meta['title'] = trim($iptc['2#105'][0]); /* * Title, "Many use the Title field to store the filename of the image, * though the field may be used in many ways." */ } elseif (!empty($iptc['2#005'][0])) { $meta['title'] = trim($iptc['2#005'][0]); } if (!empty($iptc['2#120'][0])) { // description / legacy caption $caption = trim($iptc['2#120'][0]); if (empty($meta['title'])) { mbstring_binary_safe_encoding(); $caption_length = strlen($caption); reset_mbstring_encoding(); // Assume the title is stored in 2:120 if it's short. if ($caption_length < 80) { $meta['title'] = $caption; } else { $meta['caption'] = $caption; } } elseif ($caption != $meta['title']) { $meta['caption'] = $caption; } } if (!empty($iptc['2#110'][0])) { $meta['credit'] = trim($iptc['2#110'][0]); } elseif (!empty($iptc['2#080'][0])) { $meta['credit'] = trim($iptc['2#080'][0]); } if (!empty($iptc['2#055'][0]) and !empty($iptc['2#060'][0])) { $meta['created_timestamp'] = strtotime($iptc['2#055'][0] . ' ' . $iptc['2#060'][0]); } if (!empty($iptc['2#116'][0])) { $meta['copyright'] = trim($iptc['2#116'][0]); } if (!empty($iptc['2#025'])) { $meta['keywords'] = $iptc['2#025']; } } } /** * Filter the image types to check for exif data. * @since 2.5.0 * * @param array $image_types Image types to check for exif data. */ if (is_callable('exif_read_data') && in_array($sourceImageType, apply_filters('wp_read_image_metadata_types', array(IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM)))) { $exif = @exif_read_data($file); unset($exif['MakerNote']); // Title if (empty($meta['title']) && !empty($exif['Title'])) { $meta['title'] = trim($exif['Title']); } // Descrioption if (!empty($exif['ImageDescription'])) { mbstring_binary_safe_encoding(); $description_length = strlen($exif['ImageDescription']); reset_mbstring_encoding(); if (empty($meta['title']) && $description_length < 80) { // Assume the title is stored in ImageDescription $meta['title'] = trim($exif['ImageDescription']); if (empty($meta['caption']) && !empty($exif['COMPUTED']['UserComment']) && trim($exif['COMPUTED']['UserComment']) != $meta['title']) { $meta['caption'] = trim($exif['COMPUTED']['UserComment']); } } elseif (empty($meta['caption']) && trim($exif['ImageDescription']) != $meta['title']) { $meta['caption'] = trim($exif['ImageDescription']); } } elseif (empty($meta['caption']) && !empty($exif['Comments']) && trim($exif['Comments']) != $meta['title']) { $meta['caption'] = trim($exif['Comments']); } // Credit if (empty($meta['credit'])) { if (!empty($exif['Artist'])) { $meta['credit'] = trim($exif['Artist']); } elseif (!empty($exif['Author'])) { $meta['credit'] = trim($exif['Author']); } } // Copyright if (empty($meta['copyright']) && !empty($exif['Copyright'])) { $meta['copyright'] = trim($exif['Copyright']); } // Camera Make if (!empty($exif['Make'])) { $meta['make'] = $exif['Make']; } // Camera Model if (!empty($exif['Model'])) { $meta['model'] = trim($exif['Model']); } // Exposure Time (shutter speed) if (!empty($exif['ExposureTime'])) { $meta['exposure'] = $exif['ExposureTime'] . 's'; $meta['shutter_speed'] = (string) wp_exif_frac2dec($exif['ExposureTime']) . 's'; } // Aperture if (!empty($exif['COMPUTED']['ApertureFNumber'])) { $meta['aperture'] = $exif['COMPUTED']['ApertureFNumber']; } elseif (!empty($exif['FNumber'])) { $meta['aperture'] = 'f/' . (string) round(wp_exif_frac2dec($exif['FNumber']), 2); } // ISO if (!empty($exif['ISOSpeedRatings'])) { $meta['iso'] = is_array($exif['ISOSpeedRatings']) ? reset($exif['ISOSpeedRatings']) : $exif['ISOSpeedRatings']; $meta['iso'] = trim($meta['iso']); } // Date if (!empty($exif['DateTime'])) { $meta['date'] = $exif['DateTime']; } // Created TimeStamp if (empty($meta['created_timestamp']) && !empty($exif['DateTimeDigitized'])) { $meta['created_timestamp'] = wp_exif_date2ts($exif['DateTimeDigitized']); } // Lens if (!empty($exif['UndefinedTag:0xA434'])) { $meta['lens'] = $exif['UndefinedTag:0xA434']; } // Focus Distance if (!empty($exif['COMPUTED']['FocusDistance'])) { $meta['distance'] = $exif['COMPUTED']['FocusDistance']; } // Focal Length if (!empty($exif['FocalLength'])) { $meta['focallength'] = (string) round(wp_exif_frac2dec($exif['FocalLength'])) . 'mm'; } // Focal Length 35mm if (!empty($exif['FocalLengthIn35mmFilm'])) { $meta['focallength35'] = $exif['FocalLengthIn35mmFilm'] . 'mm'; } // Flash data if (!empty($exif['Flash'])) { // we need to interpret the result - it's given as a number and we want a human-readable description. $fdata = $exif['Flash']; switch ($fdata) { case 0: $fdata = 'No Flash'; break; case 1: $fdata = 'Flash'; break; case 5: $fdata = 'Flash, strobe return light not detected'; break; case 7: $fdata = 'Flash, strob return light detected'; break; case 9: $fdata = 'Compulsory Flash'; break; case 13: $fdata = 'Compulsory Flash, Return light not detected'; break; case 15: $fdata = 'Compulsory Flash, Return light detected'; break; case 16: $fdata = 'No Flash'; break; case 24: $fdata = 'No Flash'; break; case 25: $fdata = 'Flash, Auto-Mode'; break; case 29: $fdata = 'Flash, Auto-Mode, Return light not detected'; break; case 31: $fdata = 'Flash, Auto-Mode, Return light detected'; break; case 32: $fdata = 'No Flash'; break; case 65: $fdata = 'Red Eye'; break; case 69: $fdata = 'Red Eye, Return light not detected'; break; case 71: $fdata = 'Red Eye, Return light detected'; break; case 73: $fdata = 'Red Eye, Compulsory Flash'; break; case 77: $fdata = 'Red Eye, Compulsory Flash, Return light not detected'; break; case 79: $fdata = 'Red Eye, Compulsory Flash, Return light detected'; break; case 89: $fdata = 'Red Eye, Auto-Mode'; break; case 93: $fdata = 'Red Eye, Auto-Mode, Return light not detected'; break; case 95: $fdata = 'Red Eye, Auto-Mode, Return light detected'; break; default: $fdata = 'Unknown: ' . $fdata; break; } $meta['flashdata'] = $fdata; } // Lens Make if (!empty($exif['UndefinedTag:0xA433'])) { $meta['lensmake'] = $exif['UndefinedTag:0xA433']; } // Software if (!empty($exif['Software'])) { $meta['software'] = $exif['Software']; } // Orientation if (!empty($exif['Orientation'])) { $meta['orientation'] = $exif['Orientation']; } $exif_sections = @exif_read_data($file, null, true); if (isset($exif_sections['GPS'])) { $meta['GPS'] = $this->getGPSfromExif($exif_sections['GPS']); } unset($exif_sections); //$meta['exif'] = $exif; } foreach (array('title', 'caption', 'credit', 'copyright', 'model', 'iso', 'software') as $key) { if (!empty($meta[$key]) && !seems_utf8($meta[$key])) { $meta[$key] = utf8_encode($meta[$key]); } } if (!empty($meta['keywords'])) { foreach ($meta['keywords'] as $i => $key) { if (!seems_utf8($key)) { $meta['keywords'][$i] = utf8_encode($key); } } } foreach ($meta as &$value) { if (is_string($value)) { $value = wp_kses_post($value); } } /** * Filter the array of meta data read from an image's exif data. * @since 2.5.0 * * @param array $meta Image meta data. * @param string $file Path to image file. * @param int $sourceImageType Type of image. */ return apply_filters('wp_read_image_metadata', $meta, $file, $sourceImageType); }