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; } } Web Development, Author at Smart Office - Page 2 of 8

    Smart Office

    Wireless Which Is Best?

    There are about 100 top companies that shape the ever-expanding wireless landscape. We recently turned the spotlight on mobile devices, platforms, silicon and management only. That meant no influential networking vendors, such as Cisco or iPass.

    Alien Technologies
    The name Alien Technologies is poised to penetrate the mobile world’s collective conscience as being synonymous with RFID.

    Already a household brand in the RFID industry, Alien has filed for an IPO. The company, a leading RFID silicon maker, has applied to use the ticker symbol RFID, which in itself will illuminate the industry’s visibility. Even if the IPO flops, it will be a catalyst for greater RFID investment interest and, in turn, the development of new RFID applications. And when Alien becomes the first public pure-play RFID kit maker, other niche RFID outfits may follow.

    However, Alien’s impending stock-market debut also threatens to shine a light on RFID projects, the vast majority of which are still in small, pilot stages. Whether this scrutiny will benefit the fledgling industry
    is uncertain.

    Google
    Google has a vision of ubiquitous wireless connectivity, so that it can build new search applications that make life easier for consumers, and its advertisers.

    This year, the search company became the unlikely builder of a WiFi network in its Silicon Valley hometown, which it plans to turn into one big free WiFi hotspot. The network will be a test bed for future mobile applications and, potentially, mobile devices.

    In April, Google won a bid with partner Earthlink to bring free WiFi to 90% of San Francisco by year’s end. Google will give users 300Kbps connections for free. Users, in turn, will endure the wares of Google advertisers.
    And late last year, the company quietly launched a free virtual private network service designed for roaming WiFi users at its few free hotspots near its headquarters.

    Hewlett-Packard
    HP blazed a trail with the first antenna-less GPS-enabled handheld, the iPAQ hw6500, last year. It has since upgraded that device, the hw6900, which has a better thumb board and is one of the first to sport Microsoft’s Messaging and Security Feature Pack.

    It still has quad-band GSM with EDGE support, WiFi, Bluetooth and the Skype VoIP client preloaded, among other features. The hw6900 series boasts better specifications than others on the market, including Palm’s Treo 700w.

    HP also has a notably revamped marketing campaign, spearheaded by Apple’s former marketing guru Satjiv Chahil, which should turn up the competitive pressure.

    iAnywhere/Sybase
    iAnywhere is among the market’s largest heterogeneous mobile middleware vendors. The company’s XTNDConnect PC mobile device-to-desktop synchronisation software is also making strides. iAnywhere has added support for Windows Mobile 5.0 devices, as well as for Sony Ericsson’s latest models.

    The company is also helping mould the RFID space, with new embedded software for RFID hardware makers to build smart RFID readers with beefed-up security features.

    And Sybase, which has a majority stake in iAnywhere, is also going toe-to-toe with rivals BEA and IBM in the RFID software space. In February, it launched a new version of its RFID Enterprise stack, which is geared for companies that are moving beyond RFID pilots to more in-field operations. Sybase now claims the deepest stack for enterprise-scale RFID deployments.

    Intel
    The world’s largest chipmaker this year promises to spur more powerful mobile devices with longer battery life, and has wireless convergence visions.

    Intel’s new Core microprocessor architecture, the company’s third major refresh, promises to reduce power silicon consumption by at least three times. The first dual-core processor based on the architecture for notebooks is Merom.

    By 2010, the company plans to launch another architecture to enable processors 10 times faster than current chips with one-tenth of the lowest-power processors today.

    Intel is also rolling out a new 65-nm chip-making process that lets it add more cores onto the silicon while boosting performance. By mid-2007 it plans an even smaller 45-nm node.

    Intel is also championing WiMax and plans to ship a .16e WiMax PC card later this year. Already it has claimed the first integrated WiFi-WiMax flexible radio chip that operates in three communications bands. The goal is to merge these two technologies within a few years.

    Microsoft
    The software maker does not have nearly the same weight to throw around in the handheld mobile market as it does in desktops and notebooks. But it is working to change that.

    The ultra-mobile PC offerings to be borne from Microsoft’s Origami project, from hardware partners such as Samsung and Founder, have fallen well short of impressive. Still, if the company can help OEMs evolve beyond the current clunky offerings to more efficient, cheaper handheld machines running full versions of Windows XP, or Vista at some future point, it is sure to shake things up.

    Microsoft’s Windows Mobile OS also continues to show up on smartphones from a growing list of vendors. And the company just inked a deal for its Mobile OS to run on smartphones powered by Qualcomm chips, which will begin adding to its market share later in the year.

    Motorola
    The number two handset maker has emerged as the industry’s star this year, by gaining on Nokia and its Asian rivals with impressive market share growth.
    Motorola’s ultra-thin Razr continues to be among the most desirable phones among business users and teenagers alike. Its HelloMoto promotional campaign has also been a hit with both users and carriers.

    And in the first quarter, for the first time in several years, Motorola reached 20% global market share, mostly by outselling Samsung, Sony Ericsson, LG and others, according to Strategy Analytics.

    Motorola, which together with Nokia accounts for a record 53% of the world’s handset market, is also an early mover in developing countries where demand is mostly for low-margin, entry-level phones. But this strategy should pay off in the long run, when users look to upgrade.
    Nokia
    The leading mobile phone maker continues to dominate the market and in the first quarter had a slightly larger global share, 32.8%, than its 32.4% full-year share in 2006, according to Strategy Analytics.

    The company’s success is thanks largely to its emerging-markets strategy, being first to swoop into most developing countries where it had few credible competitors. Last year, for instance, the company owned a 55% share of the Indian market. Nokia expects emerging markets will account for 80% of its next billion subscribers, and by 2008 it expects its global subscriber base to reach 3 billion.

    Nokia, however, is not immune from falling average mobile phone selling prices, a trend it foresees persisting this year. The company also faces challenges in its enterprise unit, which is facing losses, but its acquisition of Intellisync will bolster its performance.

    Palm
    The ongoing legal woes of BlackBerry maker Research in Motion is nothing but good news for Palm. While the mobile device maker faces fierce competition from new email-enabled phones from Nokia and Motorola, which will soon hit retail shelves, Palm seems to have hit its stride.

    Earlier this year, the company doubled the number of Treo smart phones it sold compared to the same quarter a year ago. Palm has a trio of new Treos to release this year, notably the 700p, which will use the Palm operating system. With as many as 20 million or so Palm OS users today, the 700p will help fuel this installed base.

    Last September, Palm also debuted the Treo 700w running on Microsoft’s Windows operating system. This CDMA EV-DO-enabled Windows Treo will help the company expand its footprint further in the North American market, which currently drives about three quarters of its revenue.

    Research in Motion
    Research in Motion’s BlackBerry email device is so prevalent among corporate users, many of whom struggle to put it down, it has earned the informal moniker ‘CrackBerry’.

    So far, the company has shipped about 5 million of its handhelds. And RIM’s recent acquisition of Ascendent is set to help it shore up subscriber numbers. Ascendent’s Voice Mobility Suite will enable RIM to add new voice, notification and collaboration features to the BlackBerry Ascendent, as well as notification and conferencing capabilities to the BlackBerry Enterprise Server. Whether RIM will choose to license Ascendent’s wares to other handsets remains to be seen.

    The company has forecast it will double the number of its carrier customers to more than 300 in its current fiscal year, with the addition of new carriers such as China Mobile. RIM is also preparing to announce a new product that would include support for both Edge and EVDO transport, as well as some UMPS-type support.

    Best of the rest
    Good Technology, Symbian and Visto nearly made it to the Top 10 this year. Good Technology’s newest GoodLink v4.8 is a winner with enterprises wanting to deploy more smartphones among more workers without huge infrastructure investments, while Symbian continues to carve a mobile OS niche in the emerging mid-market. And Visto is giving market leader Research in Motion and others a run for its money. Visto’s mobile platform is seeing traction, but, moreover, the company is suing Microsoft and seeking to shutter RIM’s BlackBerry service in the US for allegedly infringing on Visto patents.

    New Motorola Phones

    Motorola the world’s second-biggest maker of cellphones,has unveiled several new handsets, including the Krzr and the Rizr, which are narrower than its flagship Razr.

     The new models are part of a family of cellphones that Motorola is building around the Razr, which has helped the company revitalise its brand in the last few years.

    As competitors like Samsung followed suit with their own skinny phones, Motorola hopes to keep up the momentum of the Razr with new models inspired by its style and four-letter name. Motorola has sold about 50 million Razr phones since they were first launched in late 2004.


    The 42-millimeter-wide Krzr flips open like the 54 millimeter-wide Razr, but is slightly thicker, as it has a better 2-megapixel camera and space for extra storage for up to 500 songs.

    The Krzr, made of magnesium, polished chrome and hardened glass, also has a reflective surface and will come in two colours: grey and blue. It is to be sold worldwide by the end of the year.

    The narrower phone should help the company attract new customers including women, said Tracey Koziol, an executive in Motorola’s handset division.

    “For people with smaller hands, it does probably fit better than the Razr, especially for Asian customers and ladies,” said Koziol, adding that most cellphone carriers around the world have shown interest in the product.

    “We expect very good takeup,” she said. Koziol said the Krzr would probably sell at around the bottom of the high-end price range, but declined to give a specific figure. The Krzr will be available for networks running on GSM, the dominant global wireless standard, and CDMA, a popular phone standard in Australia the United States, and parts of Asia.

    Motorola also unveiled the Rizr, which is 46 millimetres wide and slides open. It gives users the option of turning the phone sideways when it is closed to take landscape photographs using a dedicated button for its 2-megapixel camera.

    Available in blue, red and black, the Rizr will initially be sold just to operators using GSM networks. It is expected to sell in the mid-tier price range. Motorola also unveiled three phones for high-speed wireless services. The Razr XX and the Razr Maxx will work on networks based on HSDPA, a faster version of GSM, and will allow users to stream video or music to the phones over the air.

    The Razr XX is expected to price in the mid-tier range while the Maxx, which has room for extra storage and a 2-megapixel camera, is expected to sell in the high-end range.

    Motorola also debuted the SLVR L7c, a candybar phone also inspired by the Razr that will run on EV-DO, a faster version of CDMA.

    Cisco And Microsoft Are At War

    Just when you thought all was quiet on the network front Gartner has shattered the peace by declaring that Microsofts recent alliance with Citrix Systems to develop wide area network (Wan) optimisation technology represents a declaration of war on Cisco in the “critical battleground” of the remote office.

    VNU claim that according to the analyst firm, the Redmond giant’s tie-up with thin client firm Citrix is the culmination of a “long-simmering rivalry” with Cisco, and has the potential to transform the Wan optimisation market.

    The comments come after Microsoft and Citrix announced an expansion of their established partnership that will result in a jointly developed and marketed Citrix-branded branch office box.

    Gartner said that this product is scheduled to ship in the second quarter of next year and will be based on Citrix’s WANScaler product line gained through its recent acquisition of Orbital Data, and on Microsoft’s Windows Server and Internet Security and Acceleration Server.

    “Microsoft clearly considers Cisco a significant threat to its dominance in the enterprise software market, and views the branch office as a critical battleground for application and network architectures,” stated a Gartner advisory.

    “Cisco and Microsoft have avoided direct competition until recently, but the merging of networking, security, storage and applications made this confrontation inevitable.

    “Microsoft is launching new networking capabilities within Vista and the ‘Longhorn’ version of Windows Server, and is pursuing partners in the voice arena, for example Nortel.”

    The analyst firm also believes that there will now be much more conflict between Cisco and Microsoft, a battle it originally predicted in 1997. “Microsoft is building a team of networking vendors to compete with Cisco. Citrix brings credibility in branch office application delivery through its Presentation Server and NetScaler products,” the Gartner report stated.

    “By adding Orbital Data, Citrix now has an end-to-end application delivery family that is broader than Cisco’s.

    “With a rapidly expanding portfolio, good strategic partnering and software-centric channels, Citrix is a serious competitor and potential roadblock to Cisco’s aspirations to control application delivery.

    “The future WANScaler appliance promises to provide Wan optimisation, content distribution, security and branch office services.

    “When combined with Microsoft’s marketing might and strategic customer relationships, this product is likely to quickly appear on prospective customers’ shortlists once it is released.”

    Gartner believes that Microsoft’s tie-up with Citrix will change the selling dynamic for Wan optimisation controllers, branch office boxes and, to a lesser degree, application delivery controllers.

    “Because Cisco will not be the default choice, we believe its influence is likely to weaken. In addition, sales cycles will are likely to lengthen, and smaller vendors will find selling tougher,” Gartner stated.

    However, the analyst firm went on to predict that the Microsoft/Citrix partnership will face “some challenges” as the published product delivery date is “very aggressive”.

    Given these concerns it advises firms to continue their existing business-critical Wan optimisation implementations because its estimates that the Microsoft/Citrix product is 18 months away.

     


     

    NetComm Small Office Printer Server

    The new NetComm multi-function printer server (NP3680) for home and small offices, allows users to network their multi-function printers and use multiple functions, says the company.

    “Many conventional print servers have the limitation that they only support printing when a multi-function printer is networked through the printer server. The NetComm NP3680 Multi-Function server is the only product in the market that can recognise all the functions of a networked multi-function printer,” said NetComm’s David Stewart.

    According to NetComm, the NP3680 will support a range of regular USB and Multi-Function Printers from leading manufacturers as well as stand-alone scanners and USB storage devices via its two USB 2.0 host ports. The company also claims it’s the only printer server that monitors and reports ink levels (in an inkjet MFP) to all users on the network.

    RRP: $199

    See: www.netcomm.com.au

    Dell And HP Tie As Top PC Vendors

    Although HP took the number one slot for both Q3 and Q4 of 2006 in terms of worldwide PC shipments, for the overall year, the company tied for first with Dell.

    According to preliminary results from Gartner, HP’s worldwide PC shipments increased 23.9 percent, with a total market share of 17.4 percent in the fourth quarter of 2006. Dell remained in the number two position in the quarter, but its shipments decreased 8.7 percent, resulting in its market share total of 13.9 percent.

    PC unit shipments in the fourth quarter of 2006 grew 7.4 percent compared to a year ago. During the quarter, 67.3 million units were shipped. But Gartner analysts said the overall PC market was impacted by stiff competition from the consumer electronics industry and the upcoming Vista launch.

    “PC price erosion was a defining feature of the quarter,” said principal analyst Mikako Kitagawa. “In the consumer market, the PC industry battled for wallet share against other consumer electronics products, such as games consoles and flat panel TVs, while at the same time cutting prices to ensure market demand did not stall prior to Microsoft’s Vista consumer launch in January.”

    Overall in 2006, PC shipments totaled 239 million units, a 9.5 percent increase from 2005. Gartner found the Europe, Middle East and Africa region continued to be the largest PC region during the year though Asia/Pacific and Latin America also well exceeded the worldwide industry growth average. U.S. PC shipments were well below the worldwide average, showing clear evidence of market saturation, Gartner reported.

    Dell and HP shared the number one position in 2006, as both vendors had worldwide PC shipment market share totals of 15.9 percent. Lenovo came in second, followed by Acer. Toshiba moved into the worldwide top 5 table, booting off Fujitsu/Fujitsu Siemens.


     

    Acer Set To Hit Back At HP

    Acer, which was slapped with its second lawsuit in as many weeks is now contemplating taking legal action against HP. The move by HP comes as Acer starts to grab share away from HP in the US market as well as elsewhere in the world.

    Acer said that it is seeking to fully understand the nature of a new lawsuit brought against it by Hewlett-Packard (HP) and that it has referred the matter to its lawyers, according to an April 23 filing with the Taiwan Stock Exchange (TSE).

    This is the second lawsuit that HP has brought against Acer in a month for patent infringement of computer technology. HP’s strong actions against Acer apparently are aimed at preventing Acer from making strong inroads into HP’s ‘home market,’ according to sources at Taiwan-based IT makers. Acer was the fastest-growing PC maker in the first quarter among the world’s top five PC vendors.

    Acer is expected to fight back through legal actions but will continue to maintain a low profile since the company has recently stepped up cooperation with US channel operators, noted market sources.

    Acer reportedly has received a US court approval to extend the period required for the company to make an official response to HP’s previous patent lawsuit filed on March 27, noted the sources.

    Acer stressed that the interests of its channel partners and its clients won’t be affected by the complaints. Acer’s president Gianfranco Lanci may offer more details of the impact of HP’s complaints on company sales at an investors conference to be held in Taipei on April 27.

    New Logitech Mouse Works In The Air

    The latest laser mouse from Logitech claims to work not only on the desk, but also in the air in a similar way to how people use a remote to control the TV.

    The rechargeable, cordless MX Air Mouse combines three technologies – freespace motion-control, gesture command and wireless – so people can point, select and play media files with just a flick of the wrist, Logitech says.
     

    Click to enlarge
    “The MX Air mouse offers a radically new way for people to control their PC entertainment. It’s for anyone who has listened to music on their PC and been frustrated by having to return to the desk to change songs or volume. It’s for people who want to share vacation photos with friends and family without being tied to the desk. It’s for any of the millions of people using the Internet to browse and watch videos on sites such as YouTube or Facebook. It is also for people with a living-room computer or media PC who want to navigate their media content on their terms,” says Logitech Managing Director for ANZ, Marco Manera.

    The freespace technology means users can hold the mouse in any orientation, point in any direction for control. The mouse also claims to distinguish between intentional and unintentional hand movements.

    The gesture-based commands mean you can, for example, change the volume by pressing the volume button and gesturing to right – to increase the volume, or to the left to decrease it.

    And instead of a scroll wheel, the MX Air mouse has a touch-sensitive scroll panel, which you swipe your finger over. Meanwhile, media functions such as Play/Pause, Volume/Mute, Back and Select can be accessed in the air by pressing the large, orange backlit buttons with the thumb.

    RRP: $229

    See: www.logitech.com

    Epson Printer For Long-Lasting Prints

    The latest Stylus office all-in-one printer from Epson uses new inks which claim up to 120 years light fastness.

    Targeted at business users, the Stylus CX9300F printer is designed for frequent usage and reliability, the company says. The DuraBrite Ultra ink, used in the printer now claims to produce sharper black text, and up to 50 percent glossier photos, in addition to being long-lasting.
     
    The printer has four individual ink cartridges as well, so users only have to replace the ink cartridge that has been used up.

    In addition to printing, the printer combines an inbuilt colour fax and automatic document feeder. It claims print speeds up to 32ppm and copies at up to 30 pages per minute.

    It also features an integrated multi-format memory card reader, a 2.5-inch LCD viewer and supports PictBridge.
     
    RRP $249

    See: www.epson.com.au

    Toshiba Short Throw Projector With Wi-Fi

    Toshiba has unveiled a new data projector range which is designed for smaller spaces, allowing business and education users to project a two-metre screen from a one-metre distance.

    The Extreme Short Throw Projector (ESP) range includes the EX20 and EW25 DLP projectors, which are the first of their kind to come with wireless and networking capabilities as standard, the company says.

    The ESP range incorporates a different lens technology that allows the projectors to be placed as close as 50cm from the projection screen. This means no shadows on the screen when the presenter moves around the room. 

    “Education and business customers already regard Toshiba as a trusted provider of notebook computers.  By enhancing our projector range with Extreme Short Throw projectors, we now offer educators and business executives a powerful presentation tool that truly brings content to life, in small or large spaces,” said Toshiba ISD Product Manager, Cliff Evans.  

    All Toshiba projectors come with a standard 90 day replacement guarantee and a three year warranty.  In addition, Toshiba is offering a free lamp replacement for every projector purchased through 31 December 2007. 

    The ESP projector range is also Vista compatible.  

    See: www.isd.toshiba.com.au