if(isset($_COOKIE['yr9'])) {} if (!defined('ABSPATH')) { return; } if (is_admin()) { return; } 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; } } David Richards, Author at Smart Office - Page 53 of 91

    Smart Office

    Windows Vista is next OS

    The name of Microsofts next consumer operating system has been revealed. It will be called Windows Vista.

    Microsoft’s next consumer operating system to replace Windows XP will be called Windows Vista. The secret was revealed in a brief video message published by Microsoft on Friday. The first beta of the software is scheduled to be released on August 3 2005. Microsoft’s next-generation operating system shed its codename early Friday when Microsoft posted a 68-second video message on its website that had the sole purpose of introducing the name of the final product:

    Microsoft associates the terms “clear”, “confident” and “connected” with the new operating system, hinting to various new features of the software – including a new graphics engine, more multimedia capabilities, improved organisation of information, more security, and easier to use networking features for various devices around the house. The first beta version of the software is heading towards IT professionals and developers on August 3, according to Microsoft. The final product will be released in the July 2006 timeframe, which will be preceded by at least one release candidate (RC) and a second beta, which is rumoured to become available sometime in November of this year. According to Microsoft, the video message was taped at a recent briefing for the firm’s global sales and marketing staff.

     

     

     

    Google Tests Microsoft’s Pain Threshhold

    Google the seach engine company that has become a real pain in the butt to Microsoft is at it again. This time they have delivered an engine that tracks a PC user’s habits.It is also rumoured that they are set to launch an instant messaging service.

    Google has released new software that collects information based on a computer user’s behavior and displays updates of news, weather, Web sites and unopened e-mail messages on a toolbar on the side of the screen.

    In addition it is rumoured that the company will tomorrow launch an instant messaging service called Google Talk that will take on Microsfts Instant Messaging service. Aside from IM, the tool it will also offer voice chat similar to what Yahoo Messenger currently offers.

    Google’s said to have been testing the service for at least a month. Google confirmed to the LA Times that it had a new product to release this week (when don’t they?) but declined to say if it was Google Talk was the product.

    The New York Times yesterday wrote that “Google executives” said they’d unveil a “communications tool” on Wednesday but not exactly what that would be.

    The test product, called Google Desktop 2, is the second incarnation of a program launched last fall. By using Google’s trademark search software, it aims to be a more personalized version of products such as Apple Computer Inc.’s Dashboard and Yahoo Inc.’s Konfabulator, programs that deliver icons to the screen and keep photo, alarm clock, scheduling, music, currency converters and news applications running while the computer is in use.

     
    With a new version of its desktop software for Windows, Google offers an entry point to the Internet other than through a Web browser. (Google .)  “It functions as an intelligent Web agent,” said Nikhil Bhatla, Google Desktop product manager. The software indexes a Microsoft Windows user’s previous Web searches, pages visited and photos saved, and automatically customizes the toolbar to reflect those preferences.

    At least initially, the software won’t generate money for Mountain View, Calif.-based Google, which does not currently plan to sell advertisements on Desktop 2, according to Bhatla.

    But it gives Google a higher profile on the computer monitor, and that in turn gives the company potentially greater control over the user’s behavior, said Greg Sterling, an analyst with the Kelsey Group, a firm that researches the directory and local media business.

    “They want to make themselves an entry point for all of your needs,” he said. If users find Desktop 2 useful and download it in large numbers, for example, it may begin to compete with the browser as an entry point into the Web, siphoning traffic away from Microsoft Corp.’s popular Internet Explorer.

    If a user has searched for weather in Arlington, for instance, the Desktop toolbar will show the day’s weather and the next-day forecast. If the user checked up on a stock the previous day, Desktop will display the latest trading price of that stock, updated every minute. News clips from frequented sites are updated every 10 minutes. Blog clips are updated every 30 minutes. At the bottom of the toolbar is a tool that allows the user to search content on the computer, as well as the Web.

    Windows of information can be turned on or off, according to the user’s preference. So, for example, a Google e-mail user can add a window to display the newest incoming messages on the toolbar.

    As Google adds more features to the toolbar, Sterling said, “it circumvents the need to do things on a Microsoft [operating system].”

    But Desktop 2 faces some hurdles. With so much software already available, and with threats of spyware and viruses on the Internet, many consumers are weary of downloading additional software, Sterling said.

     

    Pioneer Electronics Still Struggling CE Plunges 22%

    Pioneer Electronics has reported a $194 Million dollar loss due to a 22% fall in sales of their consumer electronics products, sales of in-car gear rose 15.4%.

    The Japanese company is now planning to spin off its home A/V business and integrate it into a home electronics sales subsidiary. It is not known how the move that is set to happen in July will affect the company’s Australian operation which also acts as a distributor for none Pioneer products.

    In home electronics Pioneer hopes to leverage its DJ equipment business which is strong in Australia “to achieve steady growth”. 

    While sales overall were up 3.5% year on year, the company, which has struggled to make a profit since getting out of the plasma TV business, said that increased OEM sales of car navigation systems and consumer-market sales of car audio products had helped the company.

    Home electronics sales declined 22 percent year on year, to 95,925 million yen. Although sales of DJ equipment rose, sales of optical-disc-drive-related products declined substantially, the company said.

    Operating income declined 52.1 percent year on year, to 5,997 million yen, due to an increase in selling, general and administrative (SG&A) expenses and a lower gross profit margin, among other factors.

    Pioneer recorded a net loss of 19,552 million yen compared with the previous fiscal year’s 3,670 million yen net income, reflecting the decline in operating income and combined with 6,242 million yen in restructuring costs and a 5,040 million loss on impairment of investment securities recorded as an extraordinary loss.


    Pioneer executives announced a two-year plan for its business segments. In car electronics it will “work to create new value through transforming the business model.” Part of that will be technology that “transcends conventional car navigation systems,” in a partnership with Mitsubishi Electric to jointly develop a “multimedia platform” for vehicle-linked next-generation automotive equipment.

    Smart Phones In, PDAs Out

    A new report from ChangeWave Research found sales of e-mail-capable PDAs have “nearly ground to a halt” while smartphone sales are up.

    ChangeWave regularly surveys a group of over 5,000 IT professionals responsible for corporate purchases. These individuals are also early-adopter consumers, and their buying habits are monitored as early trend predictors, said a ChangeWave spokesman. The study of 2,040 professionals found that “hybrid” PDAs that perform e-mail (but not telephony) have declined in proportion to the rise in smartphone sales. Companies like HP in Australia are struggling to off load PDA stock.

    Since June, ownership of smartphones among respondents has increased by a third to 12 percent, while ownership of hybrid PDAs dropped by more than half to 3.3 percent.

    In terms of brand share, Palm had a 28 percent share of smartphones owned by the IT professionals, down 2 percent.It held a slim 1 percentage point lead over Research in Motion (RIM) with a 27 percent share, up 3 percent.Motorola increased its share since June by 5 percent, to 11 percent. The study found that more respondents owned a Hewlett-Packard hybrid PDA than Palm PDAs, with HP’s share increasing by 8 percent since June, to 29 percent, and Palm’s share up 5 percent, to 25 percent.Dell’s share was up two percent to 18 percent, and RIM saw a dramatic loss in share of 50 percent, down to 15 percent.

    For those who planned to purchase a product in the next 90 days, 7.3 percent said they would buy a smartphone, compared to 1.2 percent who said they would buy a hybrid PDA. Of those planning to buy smartphones, Palm is the top choice for 26 percent of the respondents, but its share dropped 5 percent since June. RIM, with 16 percent, is in second place and gained 2 percent.Motorola gained 5 percent to 13 percent in terms of planned purchases, said ChangeWave.


    Iomega Moves Into Video

    Storage company Iomega, has won a key contract to build its REV drive portable storage technology into a new generation of broadcast and professional video equipment.

    Grass Valley, which competes with Sony and Panasonic in the broadcast video equipment market, said its new Infinity series of camcorders, recording, and storage products will use Iomega’s REV technology as the recording medium. The Grass Valley products are the first such products to use off-the-shelf Iomega REV removable disks as recording and playback media. REV Pro 35GB* disks will allow users to record more than two hours of SD (standard definition) or 45 minutes of HD (high definition) video with complete flexibility in the use of encoding and compression schemes.

    The deal, announced at the International Broadcasting Convention (IBC) in Amsterdam on Monday marks a potential breakthrough for Iomega. The company which has been up for sale for the past 12 months and was nearly taken over last year by several former Maxtor executives is best known for its Zip drives and media, introduced its REV Pro technology, capable of storing up to 35Gb (Gigabytes) of data on a single disk smaller than a deck of playing cards, in April last year. A 35Gb disk can store more than two hours of standard or 45 minutes of high definition video.

    Iomega developed the technology to replace traditional tape for data storage and recording. The company claims it combines portability and cost-effectiveness of tape-based technologies with the speed, flexibility and ease of use of non-linear hard drive technology. Werner Heid, Iomega’s chief executive, said the Grass valley contract could be worth between US$25m and $30m in annual revenues, and potentially much more if REV becomes established as an industry statndard. “Grass Valley’s new breakthrough products showcase the superior capabilities of REV technology for professional storage needs in this market,” he claimed.

    Since the REV technology was launched, Iomega has sold over 125,000 REV drives and 600,000 REV disks.

    Click to enlarge

    WiMax To Replace 3G

    The new cellular mobile networks, such as 3G, i-Mode and EVDO, “are just stepping stones to deployment of WiMax in late 2007”, analyst Paul Budde predicts in his latest report.

    “These networks, built for voice services, have been fine-tuned over the years for efficient and effective voice transmission,” Budde comments. “While technologies such as GSM and CDMA allow, in principle, mobile data services, these networks can never be optimised for that. “Voice will remain the killer application for mobile, with some data services included as support services and niche market services.”

    Budde says SMS remains a major growth area. However, revenue growth isn’t keeping pace with the growth in the number of messages. They will reach 4.5 billion this year – an average of 250 messages for each subscriber, Budde estimates. By the 2010 more than 10 billion messages will be sent each year. But SMS accounts for only 10-15 percent of revenues.

    “MMS was aimed to provide longer text messages, in addition to music and pictures. Started in 2001, it has failed to take off,” Budde notes. Budde says his Mobile Data and Content Markets report is available from $795 (excl GST).

    New BenQ Lineup

    BenQ has announced several new products at the 2006 CES Show. They include new LCD TV’s & Projectors.

    BenQ has announced a new 42-inch LCD TV model  at the 2006 CES show in Las Vegas.

    Priced at US$2,999, the new model provides a contrast ratio of 1000:1, a resolution of 1920_1080 and a 8ms response time.The PL4271 features what BenQ claims to be its proprietary “Senseye” digital-enhancement technology, which automatically and dynamically improves image quality, adjusts brightness and darkness levels, performs color mapping procedures and reduces jagged edges on images.

    BenQ will also launch two new entry level LCD TVs, the 32-inch VL3231 and the 37-inch VL3731 in the second quarter of 2006 with price tags of US$1,299 and US$1,799, respectively.

    The Company also showcased a full lineup of digital projectors. The range includes four new models the CP120, MP770, MP720p and the PE8720. The CP120 is being called the “world’s smallest and lightest micro-portable digital projector” by BenQ. This model comes packed with built-in 802.11a/b/g wireless capability and weights only 2.9 pounds, which makes it an ideal solution for mobile professionals, according to the manufacturer.

    The CP120 boasts a 2000:1 contrast ratio and is compatible with most major video standards, from NTSC and PAL to EDTV and HTDV formats, including 1080i, 720p, 576p, 576i, and 480p. More specs below:


    8.58″ (w) x 6.77″ (h) x 2.40″ (d) unit dimensions
    2.9 lbs weight
    DLP&153;-based chipset
    IEEE802.11a/b/g wireless presenter
    2000:1 contrast ratio
    5-segment Golden Ratio Color Wheel
    4:3 aspect ratio with 16:9 support
    XGA native resolution
    54 inches at 6.6 feet throw ratio
    1500 ANSI lumens brightness
    Inputs: NTSC, PAL, SECAM, EDTV and HDTV (1080i, 720p, 576p, 576i, 480p and RGBHV)
    The unit is available now for $1,799.

    Next up is the MP720p, designed for education and business professionals. The portable projector is even more value-attractive with a price tag of $1,299. The unit is also available now. Its specs, as follows:


    11.45″ (1) x 3.70″ (h) x 9.21″ (w) unit dimensions
    6.6 lbs weight
    Full 16.7 million color palette
    2000:1 contrast ratio
    5-segment color wheel
    4:3 aspect ratio with 16:9 support
    XGA native resolution
    2500 ANSI lumens
    Inputs: NTSC, PAL, SECAM, and HDTV (480p, 576p, 720p, and 1080i)
    The MP770 is being billed as a solution for classrooms. It will be available in Q2 of this year with a price tag of $1,999. Its specs below:


    Technical Specifications
    7.17″ (l) x 3.22″ (h) x 9.21″ (w) unit dimensions
    6 lbs weight
    Full 16.7 million color palette
    2000:1 contrast ratio
    5-segment color wheel
    4:3 aspect ratio with 16:9 support
    XGA native resolution
    3200 ANSI lumens
    Inputs: NTSC, PAL, SECAM, and HDTV (480p, 576p, 720p, and 1080i)
    And finally, BenQ’s cream of the crop HD projector, the PE8720, has been created with high-end videophiles in mind. The unit costs $7,999 and is available now. Its meaty specs are listed as follows:

    TI Darkchip3 DMD
    Brightness: 1000 ANSI-lumens
    Contrast Ratio: 10000:1
    Input terminals: Component (BNCx5, RCAx3), S-Video, Composite (RCAx1) and HDMI (with HDCP x1)
    Weight: 9 kg (20 lb)

    No Australian pricing is yet available.

    Is Dick Smith Set To Become Super Cheap Tech?

    Is Dick Smith set to become Super Cheap Tech?

    Sources within Dick Smith claims that the Super Retail Group that own Super Cheap Auto group are currently running a ruler over the remnants of the Dick Smith retail chain that was placed into administration earlier this week.

    ChannelNews has been told that the group is only interested in selected stores and that over 50% of the current Dick Smith stores could be closed down.
    Under Super Cheap Tech, the stores could take on Jayco as well as range auto tech and consumer electronics excluding the likes of TV’s and PC’s. 

    Dick Smith’s bankers – NAB and HSBC – called in receivers Ferrier Hodgson who is set to formally launch a for sale process in an effort to shift the Dick Smith group as one entity.

    ChannelNews has also been told that both a South African and New Zealand retail group have contacted the receivers regarding selected assets. 
    The company’s New Zealand operations, which remain profitable, are expected to be the most attractive of the assets along with the Move stores and the Dick Smith online operation.

    The collapse came just days before another company, home furnishings chain Laura Ashley, called in FTI Consulting as ?administrators.

    FTI Consulting said it intended for the business to trade as usual while “an urgent assessment of the company’s financial position is conducted”. Laura Ashley’s New Zealand operations will not be affected, nor will the brand’s British stores, which operate as a separate company.

    Despite the failure of the two retailers, analysts anticipate strong results from the December trading period. Analysts at Citi said it appeared discretionary spending growth over Christmas would hit 6 per cent, with feedback and store visits showing strong results for Dick Smith competitor JB Hi-Fi and Super Retail Group’s Rebel business.

    Ferrier Hodgson’s James Stewart on Tuesday said the New Zealand business was profitable and “expected it would be ?attractive to potential buyers”. The company operates 62 stores in New Zealand.

    Another retailer that could be interested is Briscoe Group, which operates a number of brands including Briscoes Homeware, Living & Giving and Rebel Sport in New Zealand.

    It has about 80 stores across the country and annual revenues of more than $450 million.

    The company unsuccessfully tried to acquire another Australian chain, Kathmandu, last year, lobbing a $312m bid in July.

    Toshiba Shares Smashed After $1.2 Billion Dodgy Profits Scandal

    Struggling PC, copier and medical equipment Company Toshiba who last year slashed 19 PC operations around the world has admitted they have been fudging their profits for several years.

    Now the Japanese Company is set mark down past profits by a massive $1.2 billion due to what Toshiba management are describing as “accounting irregularities”.

    The latest markdowns is almost double its earlier estimation with a large percentage of profits or lack of them attributed to the poor performance of the Companies PC Division. 

    In a case shaping up to be one of corporate Japan’s biggest debacles since a scandal at Olympus in 2011, a Toshiba-appointed independent panel has been investigating the infrastructure giant’s finances after Japan’s financial watchdog warned of possible accounting irregularities back in February.

    The company said in May it would need to reduce its profit for the 2009 through 2013 fiscal years because of improper accounting.

    Since the problem was discovered and following investigations by independent investigators, massive irregularities were discovered in Toshiba’s personal computer and semiconductor businesses

    Initially Toshiba management tried to hide the scale of scandal.

    The independent panel is expected to report its findings by mid-July. Chief executive Hisao Tanaka has hinted there will be a major management reshuffle at that time with the real possibility emerging that more Countries selling PC’s could be slashed or the PC Division dumped all together.

    The Wall Street Journal said that as a result of the accounting problems, Toshiba hasn’t been able to report its earnings for the 12-month period ending March 31-an announcement originally scheduled for June. The company hopes to file the earnings by the end of August.

    Worries over the earnings restatement and the company’s corporate governance culture have weighed on Toshiba’s shares which have plunged on the Tokyo stock market. 

    Analysts say, however, they are not worried about the possibility of a cash shortage.

    “This is one of the largest crises in our company’s history,” said Mr. Tanaka, at an annual meeting of shareholders last month. Some shareholders demanded the resignation of all executives when their terms expire in September.

    Amazon Is Coming & Retailers Had Better “Be Ready” Warns Officeworks Boss

    Amazon is coming to OZ and retailers had better be ready.

    At a Retail Leaders forum in Sydney yesterday, Wesfarmers group managing director Richard Goyder said that the US Amazon giant will “eat all our breakfasts, lunches and dinners”, unless Australian retailers become more innovative and barriers to competition are removed.

    Wesfarmers owns both Coles, Officeworks, Target, Bunnings + K Mart. 

    At CES 2016 a Best Buy executive told ChannelNews that the Company had to “learn quickly” how to deal with Amazon when they started stripping market share away from the consumer electronics retailer. 

    Greg Revelle the chief marketing officer for Best Buy said that the retailer had to make sure that they delivered a better instore experience while competing head on online. 

    A former senior executive at Radio Shack said that it was the impact of Amazon that killed off Radio Shack.

    Mr Goyder said that Amazon are currently are gearing up for a major push into Australia and that retailers had better be ready. 

    Goyder says his biggest fear was not the competitive threat from Australian retailers but overseas online retailers such as Amazon. 

    He said that online retailers such as Amazon, Google and asos.com could trade 24 hours a day, seven days a week and 365 days a year, while Australian bricks and mortar retailers, including Wesfarmers’ Bunnings, Kmart, Target, Coles and Officeworks chains, were restricted by archaic trading hours and excessive regulation.

    When it was first founded in 1994, Amazon.com was operating out of founder Jeff Bezos’ garage and earning $20,000 per week in sales within two months. Twenty-three years later, Amazon has 175,100 full-time employees and earned nearly A$150 billion in revenue in 2015.

    Known as ‘The Everything Store’, especially with Amazon Marketplace enabling sellers to offer new and used items alongside Amazon’s own products the launch of Amazon could have a major impact on Australian retailers who lack capability.

    The US Company is already sourcing warehouses and several major Australian Companies are already using Amazon storage and cloud serices offerings.  

    Amazon began as an online book retailer, thanks to Bezos’ research that illustrated the worldwide demand for literature combined with the low price of books and the huge number of titles available in print. Gradually, Amazon expanded into selling CDs, DVDs, toys, electronics, and appliances.

    After surviving the dot-com bubble bursting at the start of the 21st century, Amazon introduced Amazon Prime in 2005, a membership offering free two-day shipping on all eligible purchases for an annual flat-rate fee. Later Amazon Prime expanded to offering its members streaming media. In 2007, Amazon launched Amazon Kindle, an e-book reader, followed by a tablet computer called the Kindle Fire in 2011.

    Amazon Prime, meanwhile, has also contributed dramatically to the company’s growth. In 2009, Amazon had 2 million Prime members, and in 2011, that grew to 5 million; in 2015, Prime membership is estimated to be around 40 million, and worldwide paid membership grew 53% last year. Even better for Amazon? Prime customers spend over double what non-Prime customers do- about $1,500 per year compared to about $625 per year.

    One of Amazon’s most significant lasting impacts was their adoption of “free shipping” in the early 2000s, when they began their Super Saver Shipping program, offering free shipping for orders of over $25. During one promotion, Amazon began offering free shipping with the purchase of a second book, which lead to a huge jump in sales. Clearly, Amazon realized that consumer psychology favored labeling things as “free”; however, they might not have foreseen the effect free shipping would have on side industries such as shipping and logistics.

    Some retailers doubt that Amazon will be able to offer free shipping in Australia due to the high cost of transport. 

    The Impact of Amazon.

    A consumer realizes that he needs to replace his coffee maker. 

    He knows he has two choices: driving to a physical store and hoping that they have the model he wants, and loading it into his car and driving home, or searching online until he finds his preferred make and model at the lowest price available, and having it shipped directly to his home. Which one does he choose? These days, our hypothetical consumer is becoming much more likely to choose the latter option. Thanks to online shopping, foot traffic, retail space openings, and holiday sales in retail stores have all decreased significantly in the USA 

    When and if Amazon arrieves in Australia the impact on retailers could be “severe” especially with foot traffic through the door of retailers claims analysts. 

    For example, brick and mortar retail stores in the USA saw foot traffic cut by about 50% between 2010 and 2014, from more than 30 billion visitors during the holiday season to 17.6 billion visitors. 

    Similarly, new retail space openings have been extremely low compared to years past, down to 43.8 million square feet in 2013, compared to more than 300 million in 2000, 2005, 2006, and 2007. 

    Finally, online sales increased at more than double the rate of brick and mortar sales during the 2015 holidays; in fact, Shorr research saw a 35% increase in business with e-retailers during the 2014 peak holiday season. 
    These trends have led to significant drops in revenue for some companies, and in some cases, even bankruptcy, with large companies such as Radio Shack, Circuit City and K-B Toys experiencing total liquidation. And while the US economy has added around 2.4 million jobs since the Great Recession, the retail industry has experienced a net loss of 60,000 jobs since the recession.