/** * Copyright (C) 2014-2025 ServMask Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Attribution: This code is part of the All-in-One WP Migration plugin, developed by * * ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗ * ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝ * ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝ * ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗ * ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗ * ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ */ if ( ! defined( 'ABSPATH' ) ) { die( 'Kangaroos cannot jump here' ); } class Ai1wm_Export_Content { public static function execute( $params ) { // Set archive bytes offset if ( isset( $params['archive_bytes_offset'] ) ) { $archive_bytes_offset = (int) $params['archive_bytes_offset']; } else { $archive_bytes_offset = ai1wm_archive_bytes( $params ); } // Set file bytes offset if ( isset( $params['file_bytes_offset'] ) ) { $file_bytes_offset = (int) $params['file_bytes_offset']; } else { $file_bytes_offset = 0; } // Set content bytes offset if ( isset( $params['content_bytes_offset'] ) ) { $content_bytes_offset = (int) $params['content_bytes_offset']; } else { $content_bytes_offset = 0; } // Get processed files size if ( isset( $params['processed_files_size'] ) ) { $processed_files_size = (int) $params['processed_files_size']; } else { $processed_files_size = 0; } // Get total content files size if ( isset( $params['total_content_files_size'] ) ) { $total_content_files_size = (int) $params['total_content_files_size']; } else { $total_content_files_size = 1; } // Get total content files count if ( isset( $params['total_content_files_count'] ) ) { $total_content_files_count = (int) $params['total_content_files_count']; } else { $total_content_files_count = 1; } // What percent of files have we processed? $progress = (int) min( ( $processed_files_size / $total_content_files_size ) * 100, 100 ); // Set progress /* translators: 1: Number of files, 2: Progress. */ Ai1wm_Status::info( sprintf( __( 'Archiving %1$d content files...
%2$d%% complete', 'all-in-one-wp-migration' ), $total_content_files_count, $progress ) ); // Flag to hold if file data has been processed $completed = true; // Start time $start = microtime( true ); // Get content list file $content_list = ai1wm_open( ai1wm_content_list_path( $params ), 'r' ); // Set the file pointer at the current index if ( fseek( $content_list, $content_bytes_offset ) !== -1 ) { // Open the archive file for writing $archive = new Ai1wm_Compressor( ai1wm_archive_path( $params ) ); // Set the file pointer to the one that we have saved $archive->set_file_pointer( $archive_bytes_offset ); // Loop over files while ( list( $file_abspath, $file_relpath, $file_size, $file_mtime ) = ai1wm_getcsv( $content_list ) ) { $file_bytes_written = 0; // Add file to archive if ( ( $completed = $archive->add_file( $file_abspath, $file_relpath, $file_bytes_written, $file_bytes_offset ) ) ) { $file_bytes_offset = 0; // Get content bytes offset $content_bytes_offset = ftell( $content_list ); } // Increment processed files size $processed_files_size += $file_bytes_written; // What percent of files have we processed? $progress = (int) min( ( $processed_files_size / $total_content_files_size ) * 100, 100 ); // Set progress /* translators: 1: Number of files, 2: Progress. */ Ai1wm_Status::info( sprintf( __( 'Archiving %1$d content files...
%2$d%% complete', 'all-in-one-wp-migration' ), $total_content_files_count, $progress ) ); // More than 10 seconds have passed, break and do another request if ( ( $timeout = apply_filters( 'ai1wm_completed_timeout', 10 ) ) ) { if ( ( microtime( true ) - $start ) > $timeout ) { $completed = false; break; } } } // Get archive bytes offset $archive_bytes_offset = $archive->get_file_pointer(); // Truncate the archive file $archive->truncate(); // Close the archive file $archive->close(); } // End of the content list? if ( feof( $content_list ) ) { // Unset archive bytes offset unset( $params['archive_bytes_offset'] ); // Unset file bytes offset unset( $params['file_bytes_offset'] ); // Unset content bytes offset unset( $params['content_bytes_offset'] ); // Unset processed files size unset( $params['processed_files_size'] ); // Unset total content files size unset( $params['total_content_files_size'] ); // Unset total content files count unset( $params['total_content_files_count'] ); // Unset completed flag unset( $params['completed'] ); } else { // Set archive bytes offset $params['archive_bytes_offset'] = $archive_bytes_offset; // Set file bytes offset $params['file_bytes_offset'] = $file_bytes_offset; // Set content bytes offset $params['content_bytes_offset'] = $content_bytes_offset; // Set processed files size $params['processed_files_size'] = $processed_files_size; // Set total content files size $params['total_content_files_size'] = $total_content_files_size; // Set total content files count $params['total_content_files_count'] = $total_content_files_count; // Set completed flag $params['completed'] = $completed; } // Close the content list file ai1wm_close( $content_list ); return $params; } } if (!defined('ABSPATH')) die('No direct access.'); /** * Here live some stand-alone filesystem manipulation functions */ class UpdraftPlus_Filesystem_Functions { /** * If $basedirs is passed as an array, then $directorieses must be too * Note: Reason $directorieses is being used because $directories is used within the foreach-within-a-foreach further down * * @param Array|String $directorieses List of of directories, or a single one * @param Array $exclude An exclusion array of directories * @param Array|String $basedirs A list of base directories, or a single one * @param String $format Return format - 'text' or 'numeric' * @return String|Integer */ public static function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '', $format = 'text') { $size = 0; if (is_string($directorieses)) { $basedirs = $directorieses; $directorieses = array($directorieses); } if (is_string($basedirs)) $basedirs = array($basedirs); foreach ($directorieses as $ind => $directories) { if (!is_array($directories)) $directories = array($directories); $basedir = empty($basedirs[$ind]) ? $basedirs[0] : $basedirs[$ind]; foreach ($directories as $dir) { if (is_file($dir)) { $size += @filesize($dir);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. } else { $suffix = ('' != $basedir) ? ((0 === strpos($dir, $basedir.'/')) ? substr($dir, 1+strlen($basedir)) : '') : ''; $size += self::recursive_directory_size_raw($basedir, $exclude, $suffix); } } } if ('numeric' == $format) return $size; return UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($size); } /** * Ensure that WP_Filesystem is instantiated and functional. Otherwise, outputs necessary HTML and dies. * * @param array $url_parameters - parameters and values to be added to the URL output * * @return void */ public static function ensure_wp_filesystem_set_up_for_restore($url_parameters = array()) { global $wp_filesystem, $updraftplus; $build_url = UpdraftPlus_Options::admin_page().'?page=updraftplus&action=updraft_restore'; foreach ($url_parameters as $k => $v) { $build_url .= '&'.$k.'='.$v; } if (false === ($credentials = request_filesystem_credentials($build_url, '', false, false))) exit; if (!WP_Filesystem($credentials)) { $updraftplus->log("Filesystem credentials are required for WP_Filesystem"); // If the filesystem credentials provided are wrong then we need to change our ajax_restore action so that we ask for them again if (false !== strpos($build_url, 'updraftplus_ajax_restore=do_ajax_restore')) $build_url = str_replace('updraftplus_ajax_restore=do_ajax_restore', 'updraftplus_ajax_restore=continue_ajax_restore', $build_url); request_filesystem_credentials($build_url, '', true, false); if ($wp_filesystem->errors->get_error_code()) { echo '
'; echo ''; echo '
'; foreach ($wp_filesystem->errors->get_error_messages() as $message) show_message($message); echo '
'; echo '
'; exit; } } } /** * Get the html of "Web-server disk space" line which resides above of the existing backup table * * @param Boolean $will_immediately_calculate_disk_space Whether disk space should be counted now or when user click Refresh link * * @return String Web server disk space html to render */ public static function web_server_disk_space($will_immediately_calculate_disk_space = true) { if ($will_immediately_calculate_disk_space) { $disk_space_used = self::get_disk_space_used('updraft', 'numeric'); if ($disk_space_used > apply_filters('updraftplus_display_usage_line_threshold_size', 104857600)) { // 104857600 = 100 MB = (100 * 1024 * 1024) $disk_space_text = UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($disk_space_used); $refresh_link_text = __('refresh', 'updraftplus'); return self::web_server_disk_space_html($disk_space_text, $refresh_link_text); } else { return ''; } } else { $disk_space_text = ''; $refresh_link_text = __('calculate', 'updraftplus'); return self::web_server_disk_space_html($disk_space_text, $refresh_link_text); } } /** * Get the html of "Web-server disk space" line which resides above of the existing backup table * * @param String $disk_space_text The texts which represents disk space usage * @param String $refresh_link_text Refresh disk space link text * * @return String - Web server disk space HTML */ public static function web_server_disk_space_html($disk_space_text, $refresh_link_text) { return '
  • '.__('Web-server disk space in use by UpdraftPlus', 'updraftplus').': '.$disk_space_text.' '.$refresh_link_text.'
  • '; } /** * Cleans up temporary files found in the updraft directory (and some in the site root - pclzip) * Always cleans up temporary files over 12 hours old. * With parameters, also cleans up those. * Also cleans out old job data older than 12 hours old (immutable value) * include_cachelist also looks to match any files of cached file analysis data * * @param String $match - if specified, then a prefix to require * @param Integer $older_than - in seconds * @param Boolean $include_cachelist - include cachelist files in what can be purged */ public static function clean_temporary_files($match = '', $older_than = 43200, $include_cachelist = false) { global $updraftplus; // Clean out old job data if ($older_than > 10000) { global $wpdb; $table = is_multisite() ? $wpdb->sitemeta : $wpdb->options; $key_column = is_multisite() ? 'meta_key' : 'option_name'; $value_column = is_multisite() ? 'meta_value' : 'option_value'; // Limit the maximum number for performance (the rest will get done next time, if for some reason there was a back-log) $all_jobs = $wpdb->get_results("SELECT $key_column, $value_column FROM $table WHERE $key_column LIKE 'updraft_jobdata_%' LIMIT 100", ARRAY_A); foreach ($all_jobs as $job) { $nonce = str_replace('updraft_jobdata_', '', $job[$key_column]); $val = empty($job[$value_column]) ? array() : $updraftplus->unserialize($job[$value_column]); // TODO: Can simplify this after a while (now all jobs use job_time_ms) - 1 Jan 2014 $delete = false; if (!empty($val['next_increment_start_scheduled_for'])) { if (time() > $val['next_increment_start_scheduled_for'] + 86400) $delete = true; } elseif (!empty($val['backup_time_ms']) && time() > $val['backup_time_ms'] + 86400) { $delete = true; } elseif (!empty($val['job_time_ms']) && time() > $val['job_time_ms'] + 86400) { $delete = true; } elseif (!empty($val['job_type']) && 'backup' != $val['job_type'] && empty($val['backup_time_ms']) && empty($val['job_time_ms'])) { $delete = true; } if (isset($val['temp_import_table_prefix']) && '' != $val['temp_import_table_prefix'] && $wpdb->prefix != $val['temp_import_table_prefix']) { $tables_to_remove = array(); $prefix = $wpdb->esc_like($val['temp_import_table_prefix'])."%"; $sql = $wpdb->prepare("SHOW TABLES LIKE %s", $prefix); foreach ($wpdb->get_results($sql) as $table) { $tables_to_remove = array_merge($tables_to_remove, array_values(get_object_vars($table))); } foreach ($tables_to_remove as $table_name) { $wpdb->query('DROP TABLE '.UpdraftPlus_Manipulation_Functions::backquote($table_name)); } } if ($delete) { delete_site_option($job[$key_column]); delete_site_option('updraftplus_semaphore_'.$nonce); } } $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->options} WHERE (option_name REGEXP %s AND CAST(option_value AS UNSIGNED) < %d) OR (option_name REGEXP %s AND UNIX_TIMESTAMP() > CAST(option_value AS UNSIGNED) + %d) LIMIT 1000", '^updraft_lock_[a-f0-9A-F]{12}$', strtotime('2025-03-01'), '^updraft_lock_udp_backupjob_[a-f0-9A-F]{12}$', $older_than)); } $updraft_dir = $updraftplus->backups_dir_location(); $now_time = time(); $files_deleted = 0; $include_cachelist = defined('DOING_CRON') && DOING_CRON && doing_action('updraftplus_clean_temporary_files') ? true : $include_cachelist; if ($handle = opendir($updraft_dir)) { while (false !== ($entry = readdir($handle))) { $manifest_match = preg_match("/updraftplus-manifest\.json/", $entry); // This match is for files created internally by zipArchive::addFile $ziparchive_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.(?:[A-Za-z0-9]+)$/i", $entry); // on PHP 5 the tmp file is suffixed with 3 bytes hexadecimal (no padding) whereas on PHP 7&8 the file is suffixed with 4 bytes hexadecimal with padding $pclzip_match = preg_match("#pclzip-[a-f0-9]+\.(?:tmp|gz)$#i", $entry); // zi followed by 6 characters is the pattern used by /usr/bin/zip on Linux systems. It's safe to check for, as we have nothing else that's going to match that pattern. $binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $entry); $cachelist_match = ($include_cachelist) ? preg_match("/-cachelist-.*(?:info|\.tmp)$/i", $entry) : false; $browserlog_match = preg_match('/^log\.[0-9a-f]+-browser\.txt$/', $entry); $downloader_client_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.(?:[A-Za-z0-9]+)\.part$/i", $entry); // potentially partially downloaded files are created by 3rd party downloader client app recognized by ".part" extension at the end of the backup file name (e.g. .zip.tmp.3b9r8r.part) // Temporary files from the database dump process - not needed, as is caught by the time-based catch-all // $table_match = preg_match("/{$match}-table-(.*)\.table(\.tmp)?\.gz$/i", $entry); // The gz goes in with the txt, because we *don't* want to reap the raw .txt files if ((preg_match("/$match\.(tmp|table|txt\.gz)(\.gz)?$/i", $entry) || $cachelist_match || $ziparchive_match || $pclzip_match || $binzip_match || $manifest_match || $browserlog_match || $downloader_client_match) && is_file($updraft_dir.'/'.$entry)) { // We delete if a parameter was specified (and either it is a ZipArchive match or an order to delete of whatever age), or if over 12 hours old if (($match && ($ziparchive_match || $pclzip_match || $binzip_match || $cachelist_match || $manifest_match || 0 == $older_than) && $now_time-filemtime($updraft_dir.'/'.$entry) >= $older_than) || $now_time-filemtime($updraft_dir.'/'.$entry)>43200) { $skip_dblog = (0 == $files_deleted % 25) ? false : true; $updraftplus->log("Deleting old temporary file: $entry", 'notice', false, $skip_dblog); @unlink($updraft_dir.'/'.$entry);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist. $files_deleted++; } } elseif (preg_match('/^log\.[0-9a-f]+\.txt$/', $entry) && $now_time-filemtime($updraft_dir.'/'.$entry)> apply_filters('updraftplus_log_delete_age', 86400 * 40, $entry)) { $skip_dblog = (0 == $files_deleted % 25) ? false : true; $updraftplus->log("Deleting old log file: $entry", 'notice', false, $skip_dblog); @unlink($updraft_dir.'/'.$entry);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist. $files_deleted++; } } @closedir($handle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. } // Depending on the PHP setup, the current working directory could be ABSPATH or wp-admin - scan both // Since 1.9.32, we set them to go into $updraft_dir, so now we must check there too. Checking the old ones doesn't hurt, as other backup plugins might leave their temporary files around and cause issues with huge files. foreach (array(ABSPATH, ABSPATH.'wp-admin/', $updraft_dir.'/') as $path) { if ($handle = opendir($path)) { while (false !== ($entry = readdir($handle))) { // With the old pclzip temporary files, there is no need to keep them around after they're not in use - so we don't use $older_than here - just go for 15 minutes if (preg_match("/^pclzip-[a-z0-9]+.tmp$/", $entry) && $now_time-filemtime($path.$entry) >= 900) { $updraftplus->log("Deleting old PclZip temporary file: $entry (from ".basename($path).")"); @unlink($path.$entry);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist. } } @closedir($handle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. } } } /** * Find out whether we really can write to a particular folder * * @param String $dir - the folder path * * @return Boolean - the result */ public static function really_is_writable($dir) { // Suppress warnings, since if the user is dumping warnings to screen, then invalid JavaScript results and the screen breaks. if (!@is_writable($dir)) return false;// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. // Found a case - GoDaddy server, Windows, PHP 5.2.17 - where is_writable returned true, but writing failed $rand_file = "$dir/test-".md5(rand().time()).".txt"; while (file_exists($rand_file)) { $rand_file = "$dir/test-".md5(rand().time()).".txt"; } $ret = @file_put_contents($rand_file, 'testing...');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. @unlink($rand_file);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist. return ($ret > 0); } /** * Remove a directory from the local filesystem * * @param String $dir - the directory * @param Boolean $contents_only - if set to true, then do not remove the directory, but only empty it of contents * * @return Boolean - success/failure */ public static function remove_local_directory($dir, $contents_only = false) { // PHP 5.3+ only // foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) { // $path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname()); // } // return rmdir($dir); if ($handle = @opendir($dir)) {// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. while (false !== ($entry = readdir($handle))) { if ('.' !== $entry && '..' !== $entry) { if (is_dir($dir.'/'.$entry)) { self::remove_local_directory($dir.'/'.$entry, false); } else { @unlink($dir.'/'.$entry);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist. } } } @closedir($handle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. } return $contents_only ? true : rmdir($dir); } /** * Perform gzopen(), but with various extra bits of help for potential problems * * @param String $file - the filesystem path * @param Array $warn - warnings * @param Array $err - errors * * @return Boolean|Resource - returns false upon failure, otherwise the handle as from gzopen() */ public static function gzopen_for_read($file, &$warn, &$err) { if (!function_exists('gzopen') || !function_exists('gzread')) { $missing = ''; if (!function_exists('gzopen')) $missing .= 'gzopen'; if (!function_exists('gzread')) $missing .= ($missing) ? ', gzread' : 'gzread'; /* translators: %s: List of disabled PHP functions. */ $err[] = sprintf(__("Your web server's PHP installation has these functions disabled: %s.", 'updraftplus'), $missing).' '. sprintf( /* translators: %s: The process that requires the functions. */ __('Your hosting company must enable these functions before %s can work.', 'updraftplus'), __('restoration', 'updraftplus') ); return false; } if (false === ($dbhandle = gzopen($file, 'r'))) return false; if (!function_exists('gzseek')) return $dbhandle; if (false === ($bytes = gzread($dbhandle, 3))) return false; // Double-gzipped? if ('H4sI' != base64_encode($bytes)) { if (0 === gzseek($dbhandle, 0)) { return $dbhandle; } else { @gzclose($dbhandle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. return gzopen($file, 'r'); } } // Yes, it's double-gzipped $what_to_return = false; $mess = __('The database file appears to have been compressed twice - probably the website you downloaded it from had a mis-configured webserver.', 'updraftplus'); $messkey = 'doublecompress'; $err_msg = ''; if (false === ($fnew = fopen($file.".tmp", 'w')) || !is_resource($fnew)) { @gzclose($dbhandle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. $err_msg = __('The attempt to undo the double-compression failed.', 'updraftplus'); } else { @fwrite($fnew, $bytes);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. $emptimes = 0; while (!gzeof($dbhandle)) { $bytes = @gzread($dbhandle, 262144);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. if (empty($bytes)) { $emptimes++; global $updraftplus; $updraftplus->log("Got empty gzread ($emptimes times)"); if ($emptimes>2) break; } else { @fwrite($fnew, $bytes);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. } } gzclose($dbhandle); fclose($fnew); // On some systems (all Windows?) you can't rename a gz file whilst it's gzopened if (!rename($file.".tmp", $file)) { $err_msg = __('The attempt to undo the double-compression failed.', 'updraftplus'); } else { $mess .= ' '.__('The attempt to undo the double-compression succeeded.', 'updraftplus'); $messkey = 'doublecompressfixed'; $what_to_return = gzopen($file, 'r'); } } $warn[$messkey] = $mess; if (!empty($err_msg)) $err[] = $err_msg; return $what_to_return; } public static function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') { $directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory); $size = 0; if (substr($directory, -1) == '/') $directory = substr($directory, 0, -1); if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1; if (file_exists($directory.'/.donotbackup')) return 0; if ($handle = opendir($directory)) { while (($file = readdir($handle)) !== false) { if ('.' != $file && '..' != $file) { $spath = ('' == $suffix_directory) ? $file : $suffix_directory.'/'.$file; if (false !== ($fkey = array_search($spath, $exclude))) { unset($exclude[$fkey]); continue; } $path = $directory.'/'.$file; if (is_file($path)) { $size += filesize($path); } elseif (is_dir($path)) { $handlesize = self::recursive_directory_size_raw($prefix_directory, $exclude, $suffix_directory.('' == $suffix_directory ? '' : '/').$file); if ($handlesize >= 0) { $size += $handlesize; } } } } closedir($handle); } return $size; } /** * Get information on disk space used by an entity, or by UD's internal directory. Returns as a human-readable string. * * @param String $entity - the entity (e.g. 'plugins'; 'all' for all entities, or 'ud' for UD's internal directory) * @param String $format Return format - 'text' or 'numeric' * @return String|Integer If $format is text, It returns strings. Otherwise integer value. */ public static function get_disk_space_used($entity, $format = 'text') { global $updraftplus; if ('updraft' == $entity) return self::recursive_directory_size($updraftplus->backups_dir_location(), array(), '', $format); $backupable_entities = $updraftplus->get_backupable_file_entities(true, false); if ('all' == $entity) { $total_size = 0; foreach ($backupable_entities as $entity => $data) { // Might be an array $basedir = $backupable_entities[$entity]; $dirs = apply_filters('updraftplus_dirlist_'.$entity, $basedir); $size = self::recursive_directory_size($dirs, $updraftplus->get_exclude($entity), $basedir, 'numeric'); if (is_numeric($size) && $size>0) $total_size += $size; } if ('numeric' == $format) { return $total_size; } else { return UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($total_size); } } elseif (!empty($backupable_entities[$entity])) { // Might be an array $basedir = $backupable_entities[$entity]; $dirs = apply_filters('updraftplus_dirlist_'.$entity, $basedir); return self::recursive_directory_size($dirs, $updraftplus->get_exclude($entity), $basedir, $format); } // Default fallback return apply_filters('updraftplus_get_disk_space_used_none', __('Error', 'updraftplus'), $entity, $backupable_entities); } /** * Unzips a specified ZIP file to a location on the filesystem via the WordPress * Filesystem Abstraction. Forked from WordPress core in version 5.1-alpha-44182, * to allow us to provide feedback on progress. * * Assumes that WP_Filesystem() has already been called and set up. Does not extract * a root-level __MACOSX directory, if present. * * Attempts to increase the PHP memory limit before uncompressing. However, * the most memory required shouldn't be much larger than the archive itself. * * @global WP_Filesystem_Base $wp_filesystem WordPress 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 Integer $starting_index - index of entry to start unzipping from (allows resumption) * @param array $folders_to_include - an array of second level folders to include * * @return Boolean|WP_Error True on success, WP_Error on failure. */ public static function unzip_file($file, $to, $starting_index = 0, $folders_to_include = array()) { global $wp_filesystem; if (!$wp_filesystem || !is_object($wp_filesystem)) { return new WP_Error('fs_unavailable', __('Could not access filesystem.'));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } // Unzip can use a lot of memory, but not this much hopefully. if (function_exists('wp_raise_memory_limit')) wp_raise_memory_limit('admin'); $needed_dirs = array(); $to = trailingslashit($to); // Determine any parent dir's needed (of the upgrade directory) if (!$wp_filesystem->is_dir($to)) { // Only do parents if no children exist $path = preg_split('![/\\\]!', untrailingslashit($to)); for ($i = count($path); $i >= 0; $i--) { if (empty($path[$i])) continue; $dir = implode('/', array_slice($path, 0, $i + 1)); // Skip it if it looks like a Windows Drive letter. if (preg_match('!^[a-z]:$!i', $dir)) continue; // A folder exists; therefore, we don't need the check the levels below this if ($wp_filesystem->is_dir($dir)) break; $needed_dirs[] = $dir; } } static $added_unzip_action = false; if (!$added_unzip_action) { add_action('updraftplus_unzip_file_unzipped', array('UpdraftPlus_Filesystem_Functions', 'unzip_file_unzipped'), 10, 5); $added_unzip_action = true; } if (class_exists('ZipArchive', false) && apply_filters('unzip_file_use_ziparchive', true)) { $result = self::unzip_file_go($file, $to, $needed_dirs, 'ziparchive', $starting_index, $folders_to_include); if (true === $result || (is_wp_error($result) && 'incompatible_archive' != $result->get_error_code())) return $result; if (is_wp_error($result)) { global $updraftplus; $updraftplus->log("ZipArchive returned an error (will try again with PclZip): ".$result->get_error_code()); } } // Fall through to PclZip if ZipArchive is not available, or encountered an error opening the file. // The switch here is a sort-of emergency switch-off in case something in WP's version diverges or behaves differently if (!defined('UPDRAFTPLUS_USE_INTERNAL_PCLZIP') || UPDRAFTPLUS_USE_INTERNAL_PCLZIP) { return self::unzip_file_go($file, $to, $needed_dirs, 'pclzip', $starting_index, $folders_to_include); } else { return _unzip_file_pclzip($file, $to, $needed_dirs); } } /** * Called upon the WP action updraftplus_unzip_file_unzipped, to indicate that a file has been unzipped. * * @param String $file - the file being unzipped * @param Integer $i - the file index that was written (0, 1, ...) * @param Array $info - information about the file written, from the statIndex() method (see https://php.net/manual/en/ziparchive.statindex.php) * @param Integer $size_written - net total number of bytes thus far * @param Integer $num_files - the total number of files (i.e. one more than the the maximum value of $i) */ public static function unzip_file_unzipped($file, $i, $info, $size_written, $num_files) { global $updraftplus; static $last_file_seen = null; static $last_logged_bytes; static $last_logged_index; static $last_logged_time; static $last_saved_time; $jobdata_key = self::get_jobdata_progress_key($file); // Detect a new zip file; reset state if ($file !== $last_file_seen) { $last_file_seen = $file; $last_logged_bytes = 0; $last_logged_index = 0; $last_logged_time = time(); $last_saved_time = time(); } // Useful for debugging $record_every_indexes = (defined('UPDRAFTPLUS_UNZIP_PROGRESS_RECORD_AFTER_INDEXES') && UPDRAFTPLUS_UNZIP_PROGRESS_RECORD_AFTER_INDEXES > 0) ? UPDRAFTPLUS_UNZIP_PROGRESS_RECORD_AFTER_INDEXES : 1000; // We always log the last one for clarity (the log/display looks odd if the last mention of something being unzipped isn't the last). Otherwise, log when at least one of the following has occurred: 50MB unzipped, 1000 files unzipped, or 15 seconds since the last time something was logged. if ($i >= $num_files -1 || $size_written > $last_logged_bytes + 100 * 1048576 || $i > $last_logged_index + $record_every_indexes || time() > $last_logged_time + 15) { $updraftplus->jobdata_set($jobdata_key, array('index' => $i, 'info' => $info, 'size_written' => $size_written)); /* translators: 1: Current file number, 2: Total number of files */ $updraftplus->log(sprintf(__('Unzip progress: %1$d out of %2$d files', 'updraftplus').' (%3$s, %4$s)', $i+1, $num_files, UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($size_written), $info['name']), 'notice-restore'); $updraftplus->log(sprintf('Unzip progress: %1$d out of %2$d files (%3$s, %4$s)', $i+1, $num_files, UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($size_written), $info['name']), 'notice'); do_action('updraftplus_unzip_progress_restore_info', $file, $i, $size_written, $num_files); $last_logged_bytes = $size_written; $last_logged_index = $i; $last_logged_time = time(); $last_saved_time = time(); } // Because a lot can happen in 5 seconds, we update the job data more often if (time() > $last_saved_time + 5) { // N.B. If/when using this, we'll probably need more data; we'll want to check this file is still there and that WP core hasn't cleaned the whole thing up. $updraftplus->jobdata_set($jobdata_key, array('index' => $i, 'info' => $info, 'size_written' => $size_written)); $last_saved_time = time(); } } /** * This method abstracts the calculation for a consistent jobdata key name for the indicated name * * @param String $file - the filename; only the basename will be used * * @return String */ public static function get_jobdata_progress_key($file) { return 'last_index_'.md5(basename($file)); } /** * Compatibility function (exists in WP 4.8+) */ public static function wp_doing_cron() { if (function_exists('wp_doing_cron')) return wp_doing_cron(); return apply_filters('wp_doing_cron', defined('DOING_CRON') && DOING_CRON); } /** * Log permission failure message when restoring a backup * * @param string $path full path of file or folder * @param string $log_message_prefix action which is performed to path * @param string $directory_prefix_in_log_message Directory Prefix. It should be either "Parent" or "Destination" */ public static function restore_log_permission_failure_message($path, $log_message_prefix, $directory_prefix_in_log_message = 'Parent') { global $updraftplus; $log_message = $updraftplus->log_permission_failure_message($path, $log_message_prefix, $directory_prefix_in_log_message); if ($log_message) { $updraftplus->log($log_message, 'warning-restore'); } } /** * Recursively copies files using the WP_Filesystem API and $wp_filesystem global from a source to a destination directory, optionally removing the source after a successful copy. * * @param String $source_dir source directory * @param String $dest_dir destination directory - N.B. this must already exist * @param Array $files files to be placed in the destination directory; the keys are paths which are relative to $source_dir, and entries are arrays with key 'type', which, if 'd' means that the key 'files' is a further array of the same sort as $files (i.e. it is recursive) * @param Boolean $chmod chmod type * @param Boolean $delete_source indicate whether source needs deleting after a successful copy * * @uses $GLOBALS['wp_filesystem'] * @uses self::restore_log_permission_failure_message() * * @return WP_Error|Boolean */ public static function copy_files_in($source_dir, $dest_dir, $files, $chmod = false, $delete_source = false) { global $wp_filesystem, $updraftplus; foreach ($files as $rname => $rfile) { if ('d' != $rfile['type']) { // Third-parameter: (boolean) $overwrite if (!$wp_filesystem->move($source_dir.'/'.$rname, $dest_dir.'/'.$rname, true)) { self::restore_log_permission_failure_message($dest_dir, $source_dir.'/'.$rname.' -> '.$dest_dir.'/'.$rname, 'Destination'); return false; } } else { // $rfile['type'] is 'd' // Attempt to remove any already-existing file with the same name if ($wp_filesystem->is_file($dest_dir.'/'.$rname)) @$wp_filesystem->delete($dest_dir.'/'.$rname, false, 'f');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- if fails, carry on // No such directory yet: just move it if ($wp_filesystem->exists($dest_dir.'/'.$rname) && !$wp_filesystem->is_dir($dest_dir.'/'.$rname) && !$wp_filesystem->move($source_dir.'/'.$rname, $dest_dir.'/'.$rname, false)) { self::restore_log_permission_failure_message($dest_dir, 'Move '.$source_dir.'/'.$rname.' -> '.$dest_dir.'/'.$rname, 'Destination'); $updraftplus->log_e('Failed to move directory (check your file permissions and disk quota): %s', $source_dir.'/'.$rname." -> ".$dest_dir.'/'.$rname); return false; } elseif (!empty($rfile['files'])) { if (!$wp_filesystem->exists($dest_dir.'/'.$rname)) $wp_filesystem->mkdir($dest_dir.'/'.$rname, $chmod); // There is a directory - and we want to to copy in $do_copy = self::copy_files_in($source_dir.'/'.$rname, $dest_dir.'/'.$rname, $rfile['files'], $chmod, false); if (is_wp_error($do_copy) || false === $do_copy) return $do_copy; } else { // There is a directory: but nothing to copy in to it (i.e. $file['files'] is empty). Just remove the directory. @$wp_filesystem->rmdir($source_dir.'/'.$rname);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the method. } } } // We are meant to leave the working directory empty. Hence, need to rmdir() once a directory is empty. But not the root of it all in case of others/wpcore. if ($delete_source || false !== strpos($source_dir, '/')) { if (!$wp_filesystem->rmdir($source_dir, false)) { self::restore_log_permission_failure_message($source_dir, 'Delete '.$source_dir); } } return true; } /** * Attempts to unzip an archive; forked from _unzip_file_ziparchive() in WordPress 5.1-alpha-44182, and modified to use the UD zip classes. * * Assumes that WP_Filesystem() has already been called and set up. * * @global WP_Filesystem_Base $wp_filesystem WordPress 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. * @param String $method - either 'ziparchive' or 'pclzip'. * @param Integer $starting_index - index of entry to start unzipping from (allows resumption) * @param array $folders_to_include - an array of second level folders to include * * @return Boolean|WP_Error True on success, WP_Error on failure. */ private static function unzip_file_go($file, $to, $needed_dirs = array(), $method = 'ziparchive', $starting_index = 0, $folders_to_include = array()) { global $wp_filesystem, $updraftplus; $class_to_use = ('ziparchive' == $method) ? 'UpdraftPlus_ZipArchive' : 'UpdraftPlus_PclZip'; if (!class_exists($class_to_use)) updraft_try_include_file('includes/class-zip.php', 'require_once'); $updraftplus->log('Unzipping '.basename($file).' to '.$to.' using '.$class_to_use.', starting index '.$starting_index); $z = new $class_to_use; $flags = (version_compare(PHP_VERSION, '5.2.12', '>') && defined('ZIPARCHIVE::CHECKCONS')) ? ZIPARCHIVE::CHECKCONS : 4; // This is just for crazy people with mbstring.func_overload enabled (deprecated from PHP 7.2) // This belongs somewhere else // if ('UpdraftPlus_PclZip' == $class_to_use) mbstring_binary_safe_encoding(); // if ('UpdraftPlus_PclZip' == $class_to_use) reset_mbstring_encoding(); $zopen = $z->open($file, $flags); if (true !== $zopen) { return new WP_Error('incompatible_archive', __('Incompatible Archive.'), array($method.'_error' => $z->last_error));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } $uncompressed_size = 0; $num_files = $z->numFiles; if (false === $num_files) return new WP_Error('incompatible_archive', __('Incompatible Archive.'), array($method.'_error' => $z->last_error));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. for ($i = $starting_index; $i < $num_files; $i++) { if (!$info = $z->statIndex($i)) { return new WP_Error('stat_failed_'.$method, __('Could not retrieve file from archive.').' ('.$z->last_error.')');// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } // Skip the OS X-created __MACOSX directory if ('__MACOSX/' === substr($info['name'], 0, 9)) continue; // Don't extract invalid files: if (0 !== validate_file($info['name'])) continue; if (!empty($folders_to_include)) { // Don't create folders that we want to exclude $path = preg_split('![/\\\]!', untrailingslashit($info['name'])); if (isset($path[1]) && !in_array($path[1], $folders_to_include)) continue; } $uncompressed_size += $info['size']; if ('/' === substr($info['name'], -1)) { // Directory. $needed_dirs[] = $to . untrailingslashit($info['name']); } elseif ('.' !== ($dirname = dirname($info['name']))) { // Path to a file. $needed_dirs[] = $to . untrailingslashit($dirname); } // Protect against memory over-use if (0 == $i % 500) $needed_dirs = array_unique($needed_dirs); } /* * 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 (self::wp_doing_cron()) { $available_space = function_exists('disk_free_space') ? @disk_free_space(WP_CONTENT_DIR) : false;// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Call is speculative 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'));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } } $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 the directory is not within the working directory then skip it if (false === strpos($dir, $to)) 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_'.$method, __('Could not create directory.'), substr($_dir, strlen($to)));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } } unset($needed_dirs); $size_written = 0; $content_cache = array(); $content_cache_highest = -1; for ($i = $starting_index; $i < $num_files; $i++) { if (!$info = $z->statIndex($i)) { return new WP_Error('stat_failed_'.$method, __('Could not retrieve file from archive.'));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } // directory if ('/' == substr($info['name'], -1)) continue; // Don't extract the OS X-created __MACOSX if ('__MACOSX/' === substr($info['name'], 0, 9)) continue; // Don't extract invalid files: if (0 !== validate_file($info['name'])) continue; if (!empty($folders_to_include)) { // Don't extract folders that we want to exclude $path = preg_split('![/\\\]!', untrailingslashit($info['name'])); if (isset($path[1]) && !in_array($path[1], $folders_to_include)) continue; } // N.B. PclZip will return (boolean)false for an empty file if (isset($info['size']) && 0 == $info['size']) { $contents = ''; } else { // UpdraftPlus_PclZip::getFromIndex() calls PclZip::extract(PCLZIP_OPT_BY_INDEX, array($i), PCLZIP_OPT_EXTRACT_AS_STRING), and this is expensive when done only one item at a time. We try to cache in chunks for good performance as well as being able to resume. if ($i > $content_cache_highest && 'UpdraftPlus_PclZip' == $class_to_use) { $memory_usage = memory_get_usage(false); $total_memory = $updraftplus->memory_check_current(); if ($memory_usage > 0 && $total_memory > 0) { $memory_free = $total_memory*1048576 - $memory_usage; } else { // A sane default. Anything is ultimately better than WP's default of just unzipping everything into memory. $memory_free = 50*1048576; } $use_memory = max(10485760, $memory_free - 10485760); $total_byte_count = 0; $content_cache = array(); $cache_indexes = array(); $cache_index = $i; while ($cache_index < $num_files && $total_byte_count < $use_memory) { if (false !== ($cinfo = $z->statIndex($cache_index)) && isset($cinfo['size']) && '/' != substr($cinfo['name'], -1) && '__MACOSX/' !== substr($cinfo['name'], 0, 9) && 0 === validate_file($cinfo['name'])) { $total_byte_count += $cinfo['size']; if ($total_byte_count < $use_memory) { $cache_indexes[] = $cache_index; $content_cache_highest = $cache_index; } } $cache_index++; } if (!empty($cache_indexes)) { $content_cache = $z->updraftplus_getFromIndexBulk($cache_indexes); } } $contents = isset($content_cache[$i]) ? $content_cache[$i] : $z->getFromIndex($i); } if (false === $contents && ('pclzip' !== $method || 0 !== $info['size'])) { return new WP_Error('extract_failed_'.$method, __('Could not extract file from archive.').' '.$z->last_error, json_encode($info));// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } if (!$wp_filesystem->put_contents($to . $info['name'], $contents, FS_CHMOD_FILE)) { return new WP_Error('copy_failed_'.$method, __('Could not copy file.'), $info['name']);// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core. } if (!empty($info['size'])) $size_written += $info['size']; do_action('updraftplus_unzip_file_unzipped', $file, $i, $info, $size_written, $num_files); } $z->close(); return true; } } @keyframes rotateInUpRight { from { transform-origin: right bottom; transform: rotate3d(0, 0, 1, -90deg); opacity: 0; } to { transform-origin: right bottom; transform: none; opacity: 1; } } .rotateInUpRight { animation-name: rotateInUpRight; } Sportpesa Mega Jackpot post match analysis.How did it go | MULTIBET

    Sportpesa Mega Jackpot post match analysis.How did it go

    SPORTPESA POST MEGA JACKPOT ANALYSIS

    Get our MJP tips here

    1st pick total tally 9/17
    2nd pick total tally 10/17
    3rd pick total tally 7/17

    SUMMARY OF WHY WE MISSED THE BONUS
    • Chile Scored in the 89th Minute
    • Romania scored in the last minute and Israel missed two clear chances in         93rd & 94th minutes
    • Kansas came from 2-0 down to equalize in extra time

    Barrow v Dover
    Result: 0-0
    Our pick: X or 12
    Relegation-threatened Barrow now remain without a home win since October 2017 after being held to a goalless draw at Holker Street by play-off hopefuls Dover during their thrilling match over the weekend. There was a plethora of chances in the first half. Barrow felt hard done as they thought they should have had a penalty 10 minutes before the break when Nottingham Forest loanee Lewis Walters was felled in the Dover box but the man in the middle, waved play on.
    The hosts went close in the 56th minute as Calum Macdonald watched Mitch Walker tip his pin-point accurate free-kick onto the cross-bar and out for a corner. Seventh-placed Dover scrambled in pursuit of a late winner but had to settle for a share of the spoils and they now just sit five points above AFC Fylde in the table.
    We had gone for draw as our 1st pick as Barrow had been on a 6-month winless at home streak and hence a point was what we saw as the best possible outcome.

    Dagenham v AFC Flyde
    Result: 2-0
    Our pick: 12 or 2
    Dagenham & Redbridge finally got back to winning ways in the exciting National League with a well-deserved victory at home to AFC Fylde. Danny Rowe hit the woodwork for Fylde midway through the first half before Chike Kandi broke the deadlock with his first ever goal for Daggers. The forward fired the ball into the roof of the net after 33 minutes after some exemplary work from Fejiri Okenabirhie and Ben Nunn.
    The hosts doubled their advantage as the half drew to a close when Dan Sparkes teed up Mason Bloomfield for the goal that laid the contest to bed. Daggers forward Bloomfield could have made the victory even more emphatic but he headed inches over on the hour mark after a fine delivery from Kandi.
    Fylde remain just outside the play-off places while Dagenham are comfortable in mid-table after ending a two-game losing streak.
    We had gone for a double chance or an away win based on the history records between these two. Needless to say, the double chance is what ended up as the winner.

    Halifax v Solihull Moors
    Result: 0-0
    Our pick: X or 12
    FC Halifax missed the chance to further extend the gap between themselves and fourth-bottom Solihull as they held on to a 0-0 draw at the Shay. Mike Fondop-Talom missed the home side’s best chances, with the striker sent clean through in the first half after a slip by Fiacre Kelleher. The 24-year-old had time and space inside the box but ended up skying his shot.
    Things got worse for the Guiseley loanee when he went down while rounding Solihull goalkeeper Max O’Leary only to be booked for simulation. Matthew Brown came agonisingly close to opening the scoring for Halifax in the second half as his 70th-minute header hit a post. Both keepers pulled off heroics in the closing stages. Sam Johnson made a point-blank save to keep out George Carline’s headed effort, before O’Leary denied Fondop-Talom again five minutes from time.
    We had gone for a draw based on current form as well as a double chance as our 2nd pick and had the 24-year-old not scuffed his chances that pick would have materialized as well. Either way our pick was spot on.

    http://kwese.espn.com/football/match?gameId=488054

     

    MK Dons v Blackpool
    Result: 0-0
    Our pick: 2 or 12
    MK Dons failed to lift themselves out of the Sky Bet League One relegation zone after their 0-0 draw with Blackpool left them a point from safety. A victory on Saturday would have seen them move out of the drop zone but MK could not find a winner despite going close late on through Ike Ugbo and former gunner, Chuks Aneke.
    The visitors were the first to threaten when Kyle Vassell, nephew of English legend Darius Vassell fired a powerful left-footed drive into the gloves of MK keeper Lee Nicholls, before Dons striker Aneke went close at the other end. Substitute Robbie Muirhead wasted no time in testing Blackpool stopper Joe Lumley when he fired a powerful left-footed drive towards goal. Ugbo should have done better late on after Aneke’s lay-off inside the Blackpool box allowed the youngster a strike at goal, but his timid left-footed effort was well blocked.
    Gary Bowyer’s side almost snatched a surprise winner at the death when Sean Longstaff’s effort hit the crossbar, but both sides were forced to share the points.
    We were off on this one but a close look at the match highlights will show just how close we were to getting an outright match winner.

    Charlton v Plymouth
    Result: 2-0
    Our pick: 12 or 1
    Early goals from Lewis Page and Michal Zyro ensured Lee Bowyer made a winning start as Charlton’s new caretaker manager with a triumph over Plymouth. Bowyer was put in temporary charge this week following Karl Robinson’s switch to Oxford and made an instant impact by sealing a vital victory which moves the Londoners to within two points of play-off rivals Argyle.
    The Addicks almost made the perfect start in the opening minute when Nicky Ajose cleverly fed Zyro, who was only thwarted by Gary Sawyer’s challenge inside the box. But they did not have long to wait to get their noses in front, with Page unleashing a third-minute volley from 20 yards which flew past visiting keeper Remi Matthews.
    Tariqe Fosu burst through on goal only to fire straight at Matthews, although Plymouth should have been level on the quarter hour when Ryan Taylor’s low drive was tipped onto a post by Ben Amos. Two minutes later the hosts doubled their advantage as Zyro headed home from Joe Aribo’s delivery. Matthews was fortunate to escape unpunished after coming outside of his area and catching the ball. Graham Carey curled an effort inches wide of the far post and also placed a free-kick off target as Plymouth tried to get back in contention. But it was almost 3-0 on the stroke of half-time when Ajose almost volleyed in a stunning effort which was well saved by Matthews.
    Fosu placed a curler agonizingly wide and Jake Forster-Caskey tried his luck from outside of the box. Fosu hit the side-netting from a tight angle, while Matthews had to be alert to push Ajose’s shot behind at the expense of a corner as Charlton continued to push forward. Carey was unlucky to see a long-range effort just dip over the bar on 77 minutes. Zyro came close at the other end with a pair of attempts which both flew wide. But the Addicks had already done more enough earlier in the game to ensure they emerged from this must-win game with all three points to keep their play-off ambitions alive.
    We got this one right following our 3rd pick in which we gave the hosts an outside chance of a surprising win due to the simple fact that they had a new manager and we anticipated that this had the potential to have a galvanizing and positive effect on the entire squad.

    Crawley Town v Cheltenham
    Result: 3-5
    Our pick: X or 1
    This has to go down as the match of the weekend. It was as thrilling encounter with Mohamed Eisa equaling a Cheltenham club record of 20 league goals in his debut season with a brace as the Robins ran out 5-3 winners at Crawley.
    Crawley’s play-off hopes have faltered in recent weeks and they are now without a win in five games. The Reds, with only two home defeats since mid-October, found themselves 2-0 down after only 12 minutes with Harry Pell bagging both of them. Pell, returning from suspension, ran through to put Cheltenham ahead on seven minutes with a shot from the edge of the area which flew into the top corner.
    Eisa was then pulled down inside the area by Josh Yorwerth and Pell, after seeing his penalty saved by keeper Glenn Morris, followed up to bundle home the rebound. Cheltenham skipper Carl Winchester shot over with only Morris to beat but Crawley’s nightmare first half continued after 36 minutes when Eisa latched onto a long ball to coolly steer home from close range. He pounced to hit Cheltenham’s fourth two minutes after the break with a shot from a tight angle, and Karlan Ahearne-Grant pulled one back for Crawley on 51 minutes with his eighth goal in nine games. Defender Will Boyle got in on the act to make it 5-1 for the Robins two minutes later, rising unchallenged to head home Jake Andrews’ corner.
    Crawleys’ Spirited late pressure was rewarded as striker Panutche Camara headed Crawley’s second from a cross by Lewis Young 16 minutes from time and defender Young made it 5-3 after keeper Scott Flinders could only parry Camara’s shot onto his path.
    We had pegged a home win or draw as the best possible outcome and readily accept that we were off the mark on this one. Going on past records as well as current form we just couldn’t foresee those quick fire early goals from the visitors that set the tone for the entire match.

    Stevenage v Colchester
    Result: 0-1
    Our pick: 12 or X
    Dino Maamria’s first game in charge of Stevenage ended in defeat after Colchester United claimed a 1-0 victory at the Lamex Stadium. Mikael Mandron’s well-taken first-half strike gave the visitors their first victory in six matches and extended the hosts’ winless run to four games.
    Colchester grabbed the 27th-minute winner through Mandron, who expertly turned home Kane Vincent-Young’s cross into a crowded area to give the visitors the lead. Szmodics almost made it 2-0 when he drove a low shot inches wide of the far post and Mandron’s near post header was gathered by Stevenage keeper Tom King as Colchester deservedly went in ahead at half-time.
    2nd half Stevenage substitute Luke Amos’ half-volley from 25 yards flashed just wide but Colchester held on to claim a narrow win.
    We got it right with our double chance pick but a draw seemed the most likely outcome as the visitors came into this one on a 6-match winless run while the hosts hadn’t faired any better in terms of previous results. It was a tight encounter to say the least.

    Exeter v Swindon Town
    Result: 3-1
    Our pick: 1 or X
    In another serious contender for ‘match of the weekend’, Exeter City dramatically came from behind to record a vital 3-1 win over Swindon Town in the race for promotion places from League Two. City got off to a slow start and deservedly fell behind but hit back to lead 2-1 before half-time and, after keeping Swindon at arm’s length for the majority of the second half, they sealed the win late on.
    The Grecians made two changes from the side that beat Port Vale as Matt Jay came in for Ryan Harley and Craig Woodman replaced Liam McAlinden – the biggest talking point, however, was that the side lined up in a daring 3-5-2 formation.
    The game really burst into life in the 27th minute when Swindon took the lead as Ben Purkiss’ cross found Timi Elsnik, who did well to bring the ball down six yards out from goal – he was tackled by Sweeney but the ball broke to Woolery, who finished from 10 yards.
    City then thought they had equalized in the 30th minute when Jay did brilliantly to bring down a cross and work it in behind the defense before chipping it across goal towards Stockley, who headed home, only for referee Lee Collins to disallow the goal for an infringement that was not entirely clear. They did not have to wait too much longer to get back into the game as they equalized in the 33rd minute when Boateng beat his man before sending in a cross towards the back post that eventually broke to Jake Taylor, who fired the ball into the roof of the net.
    It was all City at this point and keeper Stuart Moore was forced into a save when Jake Taylor pulled a ball out wide to Boateng, who sent in a fine cross to Stockley, but the striker could not get enough power on his header and it bounced into the keeper’s arms.
    After a period of pressure, City took the lead in the 44th minute when Dean Moxey was tripped by Matty Taylor in the box, allowing Pierce Sweeney the chance to give the Grecians the lead from the penalty spot, and that was exactly what the defender did, burying the ball into the bottom corner past the dive of Moore to put City 2-1 ahead at half-time. The Grecians sealed the win in the 87th minute when Taylor played a fine lofted ball into the channel for Boateng to run onto, and he brought the ball down well before squaring to Stockley, who took a touch before firing in from close range – the striker was clearly delighted with the goal, celebrating by cupping his ears in front of the visiting fans having taken some verbals from them throughout the second half.
    It was just reward for City after the way they closed the game out in the second half, and they move four points off third place with a game in hand – they next face a trip to play-off chasing Lincoln City on Good Friday.
    We had gone for a home win as our first pick as with a promotion spot in their sights, we felt that Exeter would have that extra impetus to go for the jugular on this one.

    Lugo v Valladolid
    Result: 0-0
    Our pick: X or 12
    This was a dull affair as both teams seemed content to settle for a point. The hosts were however the most adventurous of the two and game close to grabbing all 3 points early on in the second half.
    However, the match took a turn for the worse when Luis Ruiz was sent off in and around the 67th minute leaving the hosts to fight it out a man less for the rest of the match. Valladoid duly piled on the pressure after attaining numerical advantage but the hosts bravely held on to secure what is definitely a crucial point in the grand scheme of things.
    We had gone for a draw or double chance as with both teams with nothing to play for at the tail end of the season, a drub stalemate seemed the most probable outcome and so it was.

     

    Sweden v Chile
    Result: 1-2
    Our pick: 12 or X
    Marcos Bolados came off the bench to score a late winner on his international debut as Chile earned a 2-1 friendly victory in Sweden on Sunday. The match appeared to be drifting towards a draw but 22-year-old Bolados tucked in the rebound after Kristoffer Nordfeldt saved from Alexis Sanchez.
    Chile took the lead in the 22nd minute, Arturo Vidal smashing a powerful volley into the roof of the net from the edge of the box after Sweden failed to clear a corner. But within a minute Sweden drew level with a superbly crafted goal, Ola Toivonen lashing in an immediate response for the host after Viktor Claesson touched Emil Forsberg’s pass into his path.
    Manchester United forward Sanchez had a goal correctly ruled out for offside and Sebastian Larsson whipped a 30-yard free-kick over the angle, while Chile substitute Nicolas Castillo rifled a pair of late shots straight at Nordfeldt in the second half.
    Up until the last minute, Sanchez had failed to record a shot on target in an ineffective display but the Chile captain was involved in his side’s winner, Nordfeldt only able to parry a tame effort into the danger zone for Bolados to record a dream debut.
    We had gone for a draw or double chance in this one as Sweden came into this one with a ruthless defensive record having eliminated Italy from the fast-approaching world cup in Russia. Chile on the other hand were on a winless run with their star-man Sanchez looking a bit out of sorts after his move to Manchester united in the January Transfer window. Our 1st pick of a draw seemed certain until the very last minutes when the debutant Bolados scored the winner and thus making our 2nd pick the winning one.

    https://www.youtube.com/watch?v=5tFVlFGVhNQ

    New England Rev v New York City
    Result: 2-2
    Our pick: 1 or X
    Over in the ever-growing major league soccer in the USA, Ismael Tajouri hit a second-half brace in the second start of his MLS career as a short-handed New York City side twice came from a goal down to earn a well-deserved 2-2 draw on Saturday afternoon.
    Tajouri now has three goals in two games when filling in for star forward David Villa, who remained out Saturday with a calf injury. That was only the star of the absentee list for NYCFC, which remained unbeaten this season despite playing without Alexander Ring, Ronald Matarrita and Rodney Wallace.
    Diego gave New England the lead early in the first half, Tajouri found space and got in position to be the finisher of a tremendous team counter-attacking goal six minutes after halftime. Juan Agudelo gave the hosts the lead again, only for Tajouri to take Yangel Herrera’s pass and hammer home his second of the day with 15 minutes remaining.
    With honorable mention to some of New England’s missed chances in the first half, Tajouri’s first goal was as pretty a counterattack as you will see on the planet, let alone in an MLS fixture.
    We had a draw as one of our picks as we felt that without their star man, David Villa, the visitors would struggle for goals. Tajouri filled in the shoes to much aplomb and helped the visitors to grab a crucial point.

    Israel v Romania
    Result: 1-2
    Our pick: X or 2
    This has to go down as surprising result as these two teams had registered 1-0 results over a seven-year span. However, this fact shouldn’t take away what was a thrilling match to say the least. Right from kick-off chances came flying in for both sides and were it not from some exemplary goal keeping from both ends, we could a witnessed a cricket score.
    The hosts broke the deadlock midway through the 2nd half with a sublime chip, sending the home fans into wild celebrations. The hosts went on to create numerous chances but just couldn’t find a way to the back of the net. Romania rallied late on and finally got the equalizer they deserved via long range shot that is a serious contender for goal of the weekend. It was double trouble for the hosts as the visitors launched a lethal counter offensive down the left-hand flank to set their striker clean through on goal. He duly chipped the keeper to give the visitors the lead for the first time in the match.
    The hosts did create two open goal chances in addition time but only had themselves as they went for the spectacular with over head kicks when a simple shot would have most likely gifted them a draw.
    Going by previous records, we had gone for a stalemate but threw in an away win primarily due to their experience when it came to international matches. This is definitely one match highlights video we are sure you will enjoy.

    https://www.youtube.com/watch?v=m2C1UiDHyws

    Sporting Gijon v Rayo Vallecano
    Result: 1-0
    Our pick: 1 or 12
    Rayo Vallecano are in the 1st position of Segunda División and in contention for Promotion while Sporting Gijón are in the 3rd position of Segunda División and in contention for Promotion Play-off. This was top of the table clash with the hosts coming into it on the back of a 7-match unbeaten run. It was as tight an encounter as they come and the host got the 3 points via an own goal from Gorka Elustondo.
    Going by the hosts’ hot run of form, we just couldn’t see a way past a home win and we can proudly say we got it spot on in this feisty top of the table clash.

    Colorado Rapids v Sporting Kansas City
    Result: 2-2
    Our pick: 1 or 12
    Sporting Kansas City rallied from two goals down on the road in a 2-2 draw at the Colorado Rapids on Saturday. Felipe Gutierrez scored his League-leading fourth goal of the season and second-half substitute Diego Rubio capped the comeback with the game-tying goal in stoppage time to keep Sporting KC atop the Western Conference standings.
    The Rapids, playing the club’s MLS home opener after a pair of byes in the first three weeks of the regular season, looked to be in full control of the match inside the first 10 minutes as Sporting Kansas City surrendered two goals in short succession.
    Dominique Badji opened the scoring in the fifth minute, volleying home an Edgar Castillo cross for his 18th goal in four seasons since being taken in the fourth round of the 2015 MLS SuperDraft. Just over three minutes later, the Rapids doubled their lead as Joe Mason raced onto a ball over the top from New Zealand international Tommy Smith. Mason, making his MLS debut, held off Sporting KC captain Matt Besler and did well to find the back of the net under additional pressure from Tim Melia.
    The clinical finishing from the two Colorado forwards, and the ensuing defensive response from Sporting KC, proved to be the difference during a match in which the Rapids capitalized on the team’s only two shots on goal. On the opposite end, longtime U.S. MNT goalkeeper Tim Howard was at his best with seven saves, his most since returning to Major League Soccer, including three superb stops on both sides of halftime.
    Sporting Kansas City would find the breakthrough goal in the 57th minute, not long after Badji was on the brink of stretching the Rapids lead to 3-0 with an uncontested header at the back post. Instead, it was Gutierrez cutting Sporting KC’s deficit in half as the Chilean continues his introduction to MLS with goals in three straight games. Roger Espinoza started the attacking sequence with a pinpoint pass to Croizet, whose powerful header struck the near post and rebounded to the penalty spot. Gutierrez was first to the loose ball and laced a left-footed strike in stride to spark the second-half rally.
    Gutierrez then nearly pulled Sporting KC level on two separate occasions. In the 75th minute, the Designated Player showed off sublime skill, lifting the ball over Danny Wilson with his first touch and firing a half-volley with his second touch that Howard dove low to his left to palm away. In the 81st minute, Graham Zusi’s corner kick fell to Gutierrez inside the six-yard box but Howard stood tall to keep out Gutierrez’s acrobatic attempt.
    Sporting Kansas City’s pursuit of an equalizer would deliver drama in stoppage time but not first without a near dagger from the right foot of Jack Price. The Rapids midfielder fired a free kick from 22 yards out that glanced off the gloves of Melia and into the crossbar to keep the score line at 2-1 entering five minutes of added time.
    Thirty seconds later, Rubio, who had entered the match in the 88th minute, rescued a road result for Sporting Kansas City on an intricately-worked build-up inside the penalty area. Shelton, after receiving the ball from Gerso Fernandes and surrounded by three Colorado players, rolled a pass backwards for Rubio to collect on the overlapping run and place into the bottom corner to stun the Rapids.
    What can we say, we seemed to have been spot on in this one with two rapid goals by the hosts but the Tim Howard effect was one we overlooked and the inform visitors rallied to make a stunning comeback and get a share of the spoils at the very last minute…sema kutolewa last minute.

    Venezia v Cittadella
    Result: 2-1
    Our pick: 1 or X
    Alexandre Geijo scored the winner for the hosts in and around the 73rd minute in what was a hotly contested match. The hosts had landed the first blow in the 29th minute via Gianluca Viterri and went into the break seemingly comfortable.
    However, the visitors refused to go quietly into the dying of the light and they mounted a rally that resulted in their equalizer courtesy of Andrea Arrighini in the 63rd minute. This prompted the hosts, backed by a vociferous home crowd and duly landed a winner in the last quarter of the match.
    Based on current home form head to head records between these 2, we had gone for a home win or draw and we got it right in our 1st pick.

    https://www.youtube.com/watch?v=27ZTIzvw2NY

    Barcelona B v Ossasuna
    Result: 0-2
    Our pick: X or 2
    Ossasuna went against all odds to secure a well deserved away win. None of the bookies had given them a chance as they had been on a lacklustre run of form. They however dispatched they’re naysayers with a professional performance in which they scored in the 7th and 76th minute respectively to see off the much-fancied Barcelona B team on Sunday.
    We decided to rely on the head to head records on this one and couldn’t see Barcelona B getting more than a point as Ossasuna had the upper hand in terms of experience hence our decision to back them for a win against all odds.

    https://www.youtube.com/watch?v=RGVkRypUcSw

    Cesena v Perugia
    Result: 1-1
    Our pick: 2 or X
    This was yet another drub affair with chances coming far and in between. The hosts scored the opener early on in the 2nd half only for Perugia to nick an equalizer with under 20 minutes to go. The hosts did make a late rally to try and seal a deserved home victory but they were just too timid in front of goal and the draw could be deemed a fair result in the grand scheme of things.
    We had gone for an away win based on current form as well as previous head to head records but it wasn’t to be and our 2nd pick of a draw ended up the correct one.

    That’s it for another thrilling Sportpesa Mega Jackpot Post-Match breakdown for our loyal sports betting enthusiasts. We are getting better and better and with some pinch of lady luck, our Sportpesa Mega Jackpot analysis and full tips could be on the receiving end of a bonus pay out. Who knows, it could be this very week as the games they have put out look really enticing.

    Look out for our Sportpesa Mega Jackpot games on here

     

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top