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; } } Marie Jones, Author at Smart Office - Page 2 of 13

    Smart Office

    Social Networking A Gateway For Criminals, Says Expert

    LinkedIn, Facebook, Twitter and social networking in general are proving to be a gateway for criminals trawling the internet for information that can be exploited to do harm to both businesses and consumers, according to security analysts.

    Lloyd Borett, security expert at AVG (AU/NZ), which specialises in security software solutions, says: “Online social networks have sprung up for business, hobbies, schools and religious groups. Used properly, they are a unique communications tool to keep in touch with friends and colleagues. But like any online tools, social networking sites can be abused by hackers and cyber criminals.”
    While social networking has been argued to provide tangible benefits for business, a survey by Manpower claimed only 20 per cent of companies worldwide have a social networking policy in place. 
    Leading research and advisory company, Gartner, predicts that social networking will overtake email by 2014, and according to a new survey by Regus, 40 per cent of businesses have used social networking successfully for business development. 
    Meanwhile, in the first six months of this year, LinkedIn‘s members grew by 40 per cent to 70 million, and Twitter grew to 190 million users. Around 250 million people log into Facebook everyday. 
    Borrett warns that both casual and business users should be careful about what they post online, so as not to provide ‘gateway data’ to criminals.  He advises companies to get acquainted with the privacy settings and tools on the social networks that are used. “The bottom line is – all employees should be aware of which social sites they are allowed to use during working hours,” he said.
     

    The term “gateway data’ was coined by Herbert ‘Hugh’ Thompson, a professor in the Computer Science department at Columbia University in New York, to refer to the confidential information harvested from social networking sites.

    “Criminals have got to be able to leverage the information that people are sharing to do harm at some point,” he said. The gateway data identified by Thompson can be used in a variety of ways. 
    For example, discovering someone’s mother’s maiden name from Facebook could, in turn, be used to answer a password prompt question on an email account. Even if that account is a personal account, the user will have been compromised and the hacker is one step closer to all the business information they want.
    Hackers look for lots of fragments of data to reveal a larger piece of confidential information. So the separation between personal and business data is not as distinct as people think. In fact there could be no boundaries between them at all, says Borett.
    Borrett also warns about the popularity of shortened URLs on sites such as Twitter. “The problem with shortened links is that they usually don’t bear any resemblance to the original URLs, which means that users don’t know what they’re clicking. People click with the intention of going to a specific site, but the link can be easily hacked to send them to a site containing Trojans, spyware, rootkits and other malware instead.” 
     

    The danger of an unguarded approach to social networking is not just about risks to physical property on a personal or corporate level. Identity theft is also a serious concern. The Australian Government web site Stay Smart Online contains useful advice on using social networking sites safely at www.staysmartonline.gov.au.

    The shift in attitudes about personal information sharing among its user base caused Facebook to change its privacy rules in late 2009 with some of its 350 million worldwide users concerned that the company was out of step with identity theft and online security.
    Industry opinion suggests that while businesses have adopted Facebook (and perhaps even more prevalently LinkedIn and Twitter) as a networking tool, the privacy improvements that the social networking giant brought to bear were not commensurate to the risks that now exist at a corporate networking level. 
    A central part of how social networking sites engage their audience, is getting users to post more personal content. This builds up profile and identity. “Within the business environment this identity becomes intellectual property – and this needs to be locked down,” says Borett.
    Some advice on how to manage information briefs include restricting information detailing which companies you are meeting to avoid highlighting your business partners and prospects to competitors, not revealing your product innovations prior to their official launch so not to weaken their impact, and not pumping out details of which companies you can’t stand dealing with, or whose products you hate, which might just be one step away from a defamatory court case.

    Samsung Heads For Projector Market Share

    Samsung, who has been making headway in the IT and Business market, is now set to go after the projector market with a new portable projector system.

    The company has launched an affordable, ultra portable and powerful pico projector, the Samsung SP-HO3, which makes giving business presentations, sharing information and watching movies possible while on the go.
    The projector weighs just 210g, or 130g without a battery, and is currently lighter than many smartphones on the market. The detachable battery lasts up to two hours in Eco mode. Mobile workers, salespeople and students set to benefit most, as the unit can be used with a plug and play memory card  from a camcorder, camera or smartphone or notebook computer.

    Click to enlarge

    Despite its compact, mobile package, the SP-H03 can still handle powerful presentations. Its 30-ANSI bulb is the brightest among pico projectors, and the device projects a bright, clear image on screens from 9 to 80 inches. Whether you’re showing a PowerPoint slide at a conference or watching an HD movie at home, the SP-H03 offers crystal clear image projection for maximum enjoyment. 
    With 1GB internal memory, documents, video, photos and music can be loaded directly onto the SP-H03 to deliver a smooth presentation experience. The device also supports external storage from a MicroSD card slot or PC via available USB ports, meaning size is no object for presentation delivery. The SP-H03 maximises usage efficiency through these interfaces so users can connect it to their notebook, camcorder, camera or smartphone.
    “The pico projector market is rapidly growing as corporations globalise and professionals travel more often than ever. The SP-H03 was designed for easy portability, eliminating the hassle and setup issues often encountered by presenters as they travel from organisation to organisation,” said Emmanuele Silanesu, National Product & Marketing Manager – IT, Samsung Electronics Australia.
    “Not only is it great for business people, but users of all kinds can experiment with the technology to share content in new ways. By creating a convenient, portable, powerful and inexpensive projector, Samsung is poised to assert its leadership at the top of this market. We’re excited to bring new projector technology options to Australians.”
    The Samsung SP-H03 pico projector is available from 1 August at an RRP of $399.

    Sanyo Aims To Be A Hit In Clean Energy Solutions

    The rooftop solar panel grid system installed at Johnson & Johnson Medical’s North Ryde HQ uses Sanyo’s unique patented HIT technology, providing one of the world’s highest conversion efficiencies, according to Sanyo’s Group Manager, Environmental Division, Paul Reeves.

    Hit Technology (Heterojunction with Intrinsic Thin-layer) cells are a hybrid of two common solar cells in the marketplace, Crystalline and Amorphous, that are combined to create a more efficient and effective solar cell, said Reeves.

    Sanyo HIT cells are made of thin mono crystal silicon surrounded by ultra-thin amorphous silicon layer which are claimed to provide better performance and value.


    Click to enlarge
    Bill Crichton, MD of Sanyo, Maxine McKew, MP, Member for Bennelong and Paul Reeves, Sanyo Group Manager, Environmental Division

    “Using HIT solar cells enables organisations to obtain maximum power generation per square meter. With more power per square metre, incorporating Sanyo modules into clean energy solutions for homes, businesses or public facilities also means fewer rooftop modules are required, something that saves rooftop space and installation time, which in turn saves money,” said Reeves.

    “The technology is getting to the point where companies like Johnson & Johnson Medical understand that the solar energy solutions they purchase will not only provide them with a reduction in their footprint, it will also be working for the next 25 to 30 years to dramatically reduce their monthly electricity bills,” added Reeves.

    Sanyo teamed up with approved system integrators Apollo Energy and project management team from its retail division, Energy Matters, to install this cost-effective and highly efficient solar panel system for Johnson & Johnson, which is said to be the largest commercially funded solar panel installation in Australia.

    Reeves continued: “The development of this large scale solar panel installation is truly a milestone for Sanyo, Johnson & Johnson Medical and the solar panel industry in Australia.  It is the largest panel installation in the country and will save Johnson & Johnson Medical around 10 per cent of its electricity costs.  The development of this installation is also a reflection of Sanyo’s place as a leading manufacturer in solar, and more importantly, a clean energy leader in the Australian market.”

    Big Savings On Solar For Johnson & Johnson Staff

    Energy Matters, the retail division of Apollo Energy which together with Sanyo installed Australia’s largest commercially-funded solar panel installation at Johnson & Johnson Medical’s HQ in North Ryde, is extending a special deal to the company’s employees to save money as part of the Johnson & Johnson solar project.

    Johnson & Johnson employees are being encouraged to offset their electricity bills and reduce their carbon emissions by more than 3.5 tonnes per year, by investing in a system that will cost $7,499 and save them more than $1,500 per year in energy bills. 
    Employees who take up the offer can recover their system costs in five years, and continue to benefit from lower electricity costs, as well as contributing to the environment. 
    The offer comprises 9 x 210W Sanyo panels and a Fronius IG20 inverter as well as installation costs. The RRP for such a system is $9750, but staff, whose homes do not have flat roofs and are located within Sydney, can benefit from the reduced price deal until December 2010.  

    Samsung Adds WiFi Connectivity And Colour To Compact Printers

    Samsung Australia has introduced a couple of handy features to its range of multi-funtion compact colour printers, that will make life easier for SMEs and small home businesses.

    Incorporating one touch wireless set up, colour printing and toner options, the new features of the  CLP-320N, CLP325 and CLX-3185 series are claimed to be seamlessly integrated into the printers’ design, with a stylish, glossy, slick black and cream grey finish. 
    Emmanuele Silanesu, National Product and Marketing Manager-IT, for Samsung Electronics Australia, said the simple Wi-Fi connectivity will enable small businesses to de-clutter the working environements, and toner saving features will deliver genuine cost savings, offering “a smart investment for anyone looking for a colour printing solution that will be a valued addition to any office”.
    The new printers are certified with Wi-Fi Protected Setup to ensure the wireless connection is secure, and also features Samsung’s Navigation Key Ring to enable easy navigation of printing options. 
    The one-touch toner save button also lets you print using less toner on each page without compromising on quality, extending the life of the toner cartridge by up to 30 percent compared with using it on standard mode. 
    With print speeds of up to 16 pages per minute (ppm) in monochrome and four ppm in colour, the CLP-320N, CLP-325 and CLX-3185 Series multi-function printers share the same toner cartridges, which are now available in a new slim design to save storage space. The black toner cartridge yields 1,500 pages, while the cyan, magenta and yellow cartridges have a 1,000-page yield. 
     

    This new range of printers also features Samsung’s Polymerised toner technology. Polymerised toner involves synthesising resin particles and fusing it to colour pigment additives. The result is extremely small spherical shaped toner particles that are uniform in shape and size compared to traditional “crushed” toner particles. The benefit is less toner usage per print and significantly reduced toner scatter when printing, creating outstanding quality prints with accurate colour and a beautiful glossy finish. 

    Other features include a one-touch Print Screen Button, AnyWeb Print software which allows you to select, drag and drop specific content from web pages, rather than printing the entire web pages, and Soft Power Button, which is an easy way of turning the printer on or off, or put it on standby.
    Australian RRPs are as follows:
    CLP-325W –  $399, 
    CLP-325 –  $329, 
    CLX-3185FN – $549
    CLX-3185FW – $649
    CLP-320N – $349 
    CLX-3185 – $449 

    Parallels Open Doors Down Under

    Parallels, the company which enables the use of Windows on Macs, has opened new offices in Australia and New Zealand.With the increasing use of Apple products down under, and the need to run Windows OS on their Mac OS for both personal and business use, the company is now marketing its award winning virtualisation software for business, consumer and cloud service provider audiences.

    Neil Moraji has been appointed General Manager and Alexei Anisimov as Sales Engineer. Morarji will be responsible for cementing strong relationships with cloud services provider partners and distributors, Conexus and Software Only, while Anisimov will provide strategic sales and technical support for customers and partners in ANZ. 

    Parallels has enjoyed a growing presence in the Australia and New Zealand market since 2006, grown mainly through service provider partners. John Eng, Asia-Pacific VP of Marketing and Alliance for Parallels said the company’s virtualisation and automation solutions had been rapidly adopted by businesses, consumers and service providers over the last four years, and the decision to open offices comes as a direct result of this success.  
    He said: “The large majority of businesses in Australia and New Zealand are small-to-medium enterprises in need of high-quality IT services, but lacking the budgets to manage them in-house. Parallels enables SMEs to take advantage of the best technology when they need it and without complexity, so that they can stay focused on business.”
    The company’s desktop virtualisation product for consumers, Parallels Desktop 5 for Mac, which retails at $119 in Australia and is available from stores including the Apple Store, Harvey Norman, David Jones, Dick Smith, Myer and Nextbyte,enables users to seamlessly run multiple operating systems and applications on their Mac desktops, with enhanced speed and performance. The product is also available through major resellers such as Mac One and online through Harris Technologies. 
     “With the popularity of Mac computers among consumers and more recently business and SOHO users comes the need for flexibility and compatibility. Increasingly we are seeing the need for users to have the ability to run a Windows OS on their Mac OS for various reasons relating to personal and business use. Parallels consumer products offer the best of all worlds allowing people to use their Windows OS on their Mac OS at the same time without rebooting,” said Eng.
     

    Home Users To Benefit From Redesigned HP Printer

    HP has released a family of new web-connected, ePrint-enabled Photosmart printers that offer consumers a combination of cutting-edge design, personalised apps and the ability to print from anywhere, at anytime.

    They include the HP ENVY100 e-All-in-One compact unit that is designed to fit the modern lifestyle, is said to be the world’s first PVC-free printer and offers the most convenient way to wirelessly print documents and photos. Users can also produce web prints without a PC, and print anywhere, anytime, using apps and HP ePrint.
    The new HP Photosmart eStation features a detachable, 7-inch, full-colour touchscreen and doubles as a wireless digital companion and control panel for remote printing. It also offers full web browsing capability with high performance printing, copying, scanning and faxing without a phone line. Fun apps include eReader, Snapfish, Facebook, music, email and news and users can also enjoy deluxe photo printing with the HP Photosmart eStation’s 5-ink IIC, auto photo paper tray, HP Photo Creations and HP Print Gadget.
    The HP Photosmart e-All-In-One printers are ePrint enabled printers allowing users to have a simple email address  to deliver a print the same way they would send an email message. Customers can also send documents, such as Microsoftr Office documents, Adobe PDFs, and JPEG image files among others, to print through an HP ePrint mobile app on their smartphone device to a home, office or public print location. 
    One of the key features of the new printers is ePrint, which allows users to take advantage of cloud computing to print files  from anywhere in the world, using a laptop or mobile device. The printers are also touch-enabled, which makes content available simply by sweeping your finger on an intuitive touch screen panel. 
     

    They also include AirPrint technology for Apple devices, which automatically finds printers on local networks and can print text, photos and graphics to them wirelessly over Wi-Fi without the need to install drivers or download software. AirPrint automatically finds printers on local networks and can print text, photos and graphics to them wirelessly over Wi-Fi without the need to install drivers or download software. HP’s existing and upcoming ePrint enabled printers will be the first to support printing directly from Apple iOS devices.

    Paul Gracey, Category and Marketing Manager for the HP South Pacific region said the new line up gives consumers easily accessible tools to enable them to print what matters most.  “HP’s new line-up of Photosmart printers will change perceptions of what printers look like and what they can do. We’re redefining printing for the home with modern designs, cutting-edge technology and web-direct printing for consumers,” he said.

     
    Australian RRPs and availability are as follows:
    HP ENVY100 e-All-in-One $399 from 1 November from leading consumer electronics stores accross Australia.
    HP Photosmart eStation $699. from 1 November from selected Harvey Norman stores.
    HP Photosmart Premium e-All-in-One $299 from 1 October  at leading Australian consumer technology retailers.
    HP Photosmart Plus e-All-in-One $199 from October 1 2010 at leading Australian consumer technology retailers.
    HP Photosmart Premium Fax e-All-in-One $399 which are available now from  Australian consumer technology retailers.

    Woolworths Gets Into Bed With Qantas

    Woolworths is to launch an Everyday Rewards Qantas credit card next week which will carry a low annual fee of $89. The card is said to be one of the best value frequent flyer reward cards in the market offering customers one Qantas Frequent Flyer point for every $1 spent in stores accepting Mastercard.


    Customers shopping at participating Woolworths Group stores will also be able to turbo charge their Qantas Frequent Flyer points for the same spend by earning points for each dollar spent both with the Qantas credit card, and for each dollar spent over $30 by having their Everyday Rewards card scanned for the same transaction. 

    General Manager of Woolworths Everyday Rewards, Peter Burgan said: “The Woolworths Everyday Rewards loyalty card program has gone from strength to strength with more than 5.4 million registered members, of whom 3 million have also registered to earn Qantas Frequent Flyer points.”

    “Woolworths is firmly focused on providing the best possible value to customers across all our brands and services, whether it’s a basket of groceries, a mobile phone plan or a rewards credit card. Since the launch of the Woolworths Everyday Rewards program, millions of our customers have come to value Qantas Frequent Flyer points and this credit card offers them a simple way to receive even more value from everyday purchases,” Mr Burgan said.

    Qantas Frequent Flyer Chief Executive, Simon Hickey, said: “Qantas Frequent Flyer is committed to making it as easy as possible for our members to earn points and providing them with as many ways as possible to use those points. The Woolworths Everyday Rewards Qantas credit card is another great way our members can earn points by doing their everyday shopping.”

     

    The Woolworths Everyday Rewards Qantas credit card features include a 24/7 concierge service, up to 55 days interest free on purchases, an interest rate of 19.99% on purchases with 5.99% p.a for six months on balance transfers, and no points capping or points expiry while the Qantas Frequent Flyer account remains active. Members will also be able to apply for a free additional cardholder.


    New customers also save themselves the Qantas Frequent Flyer Membership of $82.50, and those who apply before 31 January 2011 and make an eligible purchase by 31 March 2011 will also receive 16,000 bonus Qantas Frequent Flyer points.

    The Woolworths Everyday Rewards credit card is Woolworths’ second credit card product and the latest in a suite of value-focused financial services products.

    General Manager of Woolworths Financial Services Dhun Karai said: “Woolworths has already rolled out a number of successful financial services initiatives which customers have embraced. Our financial services offer now spans credit cards, gift cards, prepaid single use and reloadable prepaid cards and one of Australia’s largest networks of ATMs.”

    The Woolworths Everyday Rewards Qantas credit card is backed by HSBC, MasterCard and Qantas.

    Competition Driving Healthy Revenues For VoIP

    Increased competition in the voice over internet protocol (VoIP) market is driving revenue growth with businesses are ramping up their investments in VoIP technologies both on customer premises equipment (CPE) and hosted VoIP, according to new data from ABI Research.

    Both CPE vendors and hosted VoIP service providers are using product differentiation, attractive pricing and improved customer service to win and keep customers. As a result, the integrated unified communications suites market, which was adversely affected by the GFC, is poised to see consistent growth to reach revenues of $4.8 billion by 2015, says ABI Research.

    Asia Pacific and North America are the two most aggressive regions using hosted VoIP deployments.

    IP PBX vendors are expected to ship just over 35 million IP lines (including native IP and hybrid lines) worldwide during 2010. IP telephony shipments will continue to see robust growth throughout the forecast period as enterprise communications systems converge on the IP platform.

    In the North American market, hosted VoIP services are buoyed by an additional set of drivers including the slow economic recovery, employee mobilization, and a more distributed workforce. 
     
    “Senior analyst Subha Rama says: “Even large businesses that traditionally shied away from hosted services for mission-critical communications are deploying hybrid models, experimenting with hosted services in smaller doses.” 

    Practice director, Dan Shey, said: “Hosted VoIP is a ‘safe investment’ and offers flexibility for businesses in a slow, uncertain economic recovery. Consequently, hosted IP PBX services are expected to finish the year with a 15.3% increase in revenue to $3.4 billion, worldwide. Besides North America, Asia-Pacific will also be aggressive with hosted VoIP deployments.”