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; } } Mendelson Tiu, Author at Smart Office - Page 14 of 72

    Smart Office

    Canon Rolls Out Wireless Printers

    In addition to its new DSLR and compact camera range, Canon Australia has unveiled three new wireless multifunction printers as well as a single function printer for document and photo printing.

    The Canon Pixma MX870, MX350 and MX340 allows a user to print, copy, scan and fax from the device. These new printers offer wireless connectivity, which means users can scan and print from multiple PCs. In addition, its Easy-PhotoPrint EX application for the iPhone allows a user to print photos straight from their phone to the printer.

    Other features include Automatic Document Feeder (ADF), Easy-WebPrint EX software which makes printing documents from the web more effective, and Auto Clip feature.  Users will also enjoy the intuitive design, simple menu navigation and new enhanced security features that enable the effortless creation of password-protected PDFs.

     

    Also launched was the Pixma iP2700 – an entry- level single function printer offers a wide array of advanced features including Auto Photo Fix II and Easy-WebPrint EX to enhance the quality of print output. It offers borderless printing up to A4 size and ChromaLife100+ ink system which provides more vibrant and longer-lasting photos.

    Canon Australia’s Brand Manager – Pixma, Beryl Thomas said, “These stylish new PIXMA inkjet printers help save precious space in home office environments while improving productivity. Easy to use, the new PIXMA models enable users to improve overall workflow by completing all their output tasks in a quick and straightforward manner while maintaining the required professional standard.”

    According to Canon, the PIXMA MX870, MX350, MX340 and iP2700 come with an Auto Photo Fix II software that resolves many common photo printing errors, such as underexposed images, through Multi-Zone Exposure Correction and improvements in overall face detection, scene analysis, and brightness and saturation correction.

    The Canon PIXMA MX870 (RRP $TBC), MX350 (RRP $TBC), MX340 (RRP $TBC), and iP2700 (RRP $TBC), will be available from March 2010.

    All-In-One Fuji Printer Cuts Costs

    Fuji Xerox unveiled two new monochrome multifunction printers that claim to cut IT costs and carbon footprint.


    Click to enlarge
    The WorkCentre 3210/3220 can print, copy, scan and fax from a single compact device, is Energy Star compliant, and has an adjustable Power Save Mode that allows users to control the device’s power consumption. 

    The WorkCentre 3220 also supports automatic two-sided printing and has a Toner Save mode that allows a user to print in a draft mode.

    Fuji Xerox claims that the WorkCentre 3210 prints up to 24 printed pages per minute while the WorkCentre 3220 prints up to 28 printed pages per minute, with a First Page Out Time as fast as 8.5 seconds. Its multitasking capabilities support a busy work environment by allowing users to scan a file even while other jobs are being printed.

     

    Brad Monsbourgh, Marketing Manager for Fuji Xerox Printer Channel Australia and New Zealand, said, “The WorkCentre 3210 and 3220 demonstrate that sustainability and cost efficiencies can go hand in hand.  By having features that will both reduce the use of resources and offer a high level of productivity, Fuji Xerox is helping businesses manage their IT costs better and at the same time, reduce their carbon footprint.”

    The colour scanning capabilities in the WorkCentre 3210/3220 will facilitate the implementation of digital workflow in organisations.  Users will be able to produce electronic documents for a network / desktop folder or USB drive, or insert scanned images into an application to be emailed to users (WorkCentre 3220 only). This device includes scanning software to assist with the editing and manipulation of files and to organise and distributed scanned files.

    Advanced fax features such as Secure Fax Receive ensure only authorised users can access a fax by requiring a passcode to retrieve a document. The WorkCentre 3210/3220 supports broadcast (multi-send) faxing, fax forwarding, fax speed dialling and even faxing from desktop PCs.

    The WorkCentre 3210/3220 is available now for $699 and $799 respectively.

    Samsung Hits Record Profits

    Samsung has reported a net income of 9.64 trillion won (AU$9.34 billion) for 2009, with the company attributing this increase to strong flat screen TV and mobile phone sales, as well as higher prices for memory chips.Vice President and Head of Samsung Electronics’ Investor Relations Team, Robert Yi, said, “Despite the uncertain business environment in 2009, Samsung was able to achieve record revenues and strong profitability based on our technological and marketplace leadership. We see this positive growth and performance flowing on into 2010 as the global economy continues to stabilise.”

    According to the report, Samsung has recorded revenues of 39.24 trillion Korean won (AU$38.15 billion) on a consolidated basis for the fourth quarter ending 31 December 2009, which is an 18.9 per cent increase year-on-year.

    This fourth quarter result brought Samsung’s full year 2009 revenue to a record 136.29 trillion won (AU$132.15 billion). Its full year 2009 operating profit was 10.92 trillion won (AU$10.59 billion), while its net income on a parent company basis was 9.64 trillion won (AU$9.34 billion).

    Samsung has reported that its strong performance in the fourth quarter was supported by improved pricing for memory semiconductors and the seasonal increase in sales of consumer electronics products.

     

    The company said that its strong semiconductor business performance was driven by a rise in market prices for memory chips and solid demand. In DRAM, spot prices increased by 25-30 per cent from the beginning of the quarter, supported by strong PC sales.

    “Despite traditionally weak seasonality, sales were boosted by demand for high-density chips for smart phones. During the fourth quarter, Samsung also began production of 30-nm-class, 3-bit Multi-Level-Cell NAND chips for the first time in the industry, providing a further technological edge for 2010,” added the company.

    Samsung has also recorded flat panel TV unit sales of 10.88 million, exceeding the 10 million mark for the first time in the industry. The sales record represented a 41 per cent increase year-on-year and quarter-on-quarter. With its new line of LED TVs selling strongly, Samsung was also able to meet its sales target of 2.5 million units for the year.

    Finally, Samsung’s sales of mobile handsets for the quarter reached 69 million, up 16 per cent year-on-year. This enabled the company to comfortably exceed its 2009 sales target of 200 million units in reaching 227 million units for the full year.

    Samsung forecast positive growth across its businesses in 2010, with the continued economic recovery expected to stimulate demand for flat panel TVs, mobile handsets and notebook PCs. The company aims to continue to enhance its cost competitiveness and bolster market leadership across its core businesses.

    $799 Medion Notebook Perfect For The Home Office

    Aldi and Medion have started 2010 with a bang as they launch a 17.3-inch notebook that is perfect for home offices. It can handle office applications without slowing down and can even entertain you with its large screen and loud speakers.The E7212 does not look like its predecessors, with the unit sporting a brushed grey lid and piano black interior (the older models sport a piano black lid with matte silver interior). While the interior looks great, it is very prone to fingerprint marks and smudges, putting off users who want a clean computer.

    Various ports are located on the side of the computer including three USB ports, a microphone, headphone, and audio-in jack, an E-SATA, Ethernet, and Display Port, as well as a 4-in-1 card reader. The unit also has a 1.3-megapixel webcam, microphone, and Wi-Fi built-in. In terms of hardware, the E7212 has an Intel Pentium processor (T4500 @ 2.3Ghz), 4GB of RAM, 320GB of storage, and a DVD/CD drive with burning capabilities.

    Medion has also pre-installed Windows 7 Home Premium (32-bit), Microsoft Works 9.0, Windows Live Essentials, a trial version of Microsoft Office Home and Student 2007, PowerDirector 8, PowerProducer 5, PowerDVD9, Media Show 4, Cyberlink Power2Go 6, CyberLink YouCam, CorelDraw Essentials 3 + MediaOne, and Bullguard Internet Security.

     


    Click to enlarge
    The 17.3-inch LED backlit display has a native resolution of 1600 x 900, giving users a wider view of documents. Movies were displayed in 16:9 widescreen and looked sharp and rich. Audio quality was good too, thanks to its speakers and subwoofer that are Dolby Home Theatre v3 certified.

    Despite the good specifications, users must remember that it is not built for 3D extensive applications and high-end gaming. The E7212 does not have a dedicated graphics card and only uses an Intel Graphics Media Accelerator for mobile. The notebook scored 2494 on 3DMark 03 and received a rating of 3.4 on Windows Experience Index (it got a 3.4 on gaming graphics).

    The E7212 lasted 145 minutes on our battery drain test (playing a movie with brightness and audio set to maximum), thanks to its 8-cell battery. This means that you can watch a movie and work on your documents for a couple of hours before charging the notebook.

    For $799, this computer is worth every dollar. It will definitely not suit those who want to play games or run graphic-intensive applications, but can satisfy the needs of a home office worker. This notebook will be available starting next Thursday, 28 January 2010.

    Develop Printer Secures Your Data

    Imagetec has launched two colour multifunction printers from Develop that can print via Bluetooth and comes with security features to prevent unauthorised document tampering.


    Click to enlarge
    Develop’s new ineo+ range (280 and 360) offer mobile printing via Bluetooth, a searchable PDF function that turns any scanned document into a searchable PDF, biometric authentication that prevents unauthorised access to the printer, copy security, and improved print quality.

    The ineo+ range has also been designed to run quietly on very little power with lower fusing temperatures, ensuring the system consumes approximately 50% less energy than similar models whilst also having more than 90% recyclable components. The printers have received the Blue Angel Mark, Energy Star and meets WEEE and RoHS standards for low noise and emissions.

    Imagetec’s General Manager for Sales and Marketing, Greg Heard said, “Businesses are looking for printing solutions that are high-quality, secure and sustainable. DEVELOP’s ineo+ range with its High Definition polymer toner technology, advanced data security functionality and energy efficient features meets all these needs. In addition to offering a sleek design, it comes with a competitive price tag which is sure to attract some attention in the market.”

    “Imagetec has a substantial installed base of devices throughout Australia and these products, combined with our commitment to outstanding customer service, will enable us to expand our direct and dealership customer base even further”, added Heard.

    The ineo+ 280 and ineo+ 360 deliver a scan speed of up to 70 originals per minute and an integrated 250 GB hard disk allowing users to store scans ready for future print and copy output. The printers can easily be integrated into any corporate network providing fast access, automatic status updates, remote maintenance and individually programmable authentication and account data for each user.

    Telstra Overhauls Business Mobile Broadband

    After slashing its mobile broadband plans for consumers, Telstra has announced its new business mobile broadband prices and new Acer notebook bundles.

    According to the company, the new mobile broadband plans for business will offer: double the data allowance on some subscription plans with the $39 Standard plan offering seven times more data than previously; $0 upfront Telstra Mobile Broadband “elite” devices for the first time on some 24 month contracts; casual plan options starting at $5 a month for businesses wanting flexibility and no lock-in contracts; price reductions of up to $20 per month compared to Casual plans when customers connect their existing device on a 24-month contract; and a higher usage plan of 120GB to cater for growing demand for high bandwidth applications.

    Telstra Business will also be launching three new ‘all-in-one’ business laptops, in partnership with Acer Computing, with built-in mobile broadband capability, low upfront costs and affordable repayment options.

    Telstra Business Group Managing Director Deena Shiff said, “These landmark plans are designed to not only give small business owners and managers mobile working capabilities with Telstra’s superior network coverage, but make it affordable to equip more staff with high-speed productivity tools.”

    “The surge in mobile broadband take-up shows it’s no longer just a tool for senior executives. Mobile broadband subscribers now account for 22 per cent of all Internet subscribers and usage is up 162 per cent across all networks up to June last year. Remotely monitoring worksites and infrastructure and sending and receiving multimedia files from home or in the field are just some of the ways small and medium sized companies are rapidly becoming digital businesses,” added Shiff.

    In addition, Telstra Business will also offer access to the Aspire One A0531 10-inch Netbook with a $19 data pack, plus monthly laptop repayments starting from $28.29 per month for 24 months.

    The Acer 8371 13.3-inch Notebook and the 8571 15-inch Notebook are available with data packs starting from $59 per month for 6GB of data, with a upfront payment of $149 and $249 respectively plus monthly repayments of $62.46.

    Telstra Rolls Out Unlimited Mobile Plan

    Telstra will be offering an unlimited plan to its business customers that include all standard voice calls, video calls, MMS and SMS to any Australian mobile or fixed number plus unlimited MessageBank diversion and retrieval for $180 a month.According to Telstra, the Mobile PLUS plan is available for a 12 or 24 month minimum term. Customers with their own handset will only pay $150 per month on a 24 month plan. Users with smartphones also have the choice of a BlackBerry or Microsoft email solution or 2.5GB of data for web-based email and internet browsing.

    Telstra Business Executive Director, Yasmin Dugan said, “This is the first time Telstra has offered an unlimited mobile plan to our business customers. In addition, customers who switch to Telstra from another provider and take up the unlimited plan for 24 months will receive a bonus credit of $540. For busy small business people, mobiles phones are often a lifeline that keeps them connected and their business running. This unlimited plan is ideal for those who make long calls or are heavy users of SMS or MessageBank. Combined with the Telstra Next G network, business customers now have more flexibility to choose a mobile solution that meets their usage, coverage and speed requirements,” added Dugan.

    While this is a first for Telstra, Optus has a similar plan called Timeless Business that was launched last year. The Timeless Business plan includes 2GB Mobile Internet Browsing, unlimited standard local and national calls, text and voicemail to Australian GSM mobiles for $129.

    Talk All You Want With New Vodafone and 3 Caps

    Vodafone Hutchison Australia is set to launch new postpaid cap plans that offer unlimited voice calls (3-to-3 or Vodafone-to-Vodafone) and mobile internet data allowance, in addition to the usual included value. These new cap plans will be offered by 3 and Vodafone starting this Thursday.


    Click to enlarge
    Click here to see the new Vodafone Cap Plans

    In a press conference held by VHA this afternoon, General Manager of Voice and Broadband, Edward Goff said that they want to give users three things: unlimited value, flexibility, and choice.

    “These caps offer endless same network standard national voice calls, and what separates us from our competitors is the fact that our customers don’t need to exhaust their monthly Cap value before reaping the benefits of unlimited same network standard national voice calls. Vodafone and 3 customers will immediately benefit from endless same network standard national voice calls from the very first call they make,” said Goff.

    The new Vodafone and 3 plans offer unlimited Vodafone -to-Vodafone standard voice calls and unlimited 3-to-3 calls, within Australia, 24 hours a day, seven days a week from just $29 a month.  In addition to this, the company also said that users can now use their whole Cap value on International voice calling and texting. “This will make it even easier to stay in touch with family and friends in Australia or overseas,” added Goff.

     

    Click to enlarge
    Click here to see the new 3 Cap Plans

    Postpaid users who sign up for a $49 cap or above will also receive monthly data allowances that can be used for Internet browsing.

    For Vodafone users, it means:

    • A $49 cap will now come with 50MB of data or unlimited Blackberry Email and Internet browsing +50MB;
    • A $69 Cap comes with 500MB of data or unlimited Blackberry Email and Internet browsing +500MB; and     
    • A $79 Cap comes with 1GB of data or unlimited Blackberry Email and Internet browsing +1GB

    For 3 users, it means:

    • A $49 cap will now come with 50MB of data;
    • A $69 Cap comes with 100MB of data or unlimited Blackberry data + 100MB; and     
    • A $79 Cap comes with 250MB of data or unlimited Blackberry data + 250MB

    “New Postpaid customers on contracts above $49 per month can also count on a generous monthly data allowance, to enjoy internet and email on the go.” said Goff.

    As part of the new Postpaid plan refresh, Vodafone and 3 will also be launching new month-to-month SIM Only contracts aimed at customers who want to ‘pay as they go’.

     

    “There has never been a better time to jump on the Vodafone and 3 bandwagon. We’re thrilled to be launching a new and exciting range of products. We’re certain this launch will rattle the market. If you want incredible value, flexibility and freedom, Vodafone and 3 have you covered,” concluded Goff.

    The Vodafone SIM Only Cap (month-to-month) includes:

    • $20 – $200 Vodafone to Vodafone; $150 included value; 50MB Mobile Internet
    • $35 – Unlimited Vodafone to Vodafone; $350 included value; 250MB or unlimited Blackberry Email and Internet browsing + 250MB
    • $55 – Unlimited Vodafone to Vodafone; $550 included value plus unlimited standard TXT and PXT in Australia or to Overseas; 500MB or unlimited Blackberry Email and Internet browsing + 500MB

    The 3 SIM Only Cap (month-to-month) includes:

    • $20 – 225 minutes of 3 to 3 calls; $150 included value; Planet 3 (Sports or News and Info); 50MB Mobile Internet
    • $35 – Unlimited 3 to 3 calls; $350 included value; Planet 3 (Sports or News and Info); 250MB Mobile Internet or unlimited Blackberry data + 250MB
    • $55 – Unlimited 3 to 3 calls; $550 included value; Unlimited national SMS and MMS; Planet 3 (Sports or News and Info); 500MB Mobile Internet or unlimited Blackberry data + 500MB

    BenQ Unveils 27-inch Full HD LCD Monitor

    BenQ has launched a 27-inch LCD monitor that displays images in 1080p and can be used as a main desktop display, secondary monitor, or a screen for HD gaming.


    Click to enlarge

    The M2700HD is a 16:9 LCD monitor that claims to deliver better sight and sound via its 50,000:1 Dynamic Contrast Ratio, 400-nit brightness, patented Senseye Human Vision Technology, and a 10-watt EmbracingSound surround sound system.

    Ports found on the M2700HD include two HDMI 1.3 connectors, component, composite, and SPDIF for all office and entertainment needs.

    Ideal as a main desktop display, multi-monitor setup, or as a second display to a notebook, the large-format 27-inch size affords higher work productivity with less scrolling and more content display.

    The M2700HD visually outperforms similar-sized/-priced TVs as it displays images in Full HD 1080p. The Senseye Human Vision Technology innately optimises picture quality via six proprietary calibration techniques encompassing brightness, dynamic contrast ratio, hue, saturation, 3D noise reduction, and dual-trace sharpness.

     

    In addition, the Senseye 3 digital image enhancement calibrates true colors in all multimedia and office display scenarios via the 6 preset viewing modes: Standard (office and Internet), Movie (DVD and TV), Game, Photo, sRGB (for 100 per cent color consistency across all sRGB devices), and Eco (for power-savings) modes.

    The native 16:9 aspect ratio likewise promotes uncompromised definition, true-to-source proportions without distortion, and the assurance that every pixel on the screen is utilized.

    It also comes with EmbracingSound, a new stereo surround technology that enables the listener to experience their content’s full spatial information. Five surround sound modes (Standard, Movie, Game, Pop, Rock) offer an unrivaled multimedia experience exuding from the integrated 10-watt sound system.

    A smart remote control caters to TV-style viewing, enabling the user to switch video sources, adjust audio options, and access the OSD from the couch, the bed, or other distance.

    The BenQ M2700 is available now for $799.