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

    Smart Office

    HD TV Booming 370 million Screens By 2010

    HD TV is booming with IDC forcasting that LCD HD TV sets are set to out strip Plasma by big margins.

    HD TV is growing with IDC forcasting that sales of HD LCD TV will outstrip Plasma by a significant margin. The standards for digital TV have been in place since 1994. It has only been in the last few years that the sale of HDTV sets got interesting.  While the Wonderful World of Disney sparked the sale of color TV sets, sporting events like the soccer World Cup due next year and the Olympics have driven the demand for digital TV — especially large flat screens.

    With digital TV becoming more affordable by the day, the demand for high-def home entertainment is growing steadily according to industry observations:
    · 74% of European households will have digital TV by 2009
    · 10.4 million digital TVs were sold in Asia in 2004 and 28.8 million will be sold in 2008 (Australia falls under Asia)
    · 20.9 million US will have digital TV by the end of the year, 37 million by 2008
    · 30 million digital TV subscribers in China this year
    · 14 million British households have digital TV
    · 15% of US adults plan to get HDTV
    · Digital TV sales were up 70% in 2004
    · By 2010 more than 370 million sets should be in use worldwide

    While sales are good in front and rear projection systems, it is the flat screen ( plasma and LCD ) segment that has gotten all of the manufacturer attention (Figure 1).


    Click to enlarge

    JB Hi Fi On A Roll CEO Speaks Out On The Economy

    The CEO of leading CE retailer JB Hi-Fi Richard Uechtritz ,has said that rising oil prices is the biggest danger to the Australian economy not interest rates. He claimed this after announcing that his profit for the year ending 30 June 2008 will be around $64 million, a 58% increase on the prior years NPAT of $40.4 million (previous guidance was $57 to $60 million).

    Sales expectations continue to be in line with previous guidance of $1.8 billion, a 40% increase on the prior year. Comparable store sales growth for the 11 months ended 31 May 2008 was 15.8%.

    “While we have had mortgage rate increases the market has absorbed this and I am bullish as to future growth. Employment is not rising and the mining boom is going to be followed by an increase in agriculture sales due to good rains in the bush. This will further strengthen the economy.” He said.

    He added “The one issue that could become a problem is oil and if this keeps rising it could have a knock on effect with other services such as transport food costs etc”.

     Uechtritz said that the strong forecast for JB Hi Fi result will be achieved after absorbing the cost of a substantial first year investment in new stores in New Zealand and the rollout of telecommunications in Australia, both of which should be positive contributors in FY09

    Gross margin in Australia will be similar to last year (FY07), despite the rapid growth of new lower margin categories such as games and computers. Our cost of doing business continues to reduce,which will give us an EBIT margin increase over the previous financial year.

    “While the current retail climate has provided some variability, this outstanding result shows that we have many positives working in our favour at JB and these should continue to more than offset any tempering of consumer sentiment” said CEO Richard Uechtritz. “We continue to grow our market share as recently opened stores mature, we open new stores, expand our offering and reduce our prices on the back of increased economies of scale and a continued focus on costs” he said.

    “We have a very strong and resilient retail model in the right space. Australians’ love affair with technology is alive and well. Whilst consumers may be cutting back on furniture, fashion, eating out, that new renovation and holidays, interest in home entertainment remains strong and we are the undoubted leaders in that space” he said.

    The company will open 24 new stores in FY09, which will be the largest number it has opened in any year since formation. The maturing of the 33 stores opened in the last two years and the 24 new stores will continue to drive solid top and bottom line growth going forward. The company expects to have sales of circa $2.35 billion for FY09, a 30% increase on the prior year.

    The company currently operates 88 JB Hi-Fi branded stores in Australia and NZ. The circa $2.35 billion in sales expected in FY09 will make JB Hi-Fi Australia’s 6th1 largest retailer ahead of David Jones.”The underlying business remains strong,” Julian Mulcahy, an analyst at Citigroup Inc. in Melbourne, said in a report to clients. “The upgrade has been driven by improved gross margins.” He told Bloomburg.

    Humpty Dumpty Destroys Mosman Park

    The Humpty Dumpty Foundation who often work with leading technology Companies to raise money for Children’s hospitals and are the organisers of the now famous Balmoral Burn, have been accused of destroying a park at Balmoral Beach after the running of this year’s event which raised over $1.7 Million dollars for children’s hospitals.

    Visitors to Balmoral beach have been left with a “mud quagmire” that could costs thousands of dollars to repair after a tent city was erected in parkland below Awaba Street in Mosman for the event and a fund raising dinner attend by some of Sydney’s leading business, sporting and entertainment industry executives.

    Click to enlarge

    Also damaged by Mosman Council trucks involved in the event was parkland surrounding the Bathers Pavilion Cafe and restaurant as well as opposite the landmark Balmoral Rotunda where weddings and events often take place. 

    The damage was caused according to local residents after a tent structure was built on Balmoral Beach which resulted in parkland being chewed up by vehicles used by contractors supplying the staging equipment.

    Now residents are demanding that the problem is fixed at the expense of the organisers and not Mosman Council or the residents of Mosman.

    Click to enlarge


    A local resident said “This is an extremely popular park that is everyday used by residents and visitors to Balmoral. Every morning at least 20-30 people enjoy exercise classes in this park, visitors also hold picnics in the park that has been totally chewed up and destroyed by contractors who were not properly supervised by organisers of the event”. 

    He added “There is nothing wrong in the running of the event and local residents are very tolerant of the inconvenience and the noise that the event causes, but to leave a beautiful park in the state that it has been left is appalling and reflects poorly on the event organisers. I only hope that the Council has taken a big deposit because the repair is going to cost thousands and leave residents and visitors without a park for several weeks”.

    A spokesperson for the Humpty Foundation said “We are well aware of the problem. We did raise $1.7 Million dollars and it will reflect poorly on you if you write a story highlighting this problem. It was all done as part of a good cause”.

    Click to enlarge


    They added “We are talking to Council about this issue. Last year we gave the Council $5,000 to repair the damage we caused”.


    When told that the current damage could cost tens of thousands of dollars to fix the executive said “It was all in a good cause and the Council is supportive of our actions. The Mayor Dom Lopez attended the event and is aware of the damage”.
    A spokesperson for Mosman Council was not available.

    David Richards is a resident of Mosman.

    NSW Roads Minister More Interested In Revenue Raising Than Hoverboard Research

    COMMENT: The NSW Government is doing some great things, but occasionally along comes a really dipstick Minister who is more interested in raising revenue than taking an objective look at an issue.

    Take Duncan Gay the Minister for Roads, who really is, Mr kill joy, a man who is obsessed with collecting revenues from just about anything that moves, he calls it “safety” but most residents know that it is all about revenue raising. 

    His latest cash grab target is Hoverboards.  

    Then you have the Premier Mike Baird who is responsible for the Barrangaroo portfolio where at the weekend Panasonic photographer Ken Duncan was threatened to for simply taking pictures of the new Sydney precinct. 

    He was told he needed a permit another fund raising initiative, by a Government that spends millions trying to get publicity for NSW, and Sydney. 

    As for Duncan Gay he claims that a hoverboard is a “contraption” he has deemed them are illegal on NSW roads and footpaths – and anyone caught breaking the law he claims will cop a fine of up to $637.

    Roads Minister Duncan Gay
























     “I don’t want to be the Christmas Grinch but I want people to know and send a message that these new toys have real safety concerns.”

    Really, what would he know? 

    I suspect he has never ridden a hoverboard let alone done any research into Hoverboards as there are very few in the Country.

    We asked the Minister’s PR spin doctors as he is a Minister who “Lovvvvvves” seeing himself in the media, as to what research was done or even considered prior to his statement on the issue.

    The comment that was sent back came from Bernard Carlon the Acting Executive Director for Road Safety.

    He said “Hover Boards don’t have adequate brakes, lights or warning indicators, and can be difficult to control, meaning they can’t interact safely with other people on the road”.
     
    This is despite the fact that one only has to lean back to stop the device.

    He then went on to say “Riders endanger pedestrians on footpaths – Hoverboards are capable of hitting 26km/hour and with some being 20 times more powerful than legal electric bicycles”. 
     
    He added “Riders endanger themselves on roads because they’re unprotected around other vehicles like cars and trucks”. 

    Really!

    What about cyclists who jump lights ride through pedestrian crossings, ride on pavements and weave in and out of traffic.

     These riders take risks way beyond what a Hoverboard rider could ever do. 
     
    Carlon claims The Centre for Road Safety is working with its counterparts across the country to figure out how and where people can use hover boards safely, and develop national laws and safety standards for personal electric transport devices.

    He did not nominate which other State or Territory are doing research and at this stage SmartHouse cannot find one Government department that is researching Hoverboards.

     “Until we can make sure hover boards are safe to use, we won’t take any risks. People wanting to ride hover boards can use them on private property”.

    In other word’s they have done no research on the issue of Hoverboards but they are looking to raise revenue. 

    On Thursday, California passed legislation that allow the use of electric skateboards and other motorised, wheeled devices such as “Hoverboards” anywhere bicycles are allowed, reversing earlier legislation which banned the vehicles.

    They actually went out and did research.

    Now roads Minister Gay has a perfect opportunity to win some friends and put to real use, the hundreds of kilometres of cycle paths that are springing up all over NSW. 


    Are hoverboard riders any more dangerous than a cyclist who weaves in and out of traffic at speeds significantly faster than what a hoverboard will do.

    As a kid I remember building billy carts and then speeding down hills, my biggest problem was my mother when I used my school shoes as a break.

    Then we use to roller blade along the pavement without any fear of getting nicked. And while we wore knee pads we did not wear helmets.

    Remember this is a Government who controls the National Parks where board riders plough into skiers. With some serious consequences.

    There is no fines for them.

    Last week California passed legislation that takes effect on 1 January 2016.


    The new law, called AB 604, defines “electrically motorised boards” as a new legal category (characterised by moving no faster than 32klm per hour, carrying only one person, and being no bigger than 152cm by 45.7cm), California also allows people to ride them on public streets.


     It also requires the rider to wear a helmet, and bans their use of while under the influence of drink or drugs.

    If Gay adopted this approach he could put all those hidden speed trucks to further use hunting down speeding hoverboard riders. 

    The bill is specifically aimed at legalising electric skateboards similar to the one now being sold by Harvey Norman and JB Hi Fi. 

    Landowners still have the right to bar use of the devices which means that LA airport is persona non grata for all those Aussies taking their Hoverboards on holiday, though you will have a problem passing them off as baggage as the Lithium batteries that Hoverboards use are banned by a lot of airlines, including Qantas. 

    If Gay was serious about winning over younger voters and those who actively engage in adventure sports and fitness activities, Gay obviously doesn’t partake of such activities, he would have seriously considered this issue instead of delivering his verbal spray on the issue of Hoverboard use. 

    What he has done is come over as an old fart, a Minister who is out of touch with technology and where technology is going.

    I seriously suspect that he is one of those Ministers that struggles to use a smartphone let alone understand the technology behind a hoverboard that is no more dangerous than a person on a pushbike, especially those who ride bicycles along pavement.

    Here we have Prime Minister Malcolm Turnbull talking about innovation and technology. Then we have young Wyatt Roy who is keen to promote technology, innovation and products like Hoverboards.


    As for Gay he will spend Xmas counting the millions flowing in from speed cameras that snap one doing 55klm an hour in a 50 klm zone.
     

    Qantas To Merge With British Airways

    Only days after Geoff Dixon retired as CEO of Qantas CNN has reported that Qantas is set to merge with British Airways a former major shareholder in the Australian airline.

    CNN is reporting that British Airways has said  it was in talks with Australian rival Qantas that could see a merger of two of the world’s most prestigious airlines.

    BA says it is in talks with Australian rival Qantas.

    BA says it is in talks with Australian rival Qantas.

    London-based BA said the exploratory talks would look at creating a dual-listed company but offered no other details.

    “There is no guarantee that any transaction will be forthcoming and a further announcement will be made in due course if appropriate,” BA said in a statement.

    BA said the talks would not affect its negotiations in Spanish airline Iberia, with which it opened merger talks earlier this year. 

    The tech savvy airline British Airways has a lot to gain from a merger with British Airways analysts are reporting as both airlines have significant investments in providing services between Europe and Australia.

    Now under the leadership of Irishman Alan Joyce the former CEO of budget airline Jetstar the merger comes at a time when the Australian dollar is $0.63 to the US dollar.

    Earlier today Reuters reported that Qantas will remain majority Australian-owned and Singapore Airlines  will stay shut out of lucrative Australia-U.S. routes under a new government aviation blueprint.

    A discussion paper for the industry, to be released on Tuesday by the government, would keep the existing cap on foreign ownership of Qantas at 49 percent, Transport Minister Anthony Albanese told state radio.

    “The 51 percent Australian ownership is maintained under the Qantas act. We think there should be a level playing field apart from that,” Albanese said.

    The Australian newspaper said the proposals also include removing a 25 percent limit on individual foreign shareholdings in Qantas and a 35 percent total limit on foreign airlines’ holdings in the carrier,

    More to follow.

    PR Spin Can Sometimes Do A Lot Of Damage

    PR manipulations seems to be flavour of the day among technology vendors, who on one hand want to milk PR exposure from technology publications by offering up reviews and new product launch stories, but when there’s a sniff of a problem they all of a sudden, become PR shy.

    This week Hewlett Packard tried to spin the local tech media by not issuing a local press release for the recall of over 20 notebook batteries that could burst into flames.

    Announced to the US media on May 14th, some five days ago, HP chose not to make the PR announcement in Australia despite several of the notebooks being on sale in Australia.

    Their argument “We thought you would pick it up from the US press release”.

    Really, It was only 18 months ago that Guyon Collins a senior marketing manager at HP was complaining to SmartHouse because we dared to feature a product that had been exposed in a US press release before it was launched in Australia.

    He also complained that we had featured a product that “may or may not be launched in Australia”.

    PR is a wonderful marketing tool, but a right bastard when it goes horribly wrong as Jenny Geddes, the Communication Manager at Sony is now realising.

    Geddes, who use to work for Burson  Marsteller, who are also HP’s PR advisors,  got her knickers in a twist over a story about the kidnapping of the CEO of France by Sony staff and the implementation of Sony security in Australia.

     Screaming down the phone she demanded that we remove the story because in her words “It’s not relevant to Australia”.  We chose not to. The screaming fit came only 4 weeks after the CEO of Sony Entertainment threatened us with legal action for daring to accuse SCE of price gouging with their overpriced Playstation’s.

    Several days later Sony decided to ban 4square from press events and PR information.

     

    Geddes hissy spat, came only days after Sony Australia had sacked 32 people in Australia with a 98 word email to journalists, ironically the sacking press release was was only issued to selective journalists and only because ChannelNews and the Australian newspaper leaked the fact that layoffs were about to be made at Sony Australia.

    I, for one, wanted answer’s from Sony and I did not want a PR flack like Geddes, spinning me a positive yarn. I wanted to hear from the same senior Sony management who are always available for a new product launch, the role out of a soccer sponsorship deal or the pumping of numbers when Sony was doing well.

     I wanted to know why Sony was sacking 32 people when competitors like Samsung and Panasonic were hiring people to handle growth. I also wanted to know about the performance of the company locally and whether return to Australia of CEO Carl Rose was now having an impact on the business with the introduction of savage cost cutting.

    Last week, Sony announced losses of over $2.8 billion dollars and Panasonic losses of $5 billion, the big difference was the availability of Steve Rust the CEO of Panasonic Australia, who not only got his PR advisors to contact me but talked openly about the losses that Panasonic globally were experiencing as well as the performance of the local subsidiary.

    Maybe Sony don’t want to talk about their local performance because they are doing poorly. I don’t know. But what I do know is the PR is a two way relationship and that media organisations like SmartHouse or ChannelNews are not here to be manipulated by a PR puppet like Geddes and the other PR hacks at Sony. We are here to work with vendors to impart information to both sellers of technology and the buyers which, in the case of the SmartHouse web site, will be in excess of 3.5 Million unique visitors this year.

    Ironically, Sony has four in-house PR staff and several external PR advisors Vs one each for Samsung, LG, and Panasonic.  

     

    For the last four years, Sony has spun yarn after yarn, about the so called success, of their Bravia LCD TV’s, Playstation consoles, digital cameras and camcorders  but when it was revealed recently that not one of these product categories was making money and had not done so, for many years we started to ask why?

    Call after call and email after email, was ignored by Sony in an attempt to shut us up and internally hope that we would go away, or even forget the story.

    What most PR practitioners in Australia have not realised is that the Internet has changed game plans. Media outlets want news today not tomorrow. It’s not a case anymore of sacking 32 people today and then maybe if they feel like or after gauging the media response make an executive available for comment days later, which is what I suspect Sony were trying to do with 4Square Media.

    Web sites like ChannelNews and SmartHouse are a cross between tabloid journalism and a gladiator competition. Every day we go fishing for eyeballs and a key ingredient is fast breaking stories, which in the case of SmartHouse, attract the attention of the Google search engines.

     

    For example, one Sony story last week got over 100,000 unique visitors 89% came from a search of Google and the insertion of the word Sony into the Google search engine.

    The Internet has become the largest media outlet in the world, yet PR Company after PR Company don’t grasp the speed with which a story can break, grab eyeballs on Google and the die because a better, newer story has come along.

    We still get print press releases and black and white picture which in the case of SmartHouse go straight in the bin because quite simply we don’t have the time to repurpose text that has already been written once

    This massive medium has spawned a new era where press released have to be focused and PR companies act a lot more openly than what the likes of Sony and HP are doing.

    Because if they don’t, the blog, the internet and the really pissed off consumer will get them for the whole world to see. And that includes ChannelNews and SmartHouse.

     

     

    Sonos, Netflix + Spotify Smash Onto CoolBrands Top 20 List

    When it comes to hip cool brands Netflix, Sonos and Spotify have pushed out yesterday brands such as Sony, Bang + Olufsen and Bose in this year’s CoolBrands Top 20.

    The fact that Sony, Bose + Bang and Olufsen are seen as old technology is not surprising said analysts. 


    Spotify was the highest new entrant in this year’s CoolBrands Top 20, stealing 11th place, while Netflix and Instagram were fifth and seventh, making the top 10 for the first time.

    Young brands like Netflix and Instagram are showing clear momentum and posing a threat to established sector peers.
    Sonos, the maker of the wireless multi-room speaker systems and a pioneer of the connected home, also joined the index, while high-end home technology designer Bang & Olufsen fell five notches to 16th place and Sony dropped out of the ranking altogether. 

    Other luxury brands including Dom Pe?rignon, Rolex, Bose and Selfridges were also knocked out of the top 20.

    Apple, which had fans queuing for days last week to be among the first to get their hands on the newly released iPhone 6s and 6s Plus, retained the top spot for the fourth consecutive year.

    “Attaining Top 20 CoolBrands status takes time and isn’t the result of a one-year fad or flash in the pan,” said Stephen Cheliotis, chairman of the CoolBrands Council.

    “Young brands however, like Netflix and Instagram, are showing clear momentum. They are moving up the Top 20 at a decent pace and posing a threat to established sector peers, suggesting they’ll challenge the leading brand overall,” he said.

    While Stella McCartney, last year’s 20th coolest brand, lost its place on the index, rival British fashion house Alexander McQueen rose seven slots to rank sixth. 

    High street sports brands fared well amid a British resurgence in fitness activity, with Nike taking fourth place and Adidas joining the list at number 18. Whole Foods Market also entered the index this year, taking 15th place.

    The CoolBrands Top 20, now in its 14th year, is compiled from a longlist of 1,450 brands based on the opinions of 2,500 consumers and a judging panel. Brands cannot apply for consideration or pay to be included.

    JB Hi Fi In Restrictive Practises Strife With ACCC

    Leading consumer electronic retailer JB Hi Fi is in strife with the Australian Competition and Consumer Commission after allegations of restrictive practises trade practices in Victoria.

    Leading consumer electronic retailer JB Hi Fi is in strife with the Australian Competition and Consumer Commission after allegations of restrivive trade practices in Victoria.

    The Australian Competition and Consumer Commission claim that they have accepted a court-enforceable undertaking from JB Hi Fi Limited after concerns about the arrangements it made with a small retailer in Ballarat to close its store. Before mid 2007 JB Hi Fi approached (I Can’t Get No) Satisfaction Pty Ltd, a retailer of music in Ballarat, to buy its business. The parties agreed on a sale price with JB Hi Fi intending to trade from Satisfaction’s premises.

    However, JB Hi Fi decided that Satisfaction’s premises were too small, so the parties executed a restriction agreement. This required Satisfaction to close its store by a specified date and arrange with its landlord not to re-let the premises to another retailer of CDs/DVDs or games for 12 months. The day after Satisfaction closed its store, JB Hi Fi opened its new Ballarat store.

     

    The ACCC was concerned that by JB Hi Fi requiring Satisfaction to stop trading, JB Hi Fi may have contravened section 45 of the Trade Practices Act 1974, which prohibits making of contracts, arrangements or understandings that restrict dealings or affect competition. In particular, the ACCC was concerned that the agreement may have been an exclusionary provision within the meaning of section 4D (exclusionary provisions) of the Act.

    JB Hi Fi has provided a court-enforceable undertaking under which it has agreed that it will not, for three years, enter into any contract, arrangement or understanding with any person with whom it is (or is likely to be) in competition to ensure the person will cease trading.

    On 5 December 2006 JB Hi Fi provided a court-enforceable undertaking to the ACCC after concerns were raised by the ACCC under the consumer protection provisions of the Act. In that undertaking, JB Hi Fi agreed to establish and implement a trade practices law compliance program designed to minimise JB Hi Fi’s risk of future contraventions of the misleading and deception conduct provisions of the Act.

     

    In its most recent undertaking, JB Hi Fi has undertaken to extend its compliance program to include the restrictive trade practices provisions of the Act.

    “The present matter underlines the need for companies and their legal advisors to take care in how they structure their arrangements so that an otherwise legal transaction does not move into a possibly illegal one,” ACCC Chairman, Mr Graeme Samuel said. “A simple legal sale of business in this instance was varied into a form more akin to an agreement between competitors to cease competing in Ballarat.”

    A copy of the undertaking given by JB Hi Fi will be available on the ACCC’s website, under Public Registers.

    Yesterday it was announced that JB Hi-Fi is set to roll out 150 branded JB Hi Fi stores during the next 5 years. This is up from their previous target of 120.

    The current plan according to Chief executive Richard Uechtritz will see 13 to 15 stores rolled out each year. The Company is also investing heavily in an online presence to deliver not only an opportunity for consumers to buy online but to identify whether  an individual JB HiFi store has in stock a product a consumer wishes to buy.

     

    “This information research shows, is more likely to drive a consumer to a bricks and mortar store than one without a “live” web site. 

    JB Hi-Fi said the 150 stores are expected to be of a similar size and sales volume as the existing stores.

    The Company is also investigating the opening of smaller format stores with similar product categories in smaller consumer catchment areas.

    Chief executive Richard Uechtritz said the addition of new stores in Melbourne combined with expansion in smaller centres such as Ballarat and Townsville had extended the property opportunities available to the company however he has warned that in rural Australia there is limited expansion.

    “Several of our competitors are trying to get growth in rural location and we believe this will be one of the hardest hit if there is a downturn. We believe that we can also service this part of Australia online”

    In an interview with Live News he said” “Close to half our stores are still to complete the three-year maturity ramp up and with so many new store opportunities we remain very excited about the growth opportunities over the coming years.”

    Mobile Apple Phone Coming Soon

    Apple is set to launch a brand new mobile phone that will featuring music, video, email, and Internet functions. It will run on a unique Apple network called Mobile Me.

     Apple Computer has requested a set of trademarks for a mobile telephone service featuring music, video, email, and Internet functions, according to applications at the US Patent and Trade Office.

    The maker of the iPod music players filed this month to trademark the name ‘Mobile Me,’ for devices and services combining features of the iPod with Motorola’s ROKR telephone and the Blackberry portable communications device.

    Appled has asked the patents office to lock in the ‘Mobile Me’ name for handheld devices as well as accompanying mobile telephone service, according to the trademark applications. The telephone service would provide ‘digital music from local or global communications networks’ as well as online databases ‘in the fields of music, concerts, videos, radio, television news’ and more, the applications state.

    maker of the iPod portable music player, could be planning to launch its own mobile-phone venture, recent federal trademark filings indicate.

    The filings reinforce speculation that Apple would wade deeper into mobile phones in the wake of a partnership with Schaumburg, Ill.-based Motorola (NYSE: MOT) , the world’s second-largest mobile phone maker.

    Motorola’s Rokr phone, introduced last year, was the first to feature Apple’s popular iTunes digital music store. The phone has been criticised for inadequacies, but it has still underscored the growing importance of music to mobile phones.

     “I think they will have a device and an MVNO,” said Albert Lin, an analyst with American Technology Research. MVNO is short for “Mobile Virtual Network Operator.” MVNOs don’t own physical networks; instead, they buy wireless time from major networks like Sprint Nextel, and operate under their own brand.

    An MVNO would be a good way for Apple to spur downloads of songs from iTunes through a wireless network, Lin said: “They have to find a way to get over-the-air downloading of iTunes.” The first iTunes phone doesn’t have that capability; users can only download songs directly from their personal computers.

    By operating its own MVNO, Apple would have more control over distributing and pricing its music services than it would in a traditional relationship with a wireless carrier. “They have to take a more proactive role in developing the [over-the-air] market,” Lin said. Apple’s iPod, known for its style and functionality, has become a consumer electronics icon. The Rokr phone was criticized for lacking the iPod’s style and for holding only 100 songs, about 900 less than the new iPod Nano.

    If Apple chooses to make its own phone, it will likely contract out much of the engineering to a firm that specialises in mobile phones, said Ed Snyder, a stock analyst with Charter Equity Research. One Company tipped to pick up the contract are BenQ an OEM manufacturer that recently aquired the Siemens brand. during the recent CES event in Las Vegas a senior BenQ executive did admit that they were talking to Apple about OEM manufacturing. Snyder doesn’t see an Apple phone as a threat to Motorola or other established mobile phone makers. “The mobile phone business is enormously complicated,” he said.

    Phones are primarily sold through carriers. Carrier/manufacturer relationships can be tricky. Lin also said he didn’t see an Apple phone venture as a threat to Motorola: “I think Motorola would view it as positive.” Apple might market an MVNO in tandem with a Motorola phone. And Motorola is likely looking for a better outcome from its Apple relationship than it has gotten from the first Rokr phone, Lin said

    Samsung D600 Given Makeover

    UPDATED: Samsung has given their D600 a new paint job by chrome-ing its curves. But it wont fix the problems on the inside.

    The Samsung D600 is one of those phones that reminds of that great piece of fruit that looks sensational on the outside but when one sinks your teeth into it you find out that it’s rotten on the inside. Now in Chrome the Samsung D600 is a 2 megapixel sliding cameraphone with Bluetooth. It has a large 88 MB memory capacity, which Samsung claims is enough to store 1000 megapixel photos or 20 of your favourite songs in MP3 format.This phone does look great with its easy slider big keys and a bright screen, but it is let down by lousy Samsung PC Studio software that makes connecting to Outlook difficult which ever way one tries. Then there is the issue of entering data into a contacts database.

    There is no space for an address and no space for a business title. Maybe the Korean designers have never been on the road doing sales calls and have to access a phone to check an address. Key today in any phone purchased by a business executive is the ability to easily access Outlook and download contacts. With the D600 we constantly got an error message that said “The connection to the Microsoft Exchange server is unavailable. Outlook must be online or connected to complete this action”. In the testing that we did, Outlook was  connected, yet despite this it was impossible to easily connect to the Microsoft Exchange Server both live in a corporate network where Outlook is always connected or in a stand alone setting from my home PC. 


    Click to enlarge

    Then there is the issue of downloading music. This phone is slow, real slow. To download 10 songs that were on average three minutes in length took more than 45 minutes.

    Another problem I found was that a user cannot listen to music and write notes at the same time. A visit to several comment Websites revealed the following complaints about the Samsung D600. All the comments came from consumers who have purchased the phone. They said:

    No airplane mode “I’ve tried everything to try and turn the cellular functions off so I can just use the mp3 player but to no avail”. Delayed ring tone “The mp3 ring tones have a slight delay before they are audible. I don’t know if the secret menu can be tweaked to fix this problem”.

    No vibrate & ring at the same time – “Sometimes I have it in my pocket in a busy place and I don’t hear it ring. It would be great if it could vibrate at the same time.

    No silence button – It says that if I press a certain button it mutes the call, but it only rejects the call even when I change the option to mute the call”. No automatic save and send SMS. Cannot assign mp3 ring tones to SMS tones and can’t change volume of the message tone (unless you use the secret menu option). No multi tasking – “you can’t listen to the mp3 player while you are text messaging someone or receiving a text message”.

    The feature set for this phone is very impressive. There’s a Trans-Flash memory slot for upgrading the memory to 512 MB. It has stereo speakers, which compliment it’s ability to playback MP3 music files and MP3 ringtones. It’s a tri-band phone with Java support for games and other applications plus PC connectivity and synchronisation by Bluetooth or USB data cable.

    So if you want a mobile phone that looks great and will knock the socks off any other phone in the looks stakes the answer is the D600. But if you are looking for functionality, forget it.


    Click to enlarge

    Samsung D600

     

    Price: Changes with carriers

    Rating: 2/5