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 7 of 13

    Smart Office

    Is Kinect Paving The Way for Biometrics?

    It may yet prove to be a sign of things to come.

    Socially acceptable and fun activities are paving the way for a sinister move by companies into the world of facial recognition and biometrics, which may yet become the norm in more widespread activities such as access control and security in general.

    The Xbox 360’s Kinect, the peripheral used in Microsoft’s gaming console, uses facial recognition and infrared sensors, as the log in process for players engaging in its games, greeting returning gamers by name after recognising their faces when they step in front of the video console.

    The technology used includes a visible light camera, an infrared-based depth sensor, and microwaves, as it tracks movements of those playing the game, translating their real-life motions onto on-screen movements.

    The games are hugely popular with families.

    Earlier this month, Kinect Sports won a BAFTA (British Academy of Film and Television Award) for the best family game, but its appeal is far wider than just sports fanatics with three other games, Dance Central, Kinect Adventures and Kinectimals also being nominated in the family category.

    Kinect is also the world’s fastest selling consumer electronic device, breaking the Guinness World Records after consumers snapped up 10 million devices in the first two months of going on sale in November 2010.

    But Kinect is not just a game play device. With its camera and infrared sensor, which maps players’ bodies and faces using facial recognition technology, it has branched into the world of biometrics, allowing gamers to sign in without using an ID and password, but automatically, by being able to differentiate their facial features from other game players.

     

    However, its accuracy was brought into question within days of the device going on sale. US Watchdog Consumer Reports, which tested the Kinect soon after its release said lighting was seen to affect the gaming device’s facial recognition system from working properly when Gaming review site Gamespot complained that two of its dark skinned employees had problems logging in to the game.

    Despite log in problems, however, Microsoft’s move into biometric identification is both novel and sinister. Anonymity has long been a key feature of video gaming with gamers happy to engage in combat as long as their identity was fake. But observers claim that people aren’t likely to rebel against the technology, as long as the stakes remain low.

    Computer gaming, for instance, is not a high stake activity like banking, for instance. But what happens when gaming starts converging with other things like social networking, which could well lead it to filter into financial areas, such as shopping and banking?

    Observers have noted that introducing the technology in such a low stakes environment such as gaming, where the younger generation, in particular, are repeatedly exposed to the technology, may de-sensitize them to later uses.

    And face recognition technology is finding its way into a number of other ‘acceptable’ social uses.

    In the US, a face-matching dating website is using the technology to help people find their partners.

    FindYourFaceMate.com’s Christina Bloom said who we date depends a lot on how much they look like us.

    Bloom claims that couples often have very similar facial features and that facial similarities seem to help with the initial attraction.

     

    The face-matching dating website helps people narrow down their prospects by zeroing in on nine features, like your eyes, ears, nose, chin, or mouth, all helping to build an increasingly detailed picture of the person being profiled.

    Experts claim that when audiences are able to interact with biometrics at a socially acceptable level, the technology is able to gain traction within other uses, and could pave the way for more widespread use in the home, such as to control home security, access control and even in identification.

    Mistrust of the technology has been one reason why biometrics has so far failed to take off in more serious applications such as banking, but more acceptable functions, such as identifying members of the household to control other entertainment systems, and home automation controls for temperature, light and heating, for instance, could take off, simply for their novelty.

    Facial recognition apps are also on the rise. Face.com, a global leader in face recognition technology on the web, recently announced an upgrade in its technology which will allow it to process increased numbers of photos in a second.

    It’s a technology that is used in Facebook’s Phototagger and PhotoFinder, and is used by the social networking site to authenticate its members when they lose or forget their passwords, by putting up pictures of the member’s friends’ faces and suggesting likely names which the user must name correctly in order to gain access to their web page.

    According to the company, Face.com has been found to be effective even in challenging conditions such as lighting, background, picture angle, and even focus of the pictures.

    And now Chinese technology companies like Hanvon are making it even easier for companies and home businesses to use face recognition with low cost devices used to monitor staff or admit entry.

    Hanvon’s Face ID uses infra red technology to scan a 3D image of a person’s face. These images are stored on the device’s internal chip, so it doesn’t have to be connected to an external server.

    It can recognise up to 1400 faces and costs around US $720. Hanvon is now selling the device in 55 countries.

    Tablets: What Do You Use Yours For?

    With the mass market appeal of Tablets at an all time high, and given that Apple sold 7.3 million devices in the last quarter of 2010 for a total of 14.7 million since the iPad’s launch last year, (hardly surprising given that Apple had no real competition apart from Samsung’s Galaxy Tab which arrived late in the year) it’s clear that the Tablet is the must-have gadget for 2011.

    But what do Tablet owners use the popular device for, and what are its likely future uses?

    As part of my own research, I asked the question on my Facebook status, and found that ‘work emails’, ‘showing taxi drivers where to go on the Map’, ‘using the GPS locator’, ‘reading books’ and ‘anything else that would mean taking the lap top out of the bag’ were the most pressing needs addressed by the popular device.

    But while the Tablet has clearly found its way into both the living room and on the go, consumers are going to demand better end-user experiences, and more than just convenience from their portable devices.

    Post CES, and the imminent launch of the 10.1 inch Motorola Xoom, RIM’s 7 inch BlackBerry PlayBook, the 10.1 inch Asus EeePad Slider which has the added benefit of a slide-out keypad, two HP Web OS slates, not to mention Apple’s iPad 2, there’s going to be a lot of choice.

    According to new research published by In-Stat, the top three ranked uses for future tablet owners will be email, personal information management, and multimedia consumption (audio, video and gaming).

    “Last year’s small crop of Tablets was being touted as potential e-readers; a way to compete against the extremely popular Amazon Kindle lineup,” says Stephanie Ethier, Senior Analyst at In-Stat. 

    “But this next generation of Tablets is clearly being marketed as consumer multimedia consumption devices positioned to compete squarely against the Apple iPad.”

     

    Earlier this week, IDC published its report on the shipment of Media Tablets worldwide showing the market grew 45.1 percent in the third quarter of 2010, and Apple’s iPad dominating with 90 percent of units shipped.

    It identified Media Tablets as form factor devices with colour displays larger than 5 inches and smaller than 14 inches running lightweight operating systems (such as Apple’s iOS and Google’s Android OS) and can be based on either x86 or ARM processors, which include the iPad and Galaxy Tab.

    IDC also forecast strong demand for e-readers, which are single-purpose focussed devices. In the e-reader market, IDC identified Amazon as the market leader, with more than 1.1 million units shipped and 41.5 Percent share worldwide, with Pandigital, Barnes and Noble (exclusive to the US market), Sony and Hanvon following.

    IDC believes both tablets and e-readers will continue to flourish throughout 2011.

    Among its research on use of Tablets, In-Stat said nearly 55 percent of survey respondents who own Tablets spent 9 hours or more using their Tablet each weak.

    Despite the plethora of new Tablets being launched this year, however, more than 40 percent of future Tablet purchasers planned to buy an Apple iPad.


     

    LinkedIn Joins Forces With Nielsen Market Intelligence Service

    With Australians leading the world in terms of engagement with social networking sites, LinkedIn has added a powerful new tool for advertisers and media buyers to measure their effectiveness by joining Nielsen’s tag based digital audience measurement service, Market Intelligence.

    The move will enable it to be benchmarked against other Australian websites, by providing information on the number of daily unique browsers, page impressions, geographic location of users and daily reporting on duplication of LinkedIn with other web sites. The company’s first reported numbers for 1 December this year notched up 137,223 daily unique browsers and 1,372,917 page impressions.

    Stuart Bartram, Sales Director at LinkedIn, said: “Our decision to join Nielsen’s Market Intelligence service and tag our site is in direct response to feedback from our advertiser clients that they want in-depth insights on our audience make-up to assist with their advertising decisions.”

    LinkedIn site metrics will also be included in Nielsen’s soon-to-be-launched hybrid service, which combines tagging and panel based measurement approaches.

    Matt Bruce, Managing Director of Nielson’s online business in Australia, confirmed there had been strong demand from the market for greater audience measurement insights into the LinkedIn site. “With more than a third of Australians aged 18 to 35 having registered on LinkedIn, and a membership community including highly educated executives earning above average incomes, LinkedIn is likely to generate a lot of interest from advertisers.”

    A social media business benchmarking study conducted by Nielsen and Community Engine in 2010 found 71 percent of businesses intend to participate in social media marketing this year, and around a quarter of companies (23 percent) which had engaged with social media sites, reporting a strong or reasonable return on investment.

    Qantas To Resume A380 Flights To US

    Following the grounding of the A380 fleet and suspension of all Qantas A380 flights between Los Angeles and Australia, the Airline has announced it will resume services this weekend.

    The service will resume with the QF93 from Melbourne to Los Angeles on 16 January.

    Qantas suspended the flights last November, after problems surfaced with the A380 aircraft in Singapore. The safety measure was implemented to enable the company to monitor performance of the Rolls-Royce Trent 900 engine used by the A380s.

    A statement released by the company said that after extensive engineering analysis and close consultation with Rolls-Royce, Airbus and the European and Australian regulators, Qantas, Rolls-Royce and the Civil Aviation Safety Authority are now satisfied that it is appropriate for Qantas to resume A380 flying on the Los Angeles-Australia routes.

    Qantas Chief Executive Officer, Alan Joyce, said: “As always, safety has been our first priority in assessing when and where to bring A380s back into service over the past month. Only when we, our manufacturers and our regulators were completely satisfied that it was safe to begin flying the aircraft again did we resume A380 services, initially on London routes only.

    “We are now confident that we can begin flying the A380 to and from Los Angeles without any conditions on the use of maximum engine thrust.

    “In the meantime, our A380 engine inspection process continues as we gradually restore the aircraft to our international network. We are operating a full international and domestic schedule, using our entire range of aircraft.”

    For the remainder of January, Qantas will operate 14 A380 services per week between split between Melbourne and Sydney to routes including Singapore, London and Los Angeles routes. The company said A380 frequencies on London and Los Angeles routes will be steadily increased from next month, as aircraft return to service and new deliveries join the fleet.

    ARA Exposes Australian Online Shopping Habits

    The purchasing patterns of online consumers have been exposed by the Australian Retailers Association as it steps up the fight against lost sales to overseas websites.

    Online shopping, which is rapidly being adopted by Australian consumers and sending the likes of Harvey Norman and Myers into a frenzy of competition with their overseas counterparts, is uncovering surprising shopping habits that retailers need to be aware of, says the ARA.

    As expected, online book purchasing is by far the strongest category for e-transactions, with more than 30 percent of all books bought online.

    Overseas websites gain large dollar purchases up to $1,000, but don’t do so well on smaller purchases, the attendees at the seminar heard, and speciality retailers such as cycle and bike shops gain most online traction from customers living far from bricks and mortar retail shops.

    The seminar also heard that the next big trend in online buying might be furniture sales, as people who shop online are currently more than three times likely to buy furniture from a bricks and mortar store.

    More than 150 retailers gathered at the seminar, including e-commerce experts such as Quantium, Google and Deals Direct, to figure out how to prevent the Aussie dollar from going overseas.

    However, Quantium director Tony Davis said Australian retailers were losing sales to overseas websites regardless of the strength of the Australian dollar.

    Australian Sporting Goods Association executive director Brad Kitschke said while industry associations have been advocating for a tax neutral competitive playing field for Australian traders, that is not the sole issue that needs to be addressed.

     

    He urged retailers to engage in the online space and in e-tail as online shopping had become an increasing tendency for consumers across all demographics, and had moved beyond early adopters.

    Yesterday Target announced it was taking its operation online with plans to extend into lines it currently does not cover. 

    And in spite of all the noise made by leading retailers including Myer, Harvey Norman and Just Group over a tax neutral playing field, retailers are now moving to the web in droves to drum up sales in a flat retail trading environment. 

    The ARA is  planning to address topics such as logistics and supply chain, m-commerce, social media and video in retail.
     
     A series of Engage in E-tail seminars is planned for roll out in 2011.

    Gaming Interface To Push Marketing & Innovation

    It’s a bold prediction, but gaming is creeping into business processes just as the social networking phenomenon before it.

    Research firm, Gartner, predicts that by 2014, a ‘gamified’ service for consumer goods marketing and customer retention will become as important as Facebook, eBay or Amazon, and more than 70 percent of Global 2000 organisations will have at least one gamified application.

    It also says that by 2015, more than 50 percent of organisations that manage innovation processes, will employ game mechanics to drive those innovations.

    The trend has already begun in the UK and US, with the Department of Work and Pensions in the UK using an innovation game called Idea Street to generate ideas from its 120,000 workforce, and the US military using a video-game recruiting tool called ‘America’s Army’.

    The World Bank has also sponsored a game called Evoke, which crowdsources ideas from players globally to solve social challenges.

    According to Gartner, gamification achieves “higher levels of engagement, changes behaviours and stimulates innovation”.  As a result, the opportunities it creates for business range from having more engaged customers, to crowdsourcing innovation or improving employee performance.

    The UK’s Idea Street platform, for example, included game mechanics such as points, leader boards and a ‘buzz index’ and within 18 months had appoximately 4500 users and had generated 1,400 ideas, 63 of which went forward to implementation.

     

    There are four principal means of driving engagement using gamification, says Gartner. It increases the velocity of feedback loops to maintain engagement, it provides clear goals and rules of play, it provides a compelling narrative that engages players to participate and achieve the goals of the activity, and provides employees with short-term, challenging, but achievable goals.

    Brian Burke, an analyst at the firm said: “Where games traditionally model the real world, organisations must now take the opportunity for their real world to emulate games. Enterprise architects must be ready to contribute to gamification strategy formulation and should try at least one gaming exercise as part of their enterprise context planning efforts this year.”

    Gartner analysts are to explore the impact of gamification on enterprise architecture at a summit in London and San Diego from next month.

     

    Mobile VoIP Set To Soar, Says Study

    Voice over IP (VoIP) technology is spreading from the fixed line world to the mobile space, says a new study by In-Stat.

    The technology that has revolutionised voice services over the past few years and has brought calling costs down for residential and business customers alike, is expected to soar beyond the $6 billion mark in 2015, says analist Amy Cravens.

    “Mobile VoIP has only recently begun being implemented in the business environment.  One of the key benefits of mobile VoIP for enterprises is extending desk phone functionality to mobile devices.  Business-oriented solutions will essentially enable the users’ cellphones to become an extension of their desk phones and will deliver, in addition to voice, a unified communications experience, including email, IM, and collaboration,” said Cravens.

    The study claims business mobile VoIP users will increase tenfold over the next five years, and while mobile operators are currently a barrier to adoption, they could become a significant driver of adoption in the future.

    Growth in IP PBX, on which business mobile VoIp is based, will also be driven by mid-sized and enterprise businesses, the study says.


     

    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.

    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.
     

    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