Last active
August 26, 2017 14:11
-
-
Save tokkonopapa/1948ceb9ff42ef21e9baf2d68b04d16e to your computer and use it in GitHub Desktop.
Fix the issue that an error message would not be shown when download/read/write error happens.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* IP Geo Block - Cron Class | |
* | |
* @package IP_Geo_Block | |
* @author tokkonopapa <[email protected]> | |
* @license GPL-2.0+ | |
* @link http://www.ipgeoblock.com/ | |
* @copyright 2013-2017 tokkonopapa | |
*/ | |
class IP_Geo_Block_Cron { | |
/** | |
* Cron scheduler. | |
* | |
*/ | |
private static function schedule_cron_job( &$update, $db, $immediate = FALSE ) { | |
wp_clear_scheduled_hook( IP_Geo_Block::CRON_NAME, array( $immediate ) ); | |
if ( $update['auto'] ) { | |
$now = time(); | |
$cycle = DAY_IN_SECONDS * (int)$update['cycle']; | |
if ( FALSE === $immediate && | |
$now - (int)$db['ipv4_last'] < $cycle && | |
$now - (int)$db['ipv6_last'] < $cycle ) { | |
$update['retry'] = 0; | |
$next = max( (int)$db['ipv4_last'], (int)$db['ipv6_last'] ) + | |
$cycle + rand( DAY_IN_SECONDS, DAY_IN_SECONDS * 6 ); | |
} else { | |
++$update['retry']; | |
$next = $now + ( $immediate ? 0 : DAY_IN_SECONDS ); | |
} | |
wp_schedule_single_event( $next, IP_Geo_Block::CRON_NAME, array( $immediate ) ); | |
} | |
} | |
/** | |
* Database auto downloader. | |
* | |
* This function is called when: | |
* 1. Plugin is activated | |
* 2. WP Cron is kicked | |
* under the following condition: | |
* A. Once per site when this plugin is activated on network wide | |
* B. Multiple time for each blog when this plugin is individually activated | |
*/ | |
public static function exec_update_db( $immediate = FALSE ) { | |
$settings = IP_Geo_Block::get_option(); | |
$args = IP_Geo_Block::get_request_headers( $settings ); | |
// extract ip address from transient API to confirm the request source | |
add_filter( IP_Geo_Block::PLUGIN_NAME . '-ip-addr', array( __CLASS__, 'extract_ip' ) ); | |
// download database files (higher priority order) | |
foreach ( $providers = IP_Geo_Block_Provider::get_addons() as $provider ) { | |
if ( $geo = IP_Geo_Block_API::get_instance( $provider, $settings ) ) { | |
$res[ $provider ] = $geo->download( $settings[ $provider ], $args ); | |
// re-schedule cron job | |
self::schedule_cron_job( $settings['update'], $settings[ $provider ], FALSE ); | |
// update option settings | |
self::update_settings( $settings, array( 'update', $provider ) ); | |
// update matching rule immediately | |
if ( $immediate && FALSE !== ( $stat = get_transient( IP_Geo_Block::CRON_NAME ) ) && 'done' !== $stat ) { | |
$validate = IP_Geo_Block::get_geolocation( NULL, array( $provider ) ); | |
$validate = IP_Geo_Block::validate_country( NULL, $validate, $settings ); | |
// if blocking may happen then disable validation | |
if ( -1 !== (int)$settings['matching_rule'] && 'passed' !== $validate['result'] && | |
( empty( $_SERVER['HTTP_X_REQUESTED_FROM'] ) || FALSE === strpos( $_SERVER['HTTP_X_REQUESTED_FROM'], 'InfiniteWP' ) ) ) { | |
$settings['matching_rule'] = -1; | |
} | |
// setup country code if it needs to be initialized | |
if ( -1 === (int)$settings['matching_rule'] && 'ZZ' !== $validate['code'] ) { | |
$settings['matching_rule'] = 0; // white list | |
if ( FALSE === strpos( $settings['white_list'], $validate['code'] ) ) | |
$settings['white_list'] .= ( $settings['white_list'] ? ',' : '' ) . $validate['code']; | |
// update option settings | |
self::update_settings( $settings, array( 'matching_rule', 'white_list' ) ); | |
// finished to update matching rule | |
set_transient( IP_Geo_Block::CRON_NAME, 'done', 5 * MINUTE_IN_SECONDS ); | |
} | |
} | |
} | |
} | |
return isset( $res ) ? $res : NULL; | |
} | |
/** | |
* Update setting data according to the site type. | |
* | |
*/ | |
private static function update_settings( $src, $keys = array() ) { | |
require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
// for multisite (@since 3.0.0 in wp-admin/includes/plugin.php) | |
if ( is_plugin_active_for_network( IP_GEO_BLOCK_BASE ) ) { | |
global $wpdb; | |
$blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ); | |
foreach ( $blog_ids as $id ) { | |
switch_to_blog( $id ); | |
$dst = IP_Geo_Block::get_option(); | |
foreach ( $keys as $key ) { | |
$dst[ $key ] = $src[ $key ]; | |
} | |
update_option( IP_Geo_Block::OPTION_NAME, $dst ); | |
restore_current_blog(); | |
} | |
} | |
// for single site | |
else { | |
update_option( IP_Geo_Block::OPTION_NAME, $src ); | |
} | |
} | |
/** | |
* Extract ip address from transient API. | |
* | |
*/ | |
public static function extract_ip() { | |
return filter_var( | |
$ip_adrs = get_transient( IP_Geo_Block::CRON_NAME ), FILTER_VALIDATE_IP | |
) ? $ip_adrs : $_SERVER['REMOTE_ADDR']; | |
} | |
/** | |
* Kick off a cron job to download database immediately in background on activation. | |
* | |
*/ | |
public static function start_update_db( $settings, $force = FALSE ) { | |
require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
// the status is still inactive when this plugin is activated on dashboard. | |
if ( ! ( is_plugin_active ( IP_GEO_BLOCK_BASE ) || // @since 2.5.0 | |
is_plugin_active_for_network( IP_GEO_BLOCK_BASE ) ) || $force ) { // @since 3.0.0 | |
set_transient( IP_Geo_Block::CRON_NAME, IP_Geo_Block::get_ip_address(), MINUTE_IN_SECONDS ); | |
self::schedule_cron_job( $settings['update'], NULL, TRUE ); | |
} | |
} | |
public static function stop_update_db() { | |
wp_clear_scheduled_hook( IP_Geo_Block::CRON_NAME, array( FALSE ) ); // @since 2.1.0 | |
} | |
/** | |
* Kick off a cron job to garbage collection for IP address cache. | |
* | |
* Note: When the init action occurs in /wp-settings.php, wp_cron() runs. | |
*/ | |
public static function exec_cache_gc( $settings ) { | |
require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
if ( is_plugin_active_for_network( IP_GEO_BLOCK_BASE ) ) { | |
global $wpdb; | |
$blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ); | |
foreach ( $blog_ids as $id ) { | |
switch_to_blog( $id ); | |
IP_Geo_Block_Logs::delete_expired_cache( $settings['cache_time'] ); | |
restore_current_blog(); | |
} | |
} | |
// for single site | |
else { | |
IP_Geo_Block_Logs::delete_expired_cache( $settings['cache_time'] ); | |
} | |
self::stop_cache_gc(); | |
self::start_cache_gc( $settings ); | |
} | |
public static function start_cache_gc( $settings ) { | |
if ( ! wp_next_scheduled( IP_Geo_Block::CACHE_NAME ) ) | |
wp_schedule_single_event( time() + $settings['cache_time_gc'], IP_Geo_Block::CACHE_NAME ); | |
} | |
public static function stop_cache_gc() { | |
wp_clear_scheduled_hook( IP_Geo_Block::CACHE_NAME ); // @since 2.1.0 | |
} | |
/** | |
* Download zip/gz file, uncompress and save it to specified file | |
* | |
* @param string $url URL of remote file to be downloaded. | |
* @param array $args request headers. | |
* @param string $filename full path to the downloaded file. | |
* @param int $modified time of last modified on the remote server. | |
* @return array status message. | |
*/ | |
public static function download_zip( $url, $args, $filename, $modified ) { | |
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php'; | |
$fs = IP_Geo_Block_FS::init( 'download_zip' ); | |
// if the name of src file is changed, then update the dst | |
if ( basename( $filename ) !== ( $base = pathinfo( $url, PATHINFO_FILENAME ) ) ) | |
$filename = dirname( $filename ) . '/' . $base; | |
// check file | |
if ( ! file_exists( $filename ) ) | |
$modified = 0; | |
// set 'If-Modified-Since' request header | |
$args += array( | |
'headers' => array( | |
'If-Modified-Since' => gmdate( DATE_RFC1123, (int)$modified ), | |
), | |
); | |
// fetch file and get response code & message | |
$src = wp_remote_head( ( $url = esc_url_raw( $url ) ), $args ); | |
if ( is_wp_error( $src ) ) | |
return array( | |
'code' => $src->get_error_code(), | |
'message' => $src->get_error_message(), | |
); | |
$code = wp_remote_retrieve_response_code ( $src ); | |
$mssg = wp_remote_retrieve_response_message( $src ); | |
$data = wp_remote_retrieve_header( $src, 'last-modified' ); | |
$modified = $data ? strtotime( $data ) : $modified; | |
if ( 304 == $code ) | |
return array( | |
'code' => $code, | |
'message' => __( 'Your database file is up-to-date.', 'ip-geo-block' ), | |
'filename' => $filename, | |
'modified' => $modified, | |
); | |
elseif ( 200 != $code ) | |
return array( | |
'code' => $code, | |
'message' => $code.' '.$mssg, | |
); | |
// downloaded and unzip | |
try { | |
// download file | |
$src = download_url( $url ); | |
if ( is_wp_error( $src ) ) | |
throw new Exception( | |
$src->get_error_code() . ' ' . $src->get_error_message() | |
); | |
// get extension | |
$args = strtolower( pathinfo( $url, PATHINFO_EXTENSION ) ); | |
// unzip file | |
if ( 'gz' === $args && function_exists( 'gzopen' ) ) { | |
if ( FALSE === ( $gz = gzopen( $src, 'r' ) ) ) | |
throw new Exception( | |
sprintf( __( 'Unable to read %s. Please check the permission.', 'ip-geo-block' ), $src ) | |
); | |
if ( FALSE === ( $fp = @fopen( $filename, 'cb' ) ) ) | |
throw new Exception( | |
sprintf( __( 'Unable to write %s. Please check the permission.', 'ip-geo-block' ), $filename ) | |
); | |
if ( ! flock( $fp, LOCK_EX ) ) | |
throw new Exception( | |
sprintf( __( 'Can\'t lock %s. Please try again after a while.', 'ip-geo-block' ), $filename ) | |
); | |
ftruncate( $fp, 0 ); // truncate file | |
// same block size in wp-includes/class-http.php | |
while ( $data = gzread( $gz, 4096 ) ) { | |
fwrite( $fp, $data, strlen( $data ) ); | |
} | |
} | |
elseif ( 'zip' === $args && class_exists( 'ZipArchive', FALSE ) ) { | |
$tmp = get_temp_dir(); // @since 2.5 | |
$ret = $fs->unzip_file( $src, $tmp ); // @since 2.5 | |
if ( is_wp_error( $ret ) ) | |
throw new Exception( | |
$ret->get_error_code() . ' ' . $ret->get_error_message() | |
); | |
if ( FALSE === ( $gz = @fopen( $tmp .= basename( $filename ), 'r' ) ) ) | |
throw new Exception( | |
sprintf( __( 'Unable to read %s. Please check the permission.', 'ip-geo-block' ), $tmp ) | |
); | |
if ( FALSE === ( $fp = @fopen( $filename, 'cb' ) ) ) | |
throw new Exception( | |
sprintf( __( 'Unable to write %s. Please check the permission.', 'ip-geo-block' ), $filename ) | |
); | |
if ( ! flock( $fp, LOCK_EX ) ) | |
throw new Exception( | |
sprintf( __( 'Can\'t lock %s. Please try again after a while.', 'ip-geo-block' ), $filename ) | |
); | |
ftruncate( $fp, 0 ); // truncate file | |
// same block size in wp-includes/class-http.php | |
while ( $data = fread( $gz, 4096 ) ) { | |
fwrite( $fp, $data, strlen( $data ) ); | |
} | |
} | |
else { | |
throw new Exception( __( 'gz or zip is not supported on your system.', 'ip-geo-block' ) ); | |
} | |
} | |
// error handler | |
catch ( Exception $e ) { | |
$err = array( | |
'code' => $e->getCode(), | |
'message' => $e->getMessage(), | |
); | |
} | |
if ( ! empty( $fp ) ) { | |
fflush( $fp ); // flush output before releasing the lock | |
flock ( $fp, LOCK_UN ); // release the lock | |
fclose( $fp ); | |
} | |
! empty( $gz ) and gzclose( $gz ); | |
! empty( $tmp ) && @is_file( $tmp ) and @unlink( $tmp ); | |
! is_wp_error( $src ) && @is_file( $src ) and @unlink( $src ); | |
return empty( $err ) ? array( | |
'code' => $code, | |
'message' => sprintf( | |
__( 'Last update: %s', 'ip-geo-block' ), IP_Geo_Block_Util::localdate( $modified ) | |
), | |
'filename' => $filename, | |
'modified' => $modified, | |
) : $err; | |
} | |
} |
Author
tokkonopapa
commented
Aug 24, 2017
- Topic on support forum: https://wordpress.org/support/topic/database-file-does-not-exist/
- Difference between 3.0.4.1 and this file: tokkonopapa/WordPress-IP-Geo-Block@82d6a17#diff-52e6e62a844a99728346dfe5466c6544
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment