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 63 of 91

    Smart Office

    Retail Obscured By Government Policy Claims Westpac

    A new Westpac report called What’s in store claims that retail performance and consumer spending is being “badly” obscured by Government policy. They also claim that consumer spending is set to rise from a forecast 0.4% for the quarter to 0.6%, this say Westpac will deliver a bigger ‘payback’ later in the year.

    A new Westpac report called “What’s in store” claims that retail performance and consumer spending is being “badly” obscured by Government policy. They also claim that consumer spending is set to rise from a forecast 0.4% for the quarter to 0.6%, this say Westpac will deliver a bigger ‘payback’ later in the year.

    Currently the Australian retail market is witnessing a surge which means that monthly sales in March were 4.5% above the November level that preceded the fiscal package – and 6.3% higher than March 2008, a stronger through the year pace than registered in Dec-Jan and the strongest recorded since January last year claims Westpac.

    The report written by the economist team at Westpac, headed by Bill Evans, claims that the consumer picture is being badly obscured at the moment, by policy – both large and transitory fiscal boosts and “as such, it is nigh on impossible to gauge the likely ‘underlying’ pace of consumer demand. Financial shocks and wealth effects mean this underlying pace itself is likely to have been volatile over the last six months”.

    “Unfortunately these problems won’t be fully resolved for several months yet. Policy influences will continue to buffet retail sales well into Q3. We continue to see the general backdrop for consumers as remaining bleak. Sales are likely to slow again once policy boosters wash out, with the ongoing weakness in labour markets set to be the main restraint by year end”.

    We had expected a continuation of the wind-down in spending associated with the first round of fiscal payments to dominate in March. The $8.7bn injection had seen sales jump 3.8% in December and rise by a further 0.5% in January. And although sales dropped back 2% in February they remained well above their ‘pre-stimulus’ levels. Although the second round of fiscal payments started to go out to households in March, these were set to be ‘drip fed’ over several months – as such; the wind-down was expected to dominate.

    The upside in retail spending was dampened by a very strong price component – the implied retail sales deflator jumped 1.5% in Q1, the biggest quarterly increase since the GST introduction and, excluding that, since 1990.

    Sharper Image Looking For OZ Distributor

    Sharper Image who made a fortune selling gadgets for smart houses and then lost it all when they went belly up last year in the USA is back and they are looking for either a distributor or retailers in Australia to sell their new range of products that were launched at this year’s CES show in Las Vegas.

    The private investors who purchased the brand name when “The Sharper Image” filed for Bankruptcy Protection in February of 2008 believe that the name and the products branded with the name “have enormous potential in Australia” according to a Company spokesperson at this year’s CES where they introduced a new range of iPod attach devices, Internet Radio’s and what they describe as “health care” products.


     Rather than operate its own web site, catalogue business or shops the Company wants to cut deals with distributors or retailers to whom they will license their products and brand name.


    The new Company has struck deals with HoMedics, a manufacturer of health and grooming products, luggage maker EnE and others to produce new products.


    The name The Smarter Image was purchased by private investment Company Blue Star Alliance, Gordon Brothers and Hilco Consumer Capital for $74 million in May.


    Since then, the company has reconstituted itself (minus the stores) to become a “global lifestyle brand licensor.”
    “We are keen to do business in Australia we have the brand name and the products that we believe will appeal to Australians. We will be expanding outside of the consumer electronics area so we could well end up with two or three different distributors in different markets” A Sharper Image spokesperson said at the CES Show.

     

    In the past the Company has flogged ionic air cleaners and fogless shaving mirrors as well as battery powered toys and massage chairs.


    “Sharper Image was an aspirational brand,” said Federico de Bellegarde, the company’s vice president for licensing. While people wanted the products, not enough could afford them. “Now we can be in consumer electronic stores and Bath & Bedroom stores as well as department stores,” Mr. de Bellegarde said.


    The new company, which has fewer than 10 employees, kept five of its original product licensees. It currently has the Sharper Image name on 40 furniture and accessory products. Stores Its big push will come at the end of this year, when it releases “hundreds” of new, less-expensive products in partnership with 12 unnamed partners.


    At the Consumer Electronics Show, the company showed a range of new products including home audio gadgets like iPod and iPhone docks, a floating waterproof wireless speaker, and a shower speaker that receives music wirelessly from an iPod. The products ranged from $120 to $300.
    The iPhone dock, which includes a motor to swivel the phone horizontally when watching videos, will sell for about $120, while the floating speaker will cost about $110.

    The company is also working on a new generation of its famous air purifier which ended up being slammed by consumer affairs departments in the USA.

    CISCO Grabs Big Share Of SMB Market

    Cisco in partnership with distributors like LAN Systems and Express Data have helped CISCO grow their share of the SMB market by 40%.

    Sales to small and medium size businesses through its distribution partners have surged almost 40 percent over the past year, Cisco Systems has said.

    The taking of more than 1 million orders is a record for the company, a Cisco spoksman said. Key distribution partners for Cisco’s efforts to drive more sales to the small, medium (SMB) business segment  are Lan Systems and Express Data. “Distributors are the backbone of our SMB channel strategy and last year when we announced an increased focus on the SMB market we knew that if we executed properly we would see a spike in annual distribution order volume,” said John DiLullo, vice president, of worldwide distribution at Cisco.

    “However, hitting the million order milestone in a single year came much quicker than we anticipated and it’s due in large part to our distribution partners,” he added. “They provide personalized ordering services, competitive pricing, and technical pre- and post-sales telephone support for even the smallest customers. We would need to hire an army of people to provide this level of support.”

    Cisco has over the past 18 months introduced more than 30 products focused on the SMB segment as well as signed on several new channel sales partners and offered more support services, financing, applications and training.

    imate Expands In Oz

    Smart Phone company imate is set to expand there distributionoperations in Australia beyond Telstra.

    Smart Phone newcomer i-mate is targeting online retailers, mobile distributors, second-tier and third-tier carriers, and retailers with an expanding selection of Windows Mobile-based cellular phones, said imate Marketing Manager Allison Caruk.

     

    “We are the Smart phone of choice for people in the know and we have achieved great results through our Telstra relationship. We are now moving on to new distribution opportunities in line with global expansion plans. As a result of this we are looking at hiring additional people in Australia”.

     

    The company, whose Dubai-based parent launched operations in 2001, already offers Windows Mobile-based smart phones and PDA phones via Telstra’s distribution channel.

    Caruk said. The parent, Carrier Devices, designs the phones and contracts out their manufacturing. In entering the Australian markets last year, i-mate believes it can succeed because of its focus on Windows Mobile devices. “We are the leading experts” in Windows Mobile-based converged devices, she claimed. The company has no plans to offer smart phones or PDA phones based on the Palm or Symbian operating systems. I-mate will also provide thousands of applications downloadable from its Web site, some for a one-time fee and others, such as security and virus-scanning applications, for a monthly fee.

     

    The company differentiates itself by offering free downloads of select games, ring tones and wallpaper to the phones via connected PC from its Club i-mate site, where users can also download ROM-code updates. Users will also get 24/7 support over the phone and via live online chats as well as a free unlimited hosted e-mail account.

     

    The company’s first two phones are the SP3i, based on the Windows Mobile Smart phone operating system, and the JAM, based on Windows Mobile PocketPC Phone Edition and said to be the slimmest PocketPC phone in the world at 4.25 inches by 2.28 inches by 0.71 inches. Both are triband 850/1,800/1,900MHz GSM models with GPRS Class 10 wireless data.

     

    In coming months, the company plans to expand its selection with three to five devices, including models built on the latest version of Windows Mobile, Caruk said.

     

    Both current models offer Bluetooth, voice recorder, integrated antenna and camera, with the SP3i offering VGA resolution, and the JAM offering 1.3-megapixel resolution. The smartphone features a miniSD slot, and the PocketPC model features an SD card slot that accepts memory cards or a Wi-Fi card.

    Other SP3i smartphone features include a 2.2-inch color display, joystick-like control, Internet Explorer, Windows Media Player, Pocket Outlook, Pocket Word, Pocket Excel and MMS. The JAM PocketPC phone features 2.8-inch color touch screen, virtual QWERTY keyboard and handwriting recognition.

     

    OZ CE Market Facing Rationalisation More Closures To Come

    The former General Manager of Wow Superstores claims that the consumer electronics industry is facing a retail rationalisation and that stores like Big W and K Mart could become the new destination for shopper looking for the latest gadgets.

    Shalin Thomas a former Cole’s executive who joined the Wow Superstores as General Manager Buying and Merchandising in an effort to save them from being placed into administration believes that Woolworths and Coles will shortly move to expand their consumer electronics offerings “especially among smaller items like accessories and small appliances” he said.

    Thomas said that during a recent briefing from GFK executives he was told that the Australian consumer electronics market is set to undergo a “rationalisation” similar to what has happened in the UK.

    Thomas who joined the failed Queensland retail group in January only to see them placed into administration in March was one of several executives who were hired in an effort to help the Company turn around their fortunes.

    Thomas said “There is going to be a major rationalisation, some retail groups will disappear and it is not necessarily due to online shopping, it’s because they are not delivering what consumers want. Today retailing is all about engagement and having the staff who can deliver a good experience for the consumer, unfortunately this is not happening in a lot of stores”.

    “I was recently given a briefing by GFK, they believe that Australia will go the same way as the UK market where supermarkets have got stronger and the specialist retailer selling appliances and consumer electronics has disappeared”.

    He added ” Australian supermarkets unlike Tesco or Sainsbury in the UK will not start selling TV’s because they are restricted by floor space but they will expand their accessory lines while stores like K Mart and Big W will expand their larger consumer electronics offerings as well as appliances”.

    Earlier this year Woolworths confirmed that they are set to close over 100 Dick Smith stores they also confirmed that they are expanding their consumer electronics and IT offering via their Bi W stores who are now the #2 Apple retailer behind JB Hi Fi.

     

    Thomas who has years of experience working in the fast moving grocery business believes that stores like JB HI Fi will get stronger because of their branding and the fact that that they are creating “destination” locations for shoppers.

    He said that during the next 12 to 18 months the Australian market will start to witness change, retailers will come under pressure due to the fast churn of consumer electronic products issues with cash flow and insurance Companies who are moving to mitigate their exposure to the industry.

    Shortly after returning from the Consumer Electronics Show in the USA Thomas was confronted with the fact that his employer Wow Superstores was insolvent and that the retailer was closing 15 stores, resulting in around 580 job losses.

    Since then WOW has been placed into receivership after the group was hit by a $20 million bad debt, tough trading conditions and an eight per cent fall in turnover.

    The group’s turnover for fiscal 2011 was $257 million, or 7.7 per cent lower than for fiscal 2010.


     

    Sony Samsung Relationship Not Dead

    The President of Sony has rebuked the head of Sony TV by claiming that Sony is considering an additional investment in its joint LCD TV venture with Samsung.

    Only days after Makoto Kogure, head of Sony’s TV group, was quoted  as saying that Sony is considering an investment in Taiwanese LCD TV screen maker M&A as opposed to continuing to invest in S-LCD, its joint venture with Samsung Electronics the President of Sony Ryoji Chubachi has said the opposite claiming that Sony is considering making an additional investment in its liquid crystal display joint venture with South Korea’s Samsung Electronics Co. Ltd.

    Sony and Samsung formed a $2.6 billion  joint venture in 2004 to produce liquid crystal display (LCD) panels for flat TVs. Called S-LCD, the venture began shipments of panels in April and is expected to reach full capacity next year.

    “We are studying (an additional investment in S-LCD). It would be the most reasonable choice,” Ryoji Chubachi told a roundtable with reporters. He said, however, that nothing concrete had been decided.Chubachi also said Sony planned to write down about 60 billion yen worth of cathode ray tube television assets in the business year to next March as it shifts resources to more promising flat TVs. Sony officials said the impact was already included in the company’s earnings forecast for the business year.

    Chubachi’s comments come after Sony last week unveiled a new restructuring plan, vowing to cut 10,000 jobs, or about 7 percent of its work force, sell non-core assets and downsize or withdraw from unprofitable businesses.

    During his chat with journalists Chubachi denied reported divisions in the management team  insisting that the Japanese company’s leadership is united and doing all it can to revive its sagging fortunes.

    “There are no contradictions or conflict. I can say with confidence we stand together,” Chubachi, who also heads Sony Corp.’s electronics division and is chief operating officer, told reporters at the company’s headquarters here.Chubachi and Chief Executive Howard Stringer — the new international team heading Sony — announced a revival plan Thursday last week centered mainly on boosting profits at its electronics unit, which has lost money for two straight fiscal years because of the plunging prices of electronics products and the onslaught of cheaper Asian rivals.

    The latest shake-up calls for slashing 10,000 jobs, or about 6 percent of Sony’s global work force, by the end of March 2008. It will also close 11 of its 65 plants and shrink or eliminate 15 unprofitable electronics operations. Chubachi refused to disclose the 15 areas, saying that merely identifying them will hurt Sony’s business.

    The Financial Times reported over the weekend comments from Welsh-born Stringer, the first foreigner to head the electronics and entertainment company, saying the restructuring plan had not gone far enough and conceding that Japan’s “humanitarian” culture in offering stable employment had made dramatic job-slashing difficult.

    But a visibly excited Chubachi, who punctuated his comments with fiery declarations and friendly banter, said management remained united.

    He appreciated the differences in opinion that officials from Sony’s various sections brought in hammering out the revival plan, he said, although he said he has not confirmed the reported comments with Stringer.

    “Of course there is never going to be a day when the CEO, COO and people in the entire company are suddenly all going to come up with the same answer,” Chubachi said.

    Sony, which also has a sprawling entertainment empire including music, movies and video games, said last week it would likely report a 10 billion yen (US$89 million; euro74 million) loss for the fiscal year ending March 31, 2006, mostly from restructuring costs. Previously, it had predicted a 10 billion yen net profit.

    That would be the company’s first full-fiscal year loss since 1994, when it lost nearly 293 billion yen (US$2.6 billion; euro2.2 billion), largely on a write-off for Columbia Pictures that Sony acquired in 1989 for what some considered a higher price than its market value. But today’s crisis may be more critical because the core electronics business was profitable in fiscal 1994.

    On Monday, Moody’s Investors Service put Sony’s ratings on review for a possible downgrade, citing doubts about the new strategy. Other analysts have also criticized it as sounding much like other plans to streamline corporate structure.

    But Chubachi said Sony will answer skeptics with gadgets that offer brilliant image quality tailor-made for the digital home, although he refused to give details.

    Sony is promising to focus on “champion products” with growth potential, such as the PlayStation 3 next-generation console, Bravia liquid crystal display televisions and Walkman MP3 music players.

    Chubachi compared Sony’s plight to the Yomiuri Giants, the Tokyo baseball team that’s doing poorly this season, and said his company is being expected to deliver dazzling products like home runs and shutouts.

    “I hate it when the Giants lose,” Chubachi said with defiance. “And I hate it when Sony loses.”

    PC Sales: Biggest Quarter Fall Ever Despite Windows 10 Roll Out

    Microsoft’s move to push over 100 million upgrades of Windows based PC’s to Windows 10 has done nothing for the PC industry other than give the big software Company, access to millions of consumers personal and PC information while delivering the biggest drop in PC sales ever.

    New research revealed at the weekend by both Gartner and IDC reveals that computer sales actually dropped and that Windows 10 was not a catalyst to drive PC sales.

    Despite spruiking a free upgrade of Windows 10 to existing Windows 8 customers Microsoft was charging PC manufacturers up to $75 for a Windows 10 license on a new PC resulting in price hikes of some PC’s. 

    Both Gartner and IDC estimate that computer sales dropped several points year-over-year (between 7.7 and 10.8 percent) in the third quarter, which is when Microsoft was rolling out their new Windows 10.

    That’s one of the steeper drops in recent memory, in fact. 

    Not that it comes as a complete surprise. As the analyst firms explain, Microsoft’s fast-tracked release left many PC makers shipping existing systems with Windows 10, which weren’t going to drive demand as much as brand new models. 

    You’re not going to buy a months-old laptop just because it’s running new software, are you? The big question is whether or not the wave of new Windows 10 PCs launching with new Intel processors will make a difference — if there’s still a sharp decline, the industry is really in trouble.

    Big-name brands like Apple, Dell, HP and Lenovo (the market leader) have emerged relatively unscathed — it’s the smaller, more vulnerable companies that are shedding legions of customers. Even Acer and ASUS saw sales plunge by over 10 percent. It’s too soon to say if Windows 10 will stop the bleeding, but the days of booming computer businesses appear to be long gone.

    EXCLUSIVE: Former Dick Smith CEO Facing Bullying Claims

    Desperate to prove himself after being passed over by Myer, the former CEO of Dick Smith Nick Aboud is today facing serious questions, including possible action by former Dick Smith management who have accused him of “bullying” staff as things got desperate at the mass retailer.

    Aboud has also been accused of “blatantly lying” to supplier’s days out from the collapse of the mass retailer who now owe suppliers more than $280M for stock they have no chance of getting a return from.
     
    ChannelNews has been told that Aboud who quit the retailer earlier this month is set to be retained by Anchorage Capital the Company that pocketed $320M out of the float of Dick Smith. 
     
    According to sources several Dick Smith head office staff have move to lodge complaints with Fair Work Australia.

    Earlier today Dick Smith management placed full page advertisments in national newspapers advertising that Dick Smith Stores were “Open”. 


    Click to enlarge


    Last week buyers at Dick Smith were ordered not to talk to the media with all existing buyers forced to sign none disclosure agreements.

    Questions have also been raised as to happened to millions of marketing and Co-Op dollars that Aboud and his management team extracted from suppliers running into the end of the 2015 financial year. 
      
    According to senior Dick Smith management Aboud ran a blackboard at the Company’s NSW headquarters that listed how much additional money, buyers could extract from vendors for marketing activities, between May and June 2015.

    We know that Aboud and former marketing Manager Neil Merola met with senior executives of several consumer electronic suppliers in an effort to shore up cash flow by extracting additional revenues from suppliers.
     
    The CEO of one major supplier was asked for an additional $2M in CO-OP dollars. Several suppliers were told that their products could be pulled from shelves if they did contribute additional support.  

    Back in June Marketing Director Neil Merola categorically denied that Dick Smith was trying to extract above average Channel dollars from vendors.

    Dick Smith’s buyers pushed them to bring forward anything that could support earnings, such as rebates for advertising or discounts on stock, in the past year.

    On 16 Jun 2015 I sent the following email to Neil Merola “We have been told by several vendors and we have had it confirmed by one of your buyers that Dick Smith is asking vendors to put up large sums of money to get their products ranged and marketed by Dick Smith, with the money having to be agreed by June 30th.

    With one vendor you recently agreed terms and then your buyer came back and asked for an additional 20% margin or a “large payment” that has to be paid to Dick Smith by June 30th.

    Several of your suppliers have told me the same story including both big brand and small brand vendors. 

    The last time I raised this with you. I was told that my facts were plain “wrong”.

    We have now seen an email between Dick Smith and a major vendor. What I am doing is giving you an opportunity to comment.’

    Merola came back claiming that our claims were “pure fiction”.  

    Within days of the receivers taking control of the Dick Smith electronics chain Aboud was in contact with Anchorage Capital management.

    The former Chandlers executive who is known for his questionable management style has not commented despite leaving staff, suppliers and customers out of pocket.

    Real Estate agents in Mosman claim that Aboud is looking to place his multimillion dollar beachside property on the market.
      
    Abboud, has told Anchorage Capital executives that he was shocked by the appointment of receivers.

    The Australian Securities and Investment Commission (ASIC) has received several calls and written correspondence calling on the Federal Government organisation to investigate what went wrong at the mass retailer.
     
    Some are calling for the Federal Police to be called in to investigate.

    Aboud is believed to be concerned that it is his signature, that is on a lot of the documents relating to the performance of Dick Smith stores prior to the float and not those of Anchorage Capital executives who benefited from the float.
     
    There are also claims Abboud relied on provisions in Dick Smith’s accounts to support the underlying operation’s performance in the first few years. 

    He was hoping, that he could build momentum in that time to sustain the operation’s performance once these provisions were expended claim s former Dick Smith senior management. 

    Anchorage Capital Partners finally broke cover on Friday to defend the performance of the retailer under its stewardship.

    A spokesman said Anchorage managing director Phil Cave stayed on as chairman of Dick Smith for 12 months after its public listing in December 2013 to ensure continuity.

    He said in December 2014 the company still held more than $95 million in cash and remained debt free.

    Dick Smith shares were suspended at 35?.

    Unlike Abboud, who held on to his 6.5 per cent stake in Dick Smith, Anchorage sold its remaining 20 per cent interest in September 2014 at $2.22, crystallising a $370 million profit from its two-year investment in the business.

    Abboud’s financial interest in the business has plummeted from $34 million to about $5.4 million.
     
    When asked about cash flow and Dick Smith ability to pay suppliers Aboud allegedly said “There are no issues, we have everything under control, suppliers will be paid. Money has been tight running into Xmas I can guarantee you will be paid”.

    One of the Companies hard hit is Ingram Micro who is exposed for over $14M.

    Since acquiring Tech Pacific, Ingram Micro Australia believed to have lost over $200M.

    Matt Sanderson the CEO of Ingram Micro Australia has not returned our calls.

    Also exposed is Melbourne based distributor Synex who is owed over $18M.

    According to the CEO of Synex Kee Ong, the collapse of Dick Smith is set to have a major impact on both the IT and consumer electronics industries, with several industry executives claiming that several small distributors “will go to the wall”.

    At the recent creditors meeting not a single question was asked of voluntary administrators McGrath Nicol.

    Over 100 interested parties representing over 350 unsecured creditors, owed about $250 million, including trade creditors, landlords and some 330 employees, attended the meeting at the Wesley conference centre.

    About 3300 staff are owed $15 million in annual and long service leave ?as well as wage entitlements.

    McGrath also warned that more claims could arise as the Dick Smith saga unfolds.
     
    Mr Hayes acknowledged the lost deposits and gift cards that are no longer redeemable by customers, noting they were “the legal reality facing creditors”.

    There are 200 unsecured trade creditors, 150 landlords and an unknown quantum of customers owed roughly $250 million.

    New Microsoft Hand Held PC

    Microsoft has unveiled its “Origami Project,” a new category of handheld computer that could become the next must-have digital device for the home. It sells for under $1000

    Amid the biggest hype since it launched the Xbox 360 in November the device that runs for only for about three hours on a single battery charge and is set to replace many high end control panels. Samsung is set to sell the first models next month in the USA for $599 to $1,000, depending on what features are included. It is expected in Australia by June 2006


    Click to enlarge

    Origami Project was the code-name for a new category of PC that Microsoft and Intel have been developing for more than a year. They hope the devices will become small and cheap enough that most PC users will buy one to supplement their home and office machines, staying constantly connected via wireless networks. They also see as a product that will communicate with an Xbox or video or storage source.

    The product could also result in CEDIA members selling the device as part of an integrated home automation solution due to its low cost. “This is the first generation of a long string of innovations we intend to bring to small form factors that run full Windows,” said Mika Krammer, director of Windows mobility marketing. “We are not trying to position this Ultra Mobile PC at this time to be all things to all people, so every man, woman and child should own one of these in the next three months.”

    The Samsung has a 7-inch diameter screen, runs Windows XP Tablet Edition and weighs under 1 kilo. Some models will have global positioning systems and wide-area networking features. Storage capacity will range from 30 to 60 gigabytes. Samsung’s model comes with a program that can display TV broadcasts transmitted wirelessly if users have a Slingbox, or separate device.  Asus Computer is expected to sell a version soon in the Australian market.

    Among the device’s software advances are touch-screen capabilities and a digital version of the Sudoku numbers puzzle.Future versions will be based on Windows Vista, the new Microsoft operating system coming later this year, and a new Intel chip set with all-day battery.

    Some of the devices with XP will be able to upgrade to Vista. Analysts said the concept is intriguing but still early. If the devices cost $1,000, people may buy a laptop instead, so Microsoft, Intel and PC makers have to keep prices around $500, said Bob O’Donnell, vice president of client research at IDC.

    “If in one device I can get the equivalent of a GPS and a Web terminal and e-mail machine and media playback device, it starts to become a little more interesting,” he said. There’s also a risk the first versions will be underwhelming, O’Donnell said. “The reason it’s gotten so much buzz and so much press is the vision is very appealing; there’s no question about that,” he said. “It’s a question of execution and delivering on that promise.”

    The PC industry has tried with mixed success to develop handheld computers. It’s also facing new competitors, such as phone company Nokia’s 770 Internet tablet that went on sale in fall for under $400. Because people have different tastes, one device is unlikely to dominate, said Allen Nogee, an In-Stat/MDR analyst who carries a Nokia 770.

    “That’s the thing we see with cellphones; people are expecting one model or form factor of cellphone to fit everyone,” he said. “It’s never going to happen.” Microsoft’s Krammer said there’s an opportunity for the PC industry to build different versions of the Ultra Mobile PC for certain types of users, such as travelers wanting a GPS version loaded with hotel, restaurant and mapping information. Installers

    To start, the most likely buyer is a technology enthusiast. “Do we expect and hope that everyone’s sister and grandmother will own one?” Krammer said. “Not in the near term, but that is certainly an aspirational goal in the years to come.” Several OEMs are expected to release the first batch of Intel-based Origami devices in mid-2006.
    At CeBit, Microsoft demonstrated Touch Pack for Windows XP on Samsung’s Q1 Ultra-Mobile PC to show the ease of navigation for mobile computing.

    Microsoft has also developed special software for Windows XP Tablet PC Edition 2005 and several editions of Vista that incorporate the Tablet PC Windows software.

    The Microsoft Touch Pack for Windows XP’s customisable Program launcher lets users organize programs into categories, and it provides larger buttons and icons to make it easier to find applications. It also includes a thumb-based, on-screen keyboard that’s enhanced for touch-text input, a “Brilliant Black for Windows Media Player skin” and a new touch- and ink-enabled game.

    Woolworths Release Dick Smith From Upside Obligation As Master Costs Blow Out

    Woolworths who last year sold their Dick Smith operation to concentrate on the roll out of the Master hardware chain has finally admitted that the costs of rolling out the chain has blown out to a pre-tax loss of $157M.

    They have also announced that they have released Anchorage Capital Partners from its obligation to deliver Woolworths any upside resulting from the future sale of electronics group Dick Smith.

    Woolworths sold Dick Smith to Anchorage last year and had agreed to some upside in the future if the business was later sold.

    Woolworths said this morning in return for the new deal it would receive payments of $74 million to be booked as income in 2012-13.

    As a result of these additional proceeds the loss to Woolworths from the sale of Dick Smith of $65.7 million shown in its half year 2013 results will become a profit of $7.9 million in financial 2013.

    Anchorage Capital Management said t5hat today signifies a new chapter in Dick Smith’s independent success as Anchorage Capital Partners and Mangement, led by Nick Abboud have completed a release from the financial obligations to its former partner; Woolworths. 
    The buyout coincides with the Phase 1 completion of Dick Smith’s turnaround initiative which has increased operational efficiency, profit margins and growth, since the initial takeover from Woolworths in 2012. 
    Nick Abboud, CEO of Dick Smith Australia and New Zealand says, “This is a very exciting day for Dick Smith – one that we have been working towards since Anchorage first came on board. The Dick Smith business is in a strong financial position with cash in the bank and no net debt. Based on Dick Smith’s performance over the last six months we are confident the business will continue to experience positive growth and performance as a major player in the Australian consumer electronics industry.”
    “Dick Smith is committed to helping consumers get the most out of their technology and that starts in store. In the coming months we will be announcing a number of exciting initiatives that will see major changes to customers’ retail experience and an expansion of Dick Smith’s footprint throughout Australia and New Zealand.”


    Woolworths are also facing the potential of having to pay out between $700 and $800M to Lowes their US partner in October 2014 due to a “Put Option”.

    Master who is selling white goods and small appliances has admitted that they overestimated the costs of launching the chain up against the Wesfarmers owned Bunnings and Mitre 10.

    A statement to the Australian Securities Exchange said the higher losses were due to overly optimistic sales budgets, relatively higher wage costs for new store openings and lower margins due to the sales mix.

    Insiders are tipping that a new CEO could jettison appliances which are not delivering the returns that were first forecast.

    Recently several Analysts questioned the true cost of the Masters roll out and the losses it was accumulating for two-thirds owner Woolworths.

    Woolworths has also announced revised earnings guidance, saying it now expected net profit after tax from continuing operations, excluding non-recurring items, to grow in the range of 5 per cent to 6 per cent.

    Woolworths is still forecasting that Masters will break even during financial 2016, assuming more moderate growth in sales per store and improvements in gross margins.

    Woolworths expected the losses for financial 2014 not to exceed this year’s levels.

    In its hardware update this morning, Woolworths said there were currently 120 active sites on its books for Masters and at the end of 2012-13, 31 stores were open. But due to the timing of approvals and construction the number of store openings in the first quarter of 2013-14 would be lower than the recent run rate.

    Woolworths also moved this morning to quash any suggestion its one-third partner in Masters, US hardware giant Lowes, was seeking to dump its stake in the Australian business and walk away from the partnership.