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

    Smart Office

    How Alberts Pub In North Sydney Can Replace Shocking Service With Smart Systems

    COMMENT:There is nothing like bad service in Australia and Alberts in North Sydney which is owned by the same people as the Rag and Famish and the Terrace Hotel has got to take the top gong for delivering some of the worst service in Sydney.

    I recently walked into this establishment on a busy Friday, there were four vacant tables all covered in plates left over food and empty glasses.
     
    When I asked for someone to come and clear two of these tables, the attitude was “We are busy” we will get someone over when we are free.  

    Then after ordering some food, the meal was served minus any utensils.

    There was no “sorry” we have got no utensils or I will go and find you some utensils.

    After five minutes I again walked up to the counter to ask for utensils only to be told “We are busy, we have none, you’ll have to wait”.

    When I pointed out that it was plain dumb, let alone, poor service to actually serve a meal without utensils the waiter said “I don’t like your attitude “take it up with the manager”, which I did.

    Seconds later a ranting raving chef from the kitchen came out claiming that “I was a whinger” who had complained earlier about the dirty tables.

    “If you don’t like the service f*&k off we are busy”.

    When I went back to the table the same waiter came over with the utensils he then complained that “He did not like my attitude”. 

    I pointed out that the fundamentals of the most basic food establishment is that firstly the tables are clean and cleared and that when a meal is actually plated and served that there is actually utensils to eat the food with.

    Alberts is owned by the Calligeros Group a family Company that owns several pubs around Australia.

    What my experience exposed was not about pig ignorant management and staff who really don’t give a stuff about dirty tables or poor service but the lack of intelligence and systems inside an industry that is seriously under pressure. 

    Blind Freddy would be able to tell you that Friday is always a busy day in North Sydney, and blind Freddy would also tell you that this is the day when your operation is going to be pushed to the limits. 

    A banker once told me that when it comes to delivering service and systems in Australia that they have to build and be able to cater for only six days of the year, four days before Xmas and two days after the Boxing Day sales as this is when their ATM systems are the most stretched. 

    Organisations like Alberts are not heeding this lesson despite the pubs and clubs industry struggling to deliver growth in Australia.

    Australians’ love of eating out is growing with latest household expenditure data revealing big gains for the foodservice sector. The only problem is that consumers are not going to places like Alberts because of their attitude to service.


    The Australian Bureau of Statistics Household Expenditure data shows that in percentage terms the sales for restaurants, cafes and caterers in March 2015 has increased by 12.3 per cent from March 2014 while the pub industry has struggled to grow.

    At the same time the Pubs, Bars and Nightclubs industry has recorded moderate growth over the past five years.

     Growth has been constrained by strong competition, volatile consumer sentiment and a dependence on gambling as a revenue earner as opposed to putting in place systems that provide intelligence that allows them to deliver better service.

    Today there are several systems that deliver intelligence for people who sell food. I travel a lot and the likes of Alberts has to take the Guernsey for delivering some of the worst service and above all attitude that I have ever come across in a restaurant environment. 

    Even in Las Vegas during CES when there are over 175,000 CES attendees and over 2 million visitors passing through food establishments one gets service that is a vast improvement on what the likes of Alberts are dishing up for consumers.
     
    The lack of service and good food facilities in pubs like Alberts has  caused the collapse of some highly leveraged pub operators, as many consumers have swapped a bar stool for the comfort of their couch at home instead of a night in the pub with friends. 

    Even at Alberts on a Friday a Steak is $24 add a cider to that and there is not much change out of $30.

    Pub industry revenue is expected to increase by an annualised 2.1% over the five years through 2014-15, to reach $16.5 billion which could mean that pubs who continue to deliver poor services as Alberts go out of business.
     
    One only has to look at the difference in service levels between a well-run establishment like The Tree House in North Sydney and Alberts to realise why the Tree House is constantly packed and Alberts most evenings of the week struggles to attract patrons.
     
    According to research group IBIS World the Pubs, Bars and Clubs industry is in the mature phase of its life cycle. The industry enjoyed a growth phase between the mid-1990s and the mid-2000s, underpinned by the introduction of gaming machines in many venues. 

    IBIS said that this trend is ending, with mounting community and political opposition to gaming machines expected to result in regulation that will stifle growth in this segment. 

    Back in 2007 the Sydney Morning Herald reported that when the owner of Alberts Peter Calligeros picks up the paper in the morning it’s usually with a touch of dread, not knowing which particular story is going to be the latest unexpected pressure on his pub business
    Calligeros cites external pressures outside his control as the biggest challenge facing his business, which also comprises the century-old Rag and Famish Hotel, and the Mount Street Terrace hotel both in North Sydney, and also includes the Bargo pub, near Wollongong and a recently added establishment in Brisbane. 

    It appears by the attitude of his management at Alberts that they don’t share the same sentiment as their owner who was quoted as saying 

    “I like to walk into all my pubs and have people sitting at the public bar say ‘G’day Pete, how are you going?’ I like that whether it’s out at Bargo or in North Sydney.

    Maybe if he walked into Alberts more often he would realise that he desperately needs intelligence to give him a heads up that he needs to buy more knives and forks than the meals he serves or that when a meal is actually being delivered to a tablet that his wait staff actually take a knife and fork with them as opposed to dumping a meal on a table and expecting the customers to use their fingers to eat.

    Then again the Rag and Famish is one of the oldest pubs in Sydney so maybe the model is still back in in the 1860’s when eating off a plate with ones fingers was an established practise. 

    LCD PC Monitors Big Growth

    LCD PC monitor shipments will hit 155 million units in 2006, with LCD monitor shipments reaching 125 million units for an 80% share of the market, according to a forecast from DisplayBank.

    LCD monitor shipments are expected to increase 19% this year, while CRT shipments should drop 31%, about the same rate of decrease the segment saw in 2005, the market research firm noted.

    Worldwide monitor shipments are projected to grow by a relatively modest 4% in 2006, and growth will stay at around 5% in the future, as growth in the desktop PC market slows due to a transition to notebook PCs. According a DigiTimes Research forecast, Taiwan will ship 97.5 million of the projected 155 million LCD monitors this year, up 29% from 2005.

    Source: DisplayBank, compiled by DigiTimes.com, January 2006.

     

     

    Large Sized LCD Monitor Market To Dominate

    The large-size LCD monitor market, 19-inch and greater, is expected to account for more than 50% of the worldwide market next year, accompanied by a rapid shift in generations toward larger sizes for LCD monitors as well as LCD TVs.

    The large-size LCD monitor market, 19-inch and greater, is expected to account for more than 50% of the worldwide market next year, accompanied by a rapid shift in generations toward larger sizes for LCD monitors as well as LCD TVs.

    According to a market research firm Displaybank’s data on LCD monitor market size forecasts, market share of 19-inch and larger LCD monitors is predicted to increase by 10% from 25% in 2005 to 35% in 2006, and this trend will continue through 2007, hitting 52%, more than half the market.

    Moreover, the market research firm foresees that 19-inch products will net 27% of the total market this year, and 43% next year, emerging as the ‘Best Seller’ model instead of 17-inch. This robust upward trend will continue into 2008, with the share of 19-inch models 23% higher than 17-inch share. As such, a shift in generations in the LCD monitor market is projected to accelerate dramatically.

    EMC Goes All Security

    EMC is set to initiate a major security uprade to its product range. The move comes as EMC initiates its largest product refresh ever.

    The move also comes at a time when the company finds itself in marketplace battles with Symantec who have a reputation for security.

    EMC’s convert to security religion will see major upgrades to both its SMB offering and large enterprise solutions.It follows in the footsteps of Symantec’s merger with Veritas and Network Appliance’s planned acquisition of data-encryption vendor Decru, reflecting the growing need for storage and security to converge. EMC president and CEO Joe Tucci announced the plan in a briefing presented to Wall Street and industry analysts.

    “Information and security do go together; they are not separate,” he said. “Customers are not asking us–they are demanding it.”EMC has already added encryption capability to its Dantz Retrospect backup software, and intends to do the same with the rest of its software lines and storage systems. Company officials are emphatic that EMC is not seeking a major acquisition partner, but hasn’t ruled out smaller deals and partnerships.

    Recent losses of backup tapes by key banks, credit-card processors and government agencies, among others, potentially exposing the personal information of millions of people, have brought the issue of storage security to the forefront. EMC had to up the ante on security, notes equity analyst Daniel Renouard, of R.W. Baird claimed. “How they execute will be really hard,” Renouard says. In addition to security, EMC is seeing strong demand for its VMWare unit’s server-virtualisation software. After posting 93 percent growth last quarter, EMC is now a $400 million company.

    “That’s a tremendous opportunity,” Tucci told analysts.Another key area of emphasis will come from EMC’s network-management subsidiary, Smarts, which it acquired in February. Using that company’s network-monitoring technology and EMC’s Documentum workflow engine, EMC plans to bolster its own Control Center Management console early next year. The revamped Control Center will add network analysis and workflow from both Smarts and Documentum.

    Tucci says Smarts’ tool collects data and events. It can tap into other data, build a model of how the various components are supposed to interact and take appropriate actions.

    “It’s going to give us magic,” Tucci says. As a result of its expanded strategy, EMC is fine-tuning its tagline, from that of an information life-cycle management (ILM) provider to an infrastructure-management company. The storage giant says it’s not moving away from ILM–which accounts for 95 percent of its revenue–but rather that it is part of what EMC sees as a broader market encompassing not just the management of data, but the infrastructure that supports it.

    Meanwhile, EMC has just refreshed the Symmetrix DMX line with its largest system to date, and has upgraded its flagship CLARiiON storage arrays as well.

    New OZ Mobile Ad Measurement A World First

    Australian research Company Nielsen, has launched a new mobile Internet audience measurement intelligence service which they are describing as a world first in online audience measurement methodology.

    Thy claim that the launch of Nielsen’s Mobile Market Intelligence service will address demands from the industry for third-party metrics on mobile Internet usage in Australia, providing consistent and transparent metric for mobile advertisers and publishers.
    Results from the new service are available from mid 2009, with April 2010’s data showing average daily unique browsers accessing the Internet via mobiles at 138,574, with average time spent online via mobiles sitting at around four and a half minutes. 
    “The launch of Mobile Market Intelligence is an important step for mobile publishers in Australia. It provides media buyers with vital third-party information on mobile sites which serves to support and provide more confidence in those media buyers’ decisions on where to allocate clients’ advertising spend,” states Matt Bruce, Managing Director of Nielsen’s online business in Australia.

    “Our clients have been telling us that the lack of independent, credible information on mobile sites has been holding back the growth of mobile advertising spend, and Nielsen’s launch of Mobile Market Intelligence is in direct response to this feedback.”

    Bitter E3 Style Infighting Revealed After Voluntary Administration

    The CEO of Queensland based distributor E3 Style Vanessa Garrard claims that her Company, has not been placed into liquidation, she claims that E3 Style, which is suffering from cash flow problems, was deliberately placed into voluntary administration.

    Garrard claims that the Company ‘became the largest licensed electronics distributor in Australia’ and that “her” Company will continue to trade, and that she has every intention of fulfilling all existing orders. She has not said whether she has the ongoing financial capacity to fund the placing of further orders with overseas manufacturers.

    Documents lodged with the Australian Securities and Investment Commission clearly states that a registered “Liquidator” Domenico Alessandro Calabretta has been appointed as an External Administrator to the Company.

    E3 Style, called in the administrators on April 15, Domenic Calabretta from Mackay Goodwin was appointed voluntary administrator, he has not returned our calls.

    A creditors’ meeting is scheduled for April 28 in Brisbane, past clients of E3 Style are Dick Smith who dropped using E3 Style instead choosing to run their own house brand sourcing operation, along with JB Hi Fi who also cut their relationship with E3 over problematic deliveries and contracts.

    It’s believed that revenues have slumped from around $23M in 2012 to sub $15M this year.

    The business claims that it holds the licenses for branded Star Wars, Batman, Scooby-Doo!, Hot Wheels and The Simpsons products. ChannelNews understands that the Company has lost some license rights this year.

    Also placed into administration is KreativeDNA Pty Ltd which is a E3 Style related Company.

    Garrard, claims that the decision to place the Company into administration was a direct result of claims against the Company including a statutory demand from a business linked with Crawford Giles the CEO of Powermove who are a highly successful consumer electronics distributor based in South Australia.

    She is also describing the current Supreme Court action between The Crest Company asnd E3 Style as being based on “theft of information”.

    Garrard claims everyone will be paid in full when the administration is completed however she has not explained what will happen if both the Court cases that E3 Style are involved with go against the Company.

    Estimated costs spanning the original claims and the cost of running the action against The Crest Company which has already ran up legal bills of $2M for both sides in the case could total over $3M.

    When asked about the decision to place the Company into administration she said “This is to control the situation,” Garrard says.

    Garrard who is embroiled in a messy court case with her former employers, The Crest Company claims that the E3 v Tomkins & Crest Court case that is being played out in the Queensland Supreme Court has cost E3 almost $1million to date and E3 Style, will continue on with the court case as the “direct financial impact to E3 “was substantial”.

    Garrard is claiming that E3 incurred losses as a result of actions taken by The Crest Company and a former Crest employee Michael Tomkins who quit E3 to take on a role at Crest.


    Garrard also claims that she was never employed as a PA or worked in the Crest call centre.

    Investigations by ChannelNews reveal that Garrard was not PA to a senior director at The Crest Company for 4 years she also worked in the outbound Crest sales team.

    Information has also been supplied to ChannelNews, that Crest management who Garrard later had a major falling out with, provided a $1,000 advance against her wages when she first started at the Company that E3 Style are now taking action against.

    We have also been told that Garrard while employed in a sales role at Crest she was responsible for the loss of a $500,000 contract to supply Sanity Music, the fallout over the Garrard negotiated contract led to Sanity terminating their relationship with Crest.

    Garrard told ChannelNews in one email “I have had a hard upbringing – I built this business with $10,000 and I built up almost $120k in debt on credit cards”.

    She also claimed in the same correspondence that both Crawford Giles the CEO of Powermove and Dirk Olbertz who E3 is also suing are executives who have been “spoon fed”.

    In correspondence with ChannelNews Garrard also claims that E3 Style has “not been sued for “over $250,000.00” by “Powermove”.

    Crawford Giles of Powermove is, through another entity, beneficially entitled to a significant shareholding in E3 Style.

    She then in the next sentence said “The references to the litigation with Powermove and funding issues do not disclose that Powermove failed to honour payments for orders placed by it with E3 Style under their Distribution Agreement”.

    Garrard went on to claim that “As a result E3 Style funded those orders separately so as to ensure its customers receive their orders”

    She said that “Reference to struggling to fund orders are limited to orders Powermove failed to honour and E3 was then put in a position to fund those which is outside of E3 normal business model, E3 did however fund those orders”.

    The actual amount that Crawford Giles is claiming from Garrard is believed to be $285,000.

    Garrard said that she has never advised anyone that Harvey Norman is buying into the business of E3 Style.
    She also claims that “the Commonwealth Bank continue to be a banking partner but do not fund the company’s operations”.

    She has not said whether the Commonwealth Bank has suspended borrowings to E3 Style or whether the Commonwealth Bank is a creditor of E3 Style.

    She also said that her business partners were bought out, and that neither “quit”.

    “Director’s don’t “quit”, they sell their shares” she said.

    Garrard has not return calls made to her.

    Ogilvy PR Owners Report Massive Loss

    STW the owner of Ogilvy Public Relations, Howorth and Pulse the PR Company for brands such as Microsoft, Toshiba, E Bay, Netflix, Canon and Activision has reported a massive $52.6 million loss.

    This compares to a profit in 2014 of $44.6M. STW who is one of Australia largest marketing and communication Companies is currently undergoing a major restructure. It is not known whether Ogilvy PR, Howorth or Pulse were contributors to the Companies losses. 

    While net revenue was up by 1.6 per cent to $416m, underlying earnings before interest, tax, depreciation and amortisation (EBITDA) were down by 7.8 per cent to $76.8m.

    “After a disappointing finish to 2014, the company undertook a strategic and structural review during the course of 2015 and made tough decisions to restructure the business,” STW chief executive Mike Connaghan said.

    “We have implemented a number of initiatives designed to drive deeper engagement with each of our business, coupled with stronger financial and management oversight.”

    It is the first result since STW announced it would merge with the Australian and New Zealand business of global advertising giant WPP.

    Two Big Investment Groups Team Up To Bid For Big W

    Big W, Woolworths struggling department store, has been targeted by private equity giants TPG and The Blackstone Group who are believed to have teamed in an effort to take control of the mass retailer.

    While no formal bid has been made Fairfax Media are tipping that an offer is being formalised. 

    The Carlyle Group who has been tipped as a potential acquirer of Big W denied its involvement. 

    The two most pressing issues for the Woolworths board who are believed to have been in talks with Roger Corbett the former Fairfax Chairman and Woolworths CEO are the performance of the retail giant’s hardware chain Masters (a joint venture with United States-based retailer Lowe’s) and its discount department store chain Big W. 

    The latter has been beset by a number of problems including sliding market share and the bungled roll-out of a logistics platform. 

    The poor performance of Big W was again highlighted by the quarterly sales results of Woolworths and Wesfarmers.

    While Wesfarmers’ discount department stores delivered strong same-store sales – the Kmart chain delivered growth of 8.6 per cent, and Target 3.2 per cent – same store sales at Big W were down 8.1 per cent and total sales were down 7.9 per cent.

    Woolworths’ share price has fallen more than 20 per cent since the start of the year as concerns have grown up its ability to compete with rival Coles (owned by conglomerate Wesfarmers) and its loss making ventures.

    ATO Targets CE Companies Big Brands Set To Be Hit By New Tax Legislation

    More than 30 large IT and consumer electronics Companies are set to be hit by new Federal Government legislation that’s designed to extract taxes from organisations such as Microsoft, Apple and Google who have been using tax minimisation schemes to avoid paying their fair share of taxes in Australia.

    The Turnbull government expects to raise “hundreds of millions of dollars” from over 1000 multinational companies who are shifting vast amounts of revenue to tax havens. 

    1000 companies with global revenues above $1 billion are set to be targeted. They include Companies such as Sony who has already been fined over $30M for engaging in tax avoidance schemes, Samsung, LG, Panasonic and Companies like Epson who several years ago were investigated for transfer pricing. 

    Both Apple and Microsoft Australian operations are known to place orders on an overseas supplier or subsidiary and as these products are being shipped the ownership of the products change to a subsidiary based in a tax haven. Microsoft does this on the Surface Pro 3, Xbox console and Apple on their new iPhones, and iPads as well as their Mac PC’s.   

    Earlier today Treasurer, Joe Hockey made good on a budget promise, by introducing to Parliament a bill altering existing tax laws to target companies suspected of avoiding their fair share of tax.

    Companies found to be “cheating” the Australian Tax Office will be forced to pay back double what they owe plus interest.

    According to Fairfax Media Mr Hockey was immediately criticised by the opposition for not being able to put a specific figure on how much the measure will raise and tax experts warned that it could spark “retaliatory” laws by other governments to targeting Australian companies.  

    The Tax Office embedded staff in the offices of 30 high-risk multinationals to learn more about their tax structures, several of these Companies were technology Companies operating in the Consumer Electronics market.

    Hockey said that a number of multinationals have already come forward and are, he said, “Prepared to restructure their businesses to pay their fair share of tax”. ChannelNews has been told that Apple and Google are among those Companies. 

    “With the introduction of this legislation, we are sending a clear message that Australia has no tolerance for tax avoiders. If you are avoiding tax, the Australian Taxation Office will catch you,” Mr Hockey said.

    Tax Commissioner Chris Jordan said the ATO’s task would be to understand the actual profits companies make in Australia but “backed out” of the country.

    A Senate inquiry into tax avoidance has heard evidence that multinational tech companies such as Apple, Google and Microsoft make huge sales in Australia but report tiny taxable profit margins. 

    Likewise, pharmaceutical companies are under pressure over their low profitability in high tax markets such as Australia.

    The new rules appear to also apply to large Australian-owned multinationals such as BHP Billiton and Rio Tinto, which have been criticised for booking profits in low-tax jurisdictions such as Singapore where they have established “marketing hubs”.

    Mr Jordan said: “We have to . have a much better understanding of [companies’] true cost of sales not some inflated cost of sales.

    “We know there are billions of dollars of sales of revenue that is not being booked in Australia,” he said.

    Dick Smith Receiver Sale Described As One Big “Con”.

    The Dick Smith receivers, Ferrier Hodgson are believed to be under investigation by the Australian Competition and Consumer Commission (ACCC) over their so called ‘Receivers Sale’.

    According to sources complaints have been lodged with the

    ACCC concerning the discounts being offered.

    An Investigation by ChannelNews and SmartHouse reveals that

    several branded goods such as LG and Samsung TV’s are significantly more

    expensive at Dick Smith stores than at Harvey Norman, JB Hi Fi or Bing Lee

    stores.

    A Samsung 60″ TV model number UA60J6200 is being marked

    up at Dick Smith stores in Chadstone, Victoria at $1,819.

    The same TV is selling for $134 cheaper at Harvey Norman. To

    further seduce consumers into buying this model the Dick Smith receivers are

    offering ‘Receiver Sale’ saving of $230.


    Click to enlarge


    Click to enlarge

    Click to enlarge

    Click to enlarge

    Harvey Norman is not offering any sale discounts.

    An LG 60″ Smart TV 60LF6300 is ranged in the Dick Smith

    receiver sale at $1,899, the same TV is being sold for $1,679 a saving of $220.

    Ironically Dick Smith claims that consumers are saving $600

    by buying this TV from their stores.

    In both the PC wearable and accessories categories goods are

    more expensive at Dick Smith stores than at other consumer electronics stores.

    A sales assistant at one major Victorian store said.

    “Consumers are coming into the store believing that there are bargains

    because we have been placed under administration, when they check on their

    smartphones, what price the same goods are selling for in other stores they

    leave. There really is no sale, it’s all one big con”.

    A Chadstone staff member said “Things were cheaper when

    Dick Smith was running the stores. As soon as the receivers moved in we were

    told to jack up prices. I suppose the banks want to get their money as quick as

    they can. It’s not looking good”.

    Earlier this week Ferrier Hodgson moved to close 27 Dick

    Smith concessions stores at David Jones stores throughout Australia.

    At one concession store in Victoria a Manager said

    “Dick Smith at David Jones has never worked. In some cases, prices were

    higher in a concession store than at a regular Dick Smith stores. Woolworths

    was going to dump Dick Smith anyway prior to the Company being placed into

    administration.

    The Electronics Powered by Dick Smith outlets within David

    Jones employ two full-time employees, 78 part-time workers, and 101 casual

    staffers.

    In other moves Ferrier Hodgson has moved to advertising the

    Dick Smith stores in Asia.

    Back in November when we identified that Dick Smith stores

    were struggling a potential buyer from Hong Kong approached ChannelNews to obtain

    information about the stores.

    They said at the time that doubted that there was any

    “value” left in Dick Smith stores.

    According to sources still working at the mass retailer all

    of the management associated with Nick Aboud have “gone”.

    “The receivers have already drawn up a plan to mass

    close stores, during the past weeks they have bought operational costs under

    control” they said.

    Ferrier Hodgson retail partner James Stewart “We don’t

    want to leave any stone unturned,” said Ferrier Hodgson retail partner

    James Stewart, who took control of Dick Smith’s 393 stores at the behest of

    lenders on January 5 after the company appointed McGrathNicol administrators.

    “Most of the world’s consumer electronics retailers are

    supplied through Asian markets.  We want

    to make sure we give everyone an opportunity,” Mr Stewart said.

    Ferrier Hodgson claim that they have has received at last 50

    expressions of interest for Dick Smith’s assets but according to sources, most

    were organisations who took copies of the offer document which contained

    historical sales data, store locations a detailed 70-page information

    memorandum to selected parties.

    The deadline for non-binding expressions of interest closing

    today Wednesday 27th of January.

    The receivers claim that they have already commenced

    discussions with a core group of serious buyers and will draw up a formal short

    list after the offer deadline closes this week.

    Mr Stewart told Fairfax Media that he welcomed the decision

    by the administrator, McGrathNicol, to seek to postpone the second meeting of

    Dick Smith’s creditors until August, saying it would give the receivers more

    time to complete asset sales and liaise with landlords.