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; } } Archive Archives - Smart Office https://smartoffice.com.au/category/archive/ Wed, 22 Apr 2020 01:37:58 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 CA Rejigs Industry Code https://smartoffice.com.au/ca-rejigs-industry-code/ https://smartoffice.com.au/ca-rejigs-industry-code/#respond Wed, 22 Apr 2020 01:37:58 +0000 http://smartoffice.com.au/?p=97686 SYDNEY: The Sydney-based Communications Alliance, which claims to provide a unified voice for the Australian comms industry, has revised its industry code to simplify and improve provision of information for customers with special requirements for communications equipment for the hearing or vision impaired.  The revised code enables equipment suppliers to make details of their equipment ... Read more

    The post CA Rejigs Industry Code appeared first on Smart Office.

    ]]>

    SYDNEY: The Sydney-based Communications Alliance, which claims to provide a unified voice for the Australian comms industry, has revised its industry code to simplify and improve provision of information for customers with special requirements for communications equipment for the hearing or vision impaired. 

    The revised code enables equipment suppliers to make details of their equipment available through just one channel: the Mobile & Wireless Forum’s Global Accessibility Reporting Initiative (GARI).

    The code has been registered by the ACMA, making conformance mandatory.

    Consumers can visit the Accessible Telecoms Web site, accessible.telecoms@accan.org.au, for information on telecommunications products suitable for people with disabilities and specific communications needs. – Stuart Corner.

    The post CA Rejigs Industry Code appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/ca-rejigs-industry-code/feed/ 0
    Harvey Norman Profits Crash 57% https://smartoffice.com.au/harvey-norman-profits-crash-57-2/ https://smartoffice.com.au/harvey-norman-profits-crash-57-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/harvey-norman-profits-crash-57-2/ Harvey Norman profits have slipped 57% to $99 million and that the outlook does not look good going forward. In comparison JB Hi Fi reported a 40% incrrease in profits and a 26% increase in sales.

    The post Harvey Norman Profits Crash 57% appeared first on Smart Office.

    ]]>
    Harvey Norman profits have slipped 57% to $99 million and that the outlook does not look good going forward. In comparison JB Hi Fi reported a 40% incrrease in profits and a 26% increase in sales.

    Harvey Norman profits have slipped 57% to $99 million and that the outlook does not look good going forward. In comparison JB Hi Fi reported a 40% incrrease in profits and a 26% increase in sales.

    Chairman Gerry Harvey said that the first-half had been market by unprecedented market turbulence and that trading conditions in the second-half remained challenging however the Group was operating well he said and its core operations remained strong and resilient.

    “We are confident of sustainable growth across all of our brands and the property portfolio through sound strategic and financial management during the current period and in preparation for improved economic conditions,” he said.

    “Our integrated retail, franchise and property system and the resilient strength of the franchising operations segment has the consolidated entity very well placed for the future.”

    However, the company noted that retail conditions in Ireland remained stagnant and said it had taken a $17 million charge against the business.

    Returning to earnings, Mr Harvey said net profit from underlying business was down 29% on the previous corresponding period, however argued that this should be viewed in light of the retail boom conditions experienced during HY 2007.

    The company, which has been shuttering stores because of the slump in consumer retail spending, said sales revenue rose to $770 million from last year’s $765 million.

    The post Harvey Norman Profits Crash 57% appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/harvey-norman-profits-crash-57-2/feed/ 0
    Maxtor Armoured Drive For Total Data Protection https://smartoffice.com.au/maxtor-armoured-drive-for-total-data-protection-2/ https://smartoffice.com.au/maxtor-armoured-drive-for-total-data-protection-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/maxtor-armoured-drive-for-total-data-protection-2/ The new portable hard drive from Maxtor will provide you with government-grade security, thanks to its encrypting storage solution.

    The post Maxtor Armoured Drive For Total Data Protection appeared first on Smart Office.

    ]]>
    The new portable hard drive from Maxtor will provide you with government-grade security, thanks to its encrypting storage solution.


    Click to enlarge
    Named BlackArmour, this new device claims to provide AES government-grade encryption solution that protects against ‘unauthorised access to valuable and private information.’

    Using Seagate Secure technology, Maxtor’s BlackArmour drive is designed to keep data locked up and protected in the event of loss or theft. Seagate Secure technology is a hardware-based encryption, making the encryption transparent to the user and free of complicated installation and use procedures required by software-based security.

    This device provides transparent, real-time encryption of all that data on the device, not just selected files; providing performance and ease of use advantages over manual software-based security controls. The BlackArmour product also puts all security keys and cryptographic operations within the device, delivering protection against hacking and tampering.

     

    Senior Analyst of Information Security at Enterprise Strategy Group, John Oltsik said, “Government regulations on organisations that manage confidential and personal information continue to get more stringent, making security of sensitive information a mission-critical requirement. Unfortunately, this is a monumental set of tasks that organisations are faced with, when confidential data is created, copied, and stored across the enterprise at an ever-increasing rate from data centre systems to desktop and mobile devices.”

    Seagate Asia Pacific’s vice President and managing Director, BanSeng Teh said, “Maxtor storage solutions are focused on security and back up of your valued digital assets. BlackArmour is an innovative new product that delivers on the promise of providing our customers with a level of security that is both reliable and robust, for a plug-and-play, easy-to-manage storage device.”

    Availability and Pricing:

    The Maxtor BlackArmour will be available in 160GB and 320GB and will have an RRP of $179 and $259, respectively.

    The post Maxtor Armoured Drive For Total Data Protection appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/maxtor-armoured-drive-for-total-data-protection-2/feed/ 0
    3Com & Westcon Divorce Over Direction Issues https://smartoffice.com.au/3com-westcon-divorce-over-direction-issues-2/ https://smartoffice.com.au/3com-westcon-divorce-over-direction-issues-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/3com-westcon-divorce-over-direction-issues-2/ 3Com Corporation, a leading provider of secure converged networking (SCN) solutions and Westcon Group, an IT distributor specialising in networking technology, solutions for convergence, security and storage, have announced that they have mutually agreed to terminate their partnership agreement in Australia, expected to take effect by the end of August.

    The post 3Com & Westcon Divorce Over Direction Issues appeared first on Smart Office.

    ]]>
    3Com Corporation, a leading provider of secure converged networking (SCN) solutions and Westcon Group, an IT distributor specialising in networking technology, solutions for convergence, security and storage, have announced that they have mutually agreed to terminate their partnership agreement in Australia, expected to take effect by the end of August.

    Wendy O’ Keeffe, managing director of Westcon Group in Australia and New Zealand, said, “Westcon Group has enjoyed a successful long-term relationship with 3Com in Australia. As we continue to refine our local and global strategy, it is important that we align our portfolio around key vendors that are both synergistic with our core competencies and deliver consistent growth and profitability for Westcon Group and our channel partners.  We wish 3Com all the very best for the future.”

    Grant Howe, country manager, 3Com Australia said of 3Com,  “They have made a strategic decision to re-focus their portfolio of offerings, and we feel that it is best for us to jointly terminate the agreement.”

    As part of a more focused channel strategy, 3Com Australia is investing additional resources to support and further strengthen its channels in Australia.  It has already begun to dedicate additional channel resources in the country and will announce a new distributor in the coming weeks, it said in a statement.

     

     

    The post 3Com & Westcon Divorce Over Direction Issues appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/3com-westcon-divorce-over-direction-issues-2/feed/ 0
    Forget GST Harvey, Margins Our Big Worry: Dick Smith https://smartoffice.com.au/forget-gst-harvey-margins-our-big-worry-dick-smith-2/ https://smartoffice.com.au/forget-gst-harvey-margins-our-big-worry-dick-smith-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/forget-gst-harvey-margins-our-big-worry-dick-smith-2/ Forget the GST crisis Gerry Harvey - retailers have bigger fish to fry says its rival.

    The post Forget GST Harvey, Margins Our Big Worry: Dick Smith appeared first on Smart Office.

    ]]>
    Forget the GST crisis Gerry Harvey – retailers have bigger fish to fry says its rival.

    Competition and ever tighter margins are just some of the problems ailing Dick Smith and other major retailers, says Woolworths boss Mike Luscombe who also owns the electronics outfit and Big W. 

    Larger margins retailers enjoyed for years is also a thing of the past thanks to the strong Aussie dollar and intense competition between retailers and pressures from online are all driving profits south, forcing year-round sales and ‘special offers’ in stores.    

    Woolworths said that while BIG W had produced a solid EBIT for the first half it is expected to be down on last year, while the Dick Smith business is currently being re-positioned and old stores were not performing as well their new “transformation” stores, in a report issued to the ASX yesterday.        

    ”The Australian dollar means everything’s cheaper to buy,” he said announcing the sales figures for the company.  

    ”There is intense competition to sell those products in the Australian market place and that has driven prices down even further and it’s just meant that the profit that you made out of selling a TV is less than you made last year.

    ”The selling price is down by some 30 per cent. More and more they are only sold on special. There’s no doubt we are all finding it difficult to get that growth margin.”

    And online is the in-place to be and its where the consumers at, says the self proclaimed techxpert, affording benefits in the back-room and at the till.      

     
    ”You don’t have to carry the stock. To sell one TV online you need one TV in stock but to sell one in 400 stores you need 400. 

    So the mathematics of the working capital are far better. It’s the way that a lot of people want to shop.”

    The chain are planning to unveil a web portal in a bid to lure even more consumers towards their e-store offering. 

    Web sales has already proved a winning formula for Dick Smith who in August last reported a 116 percent jump in sales.        

    He also admitted discount retailer Big W was feeling the pressure and further price reductions were necessary to drive sales. 

    ”We’re not getting the dollars out of customers.       

    We are selling things much cheaper than last year, 6 or 7 per cent.”

    The post Forget GST Harvey, Margins Our Big Worry: Dick Smith appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/forget-gst-harvey-margins-our-big-worry-dick-smith-2/feed/ 0
    Review: New Lexmark S815 MFP Design Icon or Good Printer? https://smartoffice.com.au/review-new-lexmark-s815-mfp-design-icon-or-good-printer-2/ https://smartoffice.com.au/review-new-lexmark-s815-mfp-design-icon-or-good-printer-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/review-new-lexmark-s815-mfp-design-icon-or-good-printer-2/ Laser printers are in big demand and as sizes shrink and functions grow, Lexmark has gone one step further with a printer that is very much a design statement for the desk. But the big question is does the S815 stack up as a good all round printer?

    The post Review: New Lexmark S815 MFP Design Icon or Good Printer? appeared first on Smart Office.

    ]]>
    Laser printers are in big demand and as sizes shrink and functions grow, Lexmark has gone one step further with a printer that is very much a design statement for the desk. But the big question is does the S815 stack up as a good all round printer?

    When you open up the box of this all new Lexmark Genesis printer, you’re either going to love it or hate it. There’s no in-between on this clash of interests between design and practicality. The functionality and inventiveness is all there in more ways than one, but everything from the unconventional shape to the subverted angles show that Lexmark must have put more time into pushing design limits than supporting functionality.

    The Genesis S815 features scanning times as quick as three seconds through an ingeniously simple idea that dramatically speeds up the everyday scanning process, while still retaining vivid colour and picture quality. Scanning and printing on the fly will reproduce near-perfect copies on the right kind of paper, with high resolution detail clearly visible. Colours on plain paper are washed out from absorption while text is only less sharp if you look obsessively close at the page. Images come out pretty saturated but still high quality for anyone with an eye for detail. Wireless capabilities provide online interaction that lets users send these images they scan straight off to sites like Evernote and Photobucket without using the computer as a middleman.

     

    This is one part of the multi-faceted online capability of SmartSolutions, Lexmark’s customisation tool for the Genesis. Working like an App Store, the Lexmark website offers a Solution Library which pulls up a list of shortcuts and applications to run on the printer’s touch screen. Once you sign up to SmartSolutions, simply touching any ‘+’ symbol will launch the Library on your web browser where users can choose everything from sheet music templates to clock and calculator widgets to give their Genesis the personal touch for whatever they use most.

    On that note, the capacitive touch screen is a gorgeously smooth addition compared to the usually resistive and unresponsive screen retrofitted into most older printers, now joining the ranks of printing powerhouses like HP – only that with Lexmark, menu customisation, fluid menu control and extreme simplicity and ease-of-use push it a step ahead of the game (or on par with HP’s Photosmart eStation).

    The multifunction centre also features USB and SD/MS/xD/MMC connections alongside Wi-Fi and TCP/IP connectivity, along with fax machine integration.

     

    Earlier last month, Lexmark’s Director of Worldwide Product and Solutions Marketing, Bill Lucas told SmartHouse that “instead of looking at a piece of technology and asking ourselves what we could do with it, we ask users what they want on their printers.”

    Apparently users want their printers looking more like their old CRT TV than an actual printer.

    Fair enough, the design comes very subjectively and many may like monolithic stature that defies the typically boring, eggshell/grey-white box printer, but some of the design elements impede on practicality. Take the scanner, for example: the front panel that features the touch screen doubles as the lid of the scanner. Not a problem for scanning photos, cards and documents, but a major problem if you’re trying to scan anything as large as an encyclopaedia or bigger. The lid opens from near vertical alignment to around 45 degrees with a few centimetres of give for thicker documents, but thick books or boxes can’t always fit flush against the scanning screen as they would on a face-down flatbed scanner.

    If you do manage to fit your larger items into the scanner with the lid open, you’ll then come across the wonder of bending down to use the absentmindedly-placed touch screen that is now facing the floor rather than the user. Even though scanning pages and documents is a breeze, the design compromises any further love for this misunderstood device.

    The Lexmark Genesis S815 runs at $449 from participating Harvey Norman, Domayne & Joyce Mayne outlets.

    The post Review: New Lexmark S815 MFP Design Icon or Good Printer? appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/review-new-lexmark-s815-mfp-design-icon-or-good-printer-2/feed/ 0
    Online Shopping Risky This Season https://smartoffice.com.au/online-shopping-risky-this-season-2/ https://smartoffice.com.au/online-shopping-risky-this-season-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/online-shopping-risky-this-season-2/ Online shopping is convenient, but risky, and the Government has issued a warning to consumers on the perils of online shopping this Christmas season.

    The post Online Shopping Risky This Season appeared first on Smart Office.

    ]]>
    Online shopping is convenient, but risky, and the Government has issued a warning to consumers on the perils of online shopping this Christmas season.

    Minister for Home Affairs And Justice, Brendan O’Connor, and the Minister for Broadband, Communications and the Digital Economy, Senator Stephen Conroy warned Australians to take some simple precautions while shopping in cyberspace and protect their personal information over the net.

    Its cybersecurity website provides information for Australian internet users on what they need to do to protect personal information online.

    O’Connor said:  “There are precautions that consumers can take to reduce the risk of credit card fraud, such as using anti-virus software and checking credit card statements regularly.”

    Simple steps to protect your computer, yourself and your family online this festive season include:
    – Shopping at secure websites by researching the merchant before placing an order and saving all transaction details.
    – Be wary of seasonal e-cards or emails from suspicious senders, including those described as ‘friend’, misspelled words, or strange and vague subject lines.
    – Never click on links in emails from people you don’t know, even from what may appear to be trusted sources. Banks will never ask for personal details such as PINS or passwords by email
    – Don’t share your full name, date of birth, address or phone number with people or sites that you don’t know or trust.
    – Install security software and update it regularly. Turn on automatic updates so that all your software receives the latest fixes.
    – Get a stronger password and change it at least twice a year.
    – Keep an eye on what your children are doing online and encourage them to report anything suspicious.

    You can also find more information on cybersecurity at www.staysmartonline.gov.au. A booklet entitled “Protecting Yourself Online – What Everyone Needs to Know” is also available from cybersecurity@ag.gov.au

    The post Online Shopping Risky This Season appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/online-shopping-risky-this-season-2/feed/ 0
    Union Peddling Lies & Untruths Over A380 Incident Claims Qantas https://smartoffice.com.au/union-peddling-lies-untruths-over-a380-incident-claims-qantas-2/ https://smartoffice.com.au/union-peddling-lies-untruths-over-a380-incident-claims-qantas-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/union-peddling-lies-untruths-over-a380-incident-claims-qantas-2/ The union representing Qantas Licenced Aircraft Engineers appear to have had a lapse in intelligence after they started peddling fear and untruths about the recent Qantas A 330 incident over Indonesia says Qantas.

    The post Union Peddling Lies & Untruths Over A380 Incident Claims Qantas appeared first on Smart Office.

    ]]>
    The union representing Qantas Licenced Aircraft Engineers appear to have had a lapse in intelligence after they started peddling fear and untruths about the recent Qantas A 330 incident over Indonesia says Qantas.


    Desperate to push their case the Union claimed that engineers were set to be stood down because of the incident which saw the entire fleet of Qantas flights grounded after an engine exploded.Qantas claims this is blatent lies  and that ALAEA federal secretary Steven Purvinas is taking advantantage of a situation to “peddle lies”

    Qantas chief executive Alan Joyce said in a statement that Mr Purvinas was wrong to say Qantas engineers has been stood down because of the incident on QF32, which was forced to turn back to Singapore following the explosion.

    He said the cause of the engine failure was still being investigated, but it appeared likely to be a design problem.

    Joyce, said Mr Purvinas was wrong, and that he and the Union had demonstrated yet again that he was prepared to go to any lengths to further his industrial agenda.
    “It is clearly too soon to speculate on the cause of yesterday’s engine failure,” Mr Joyce said.

    “Regardless, Steve Purvinas continues to peddle prejudices and generalisations about aircraft maintenance and safety in the knowledge that his claims will more than likely go unchallenged. “The engineers he has referred to in a number of media interviews today are employed by QantasLink in Brisbane and are involved in ongoing enterprise agreement negotiations. Six employees were directed not to attend work last week, on full pay, while a disciplinary matter is appropriately investigated. This has nothing to do with our A380 fleet.”

    “Mr Purvinas also continues to raise overseas aircraft maintenance as though this was something only Qantas was not allowed to pursue. The overwhelming majority of our aircraft maintenance is undertaken in Australia, and he knows this.

    “We operate an international airline and aircraft that are manufactured overseas so it is inevitable some need to be serviced overseas and that has always been the case.
    “The A380 involved in the Singapore incident recently underwent its first heavy maintenance check by Lufthansa Technik in Germany. Lufthansa is a leading international airline, a top tier engineering and maintenance provider and an operator of the A380 itself. Rolls-Royce Trent 900 engines are overhauled at
    Rolls-Royce facilities.

    “To suggest that Lufthansa and Rolls-Royce do not have the expertise and experience to undertake the highest quality aircraft and checks is ludicrous.
    “All Mr Purvinas is interested in grabbing is a headline, regardless to the damage to the reputation of Qantas and its employees including members of his own union”
    Mr Joyce also confirmed that Qantas met all the requirements of two Airworthiness Directives (ADs) applying to the Trent 900 engine.

    “We take compliance with any Airworthiness Directives extremely seriously,” he said. “Two ADs applied to the Trent 900 engines we use on our A380s. One is no longer relevant to Qantas following an engine modification, and we are fully compliant with the other. Any claim otherwise would be wrong.

    A short while ago Qantas said that the Qantas B747-400 dispatched as a relief flight last night to Singapore to bring passengers affected by yesterday’s QF32 engine failure was scheduled to depart Singapore at 10.30am local time. QF8032 is expected to arrive in Sydney at 8.45pm tonight.

    Qantas continues to provide assistance to customers affected by the temporary suspension of A380 operations, including hotel accommodation, where needed, and meals, as arrangements are made to get people on flights as soon as possible. All available Qantas aircraft capacity is being used and the airline is also in discussions with other carriers regarding aircraft charter options in addition to the QF10 charter listed below.

    Qantas continues to work with Rolls-Royce and Airbus to fully understand the circumstances surrounding the engine failure ahead of taking the first steps toward to resuming operations. It is still too soon to be able to provide an indication of when this might be.

    The post Union Peddling Lies & Untruths Over A380 Incident Claims Qantas appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/union-peddling-lies-untruths-over-a380-incident-claims-qantas-2/feed/ 0
    New Vodafone And 3 Plans Arrive Tomorrow https://smartoffice.com.au/new-vodafone-and-3-plans-arrive-tomorrow-2/ https://smartoffice.com.au/new-vodafone-and-3-plans-arrive-tomorrow-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/new-vodafone-and-3-plans-arrive-tomorrow-2/ Vodafone Hutchison Australia announced that it will introduce a set of new postpaid plans to its Vodafone and 3 Mobile customers tomorrow.

    The post New Vodafone And 3 Plans Arrive Tomorrow appeared first on Smart Office.

    ]]>
    Vodafone Hutchison Australia announced that it will introduce a set of new postpaid plans to its Vodafone and 3 Mobile customers tomorrow.


    Click to enlarge
    New Vodafone and 3 Plans: Part 1 of 2

    According to the company, the new plans have more value, increased mobile data allowance, as well as unlimited calls within the Vodafone and 3 network.

    Vodafone Hutchison Australia’s Director of Marketing, John Casey said, “Vodafone and 3 are determined to lead the market by giving customers the best value for money. It’s great to be delivering even more value at a time when prices continue to rise on most other everyday items.”

    “We’ve designed these caps be used in a way that’s convenient and relevant to our customer’s needs. For customers with friends, family members or business interests overseas, we’ve provided them with the ability to use their cap value towards international calls,” added Casey.

     

    Click to enlarge
    New Vodafone and 3 Plans: Part 2 of 2

    In addition to the increase in cap value, the new Vodafone or 3 Contract Cap from $29 a month will feature the ability for customers to make free unlimited standard voice calls in Australia to friends and family on both Vodafone and 3.

    This free calls offer for Vodafone customers to Vodafone and 3 numbers is currently rolling out and the free calls offer for 3 customers to 3 and Vodafone numbers will launch by the end of July.

    “That’s free standard voice calls to almost six million people in Australia, anytime of the day or night. VHA is thrilled to be leading the way with a simple promise to consumers that if you’re with Vodafone or 3, you’ll get more value for your money,” concluded Casey.

    Click on the screenshot for the new caps launching tomorrow.

    The post New Vodafone And 3 Plans Arrive Tomorrow appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/new-vodafone-and-3-plans-arrive-tomorrow-2/feed/ 0
    BenQ Announces World’s Slimmest LED Monitors https://smartoffice.com.au/benq-announces-worlds-slimmest-led-monitors-2/ https://smartoffice.com.au/benq-announces-worlds-slimmest-led-monitors-2/#respond Thu, 06 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/benq-announces-worlds-slimmest-led-monitors-2/ BenQ has launched two new LED monitors that claim to be the slimmest in the world.

    The post BenQ Announces World’s Slimmest LED Monitors appeared first on Smart Office.

    ]]>
    BenQ has launched two new LED monitors that claim to be the slimmest in the world.

    Click to enlarge
    According to BenQ, the V2420H and V2420HP are the world’s slimmest LED monitors. These new monitors use LED backlighting that consume around 44 percent less power and up to 71 percent less whilst used in BenQ’s exclusive ‘Eco’ mode compared to CCFL monitors. The shell of the new V Series monitors is produced from 28 percent recycled plastic, giving the product a distinct environmental edge.

    In addition, the new monitors offer full 1080p High-Definition (HD) at 16:9 aspect ratio, with images being enhanced with BenQ’s Senseye Human Visual Technology.

    BenQ Australia’s General Manager, Chee Chung said, “The new V2410 provides an amazing 5,000,000:1 ultra-high contrast ratio, while the new ultra-slim 15mm thick V2420 Series provides an amazing 10,000,000:1 ultra-high dynamic contrast ratio.  This equates to picture quality that is brighter and more balanced, but most impressively, they cost significantly less to run than their predecessors.”

    “LED technology is the revolutionary way forward for display monitors and televisions offering a reduction in power consumption, more balanced display properties, a longer lifespan and lighter weight,” added Chung.

    The company is also set to launch the V2410T, a monitor that is height adjustable for added versatility and comfort.  

    The BenQ V2420H, V2420HP, and V2410T are available now for $479.00, $479 (glare panel), and $549, respectively.

    The post BenQ Announces World’s Slimmest LED Monitors appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/benq-announces-worlds-slimmest-led-monitors-2/feed/ 0