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; } } Staff Writers, Author at Smart Office - Page 7 of 43

    Smart Office

    LG Develops Cheap LCD Technology

    According to digitimes.com, LG Display has developed what it says is the world’s first TFT roll-printing technology that can replace the photolithography process.


    Click to enlarge
    Courtesy: www.digitimes.com & LG Display

    Photolithography is a process used in TFT-LCD fabrication to form patterns on the TFT and color filter substrate and involves a complex set of processes that requires huge and costly equipment.

    However, using this new roll-printing technology instead of photolithography, the complex set of processes used to form the required patterns can be proceeded at once.

    The report notes that roll-printing technology is expected to help reduce material and equipment costs, clean room investment costs and also shorten the production time of LCDs.

    Furthermore, roll printing is an environment-friendly technology that significantly decreases the use of chemicals used in the photolithography process and is also applicable to the next-generation, flexible display technology.

     

    Telstra Capex Already Up 8%

    Telstra has only just begun its planned re-invigoration in the last three months, but the telco’s Capital Expenditure figures for the final 6 months of 2005 already show evidence of the big splurge to come.

    Telstra Chief Executive Sol Trujillo has already forewarned the country that the major telco’s planned spending pattern wouldcause a Capital Expenditure bubble over the next four years before returning to normal in 2010 fiscal year. But this was only in November last year and the company’s last half fiscal results are already showing signs of the cash going out the door.

    The company’s guidance is that a $2.5 – $3.5 bubble over fiscal years 2006 – 2008 will ultimately even out with future Capex expected to be around 12% of revenue by 2010.

    Operating capital expenditure for the half year ended 31 December 2005 increased by 8.4% or $154 million, with domesti

    c core operating expenditure of $1.8 billion increasing by 4.8% or $82 million.

    The company says the higher capital expenditure was driven primarily by growth in mobiles and broadband assets and includes the whopping $312 million it paid to access competitor Hutchison’s 3G network.

    To try to limit the spending spree, Trujillo has had the axe out cutting 15 building leases, abandoning over 400 projects that weren’t making the grade and will push some $300 million it is saving from Capex into the transformational project he is putting the company through.

    The fiscal ramifications of the increased expenditure on new infrastructure will mean that depreciation and amortisation expenses will also grow over the next few years as assets that are phased out over the 2006 and 2007 fiscal years, explained CFO John Stanhope.

    Cash flow will be impacted by our investments in capital expenditure over the next two to three years and free cash flow is expected to reflect this

    Also the second half of the 2006 fiscal year will be impacted by redundancies and other costs associated with our transformational initiatives announced in November 2005.

    The company warned that EBIT decline for the fiscal 2006 full year to be in the range of 15% to 20%, before restructuring and redundancy provisions, and 21% to 26% including restructuring and redundancy provisions.

     

    AMD, Fujitsu Float Memory JV

    AMD and Fujitsu, majority shareholders in Flash memory maker Spansion have announced the company will float as soon as practicable.

    A prospectus has been filed with the Securities and Exchange Commission (SEC) and could be finalised as early as this week.

    The going price is reportedly in the region of US$622 million pricing the stock at around US$16-$18per share for 39 million shares.

    AMD and Fujitsu will retain large shareholdings in Spansion and have transferred staff to Spansion. Indeed, some transactions undertaken by Spansion will depend on the consent of AMD and Fujitsu, including joint ventures and design and manufacturing, according to wire services.

    Financing Can Increase Deal Size

    Microsoft has launched a business finance service for the purchase of software, hardware and services, saying access to money can increase deal sizes by as much as 70 per cent.

    Typically, that figure is in the 15-40 per cent range, says Elizabeth Aris, Project Lead – Microsoft Financing at Microsoft Australia. Even better is the affect it can have on service margins, says Aris.

    When negotiating deals with a customer a little light on money, Aris says its usually the services and maintenance component that systems integrators and resellers have to hack into when trying o price a deal within a customer’s budget.

    With hardware and software pricing pretty tightly controlled y vendors, there’s not a lot of margin left to cut and so the reseller needs to find shortcuts in the offering or take a gross profit margin cut on the services component. But with a financing option available customers can be more easily afford to buy sophisticated systems.

    Microsoft announced the introduction of Microsoft to Australia in conjunction to with the local subsidiary of De Lage Landen Australia, part of a huge Dutch banking group. The Financing Program cut the average Australian company’s up-front financial investment by two-thirds with payment periods typically spread over two to five years.

    The service is meant to redress the situation that exists in Australia and globally where financing is easier to obtain for hardware investments, but almost impossible for software or services. Forrester Research estimates that while 25 per cent of hardware is bought on finance only 3 per cent of software is paid for that way. To put a dollar figure to that do the math on IDC’s prediction that in 2006 Australia will outlay $3 billion on software and a further $11 billion on services.

    Microsoft is sufficiently confident in its product and partner’s abilities to basically underwrite the money De Lage Landen lends out.

    For the resellers, access to this sort of financing can mean the difference between winning a deal and missing out. It also guarantees payment (usually) within 48 hours of approval.

    For businesses, it allows them to spread payments over several years and preserve their valuable capital. The application process is handled via the Microsoft Partner, with a simple one page application to be filled out detailing the products and services to be financed and details to allow De Lage Landen to run credit checks etc. Aris says funding can be completed within 48 hours on the deals which have a minimum investment spend of $15,000. However under terms of the deal struck with De Lage Landen (which basically provides the finance as a whitelable service), there is no minimum spend on hardware as is often the case in other deals and the mix of hardware service and software is entirely flexible.

    As long as there is at least “some little piece of Microsoft software” in the deal then it qualifies for the financing, said Aris.

    “Our mission is not to try to create a whole finance division as you have seen with some hardware vendors,” explained Aris. “We are doing it so that customers can afford to do more stuff with Microsoft product.”

    “When we talk to customers they always have this big long list of things they would love to do, but they can’t because they don’t have access to the money,” she said.

    Aris explained there is no financial incentive for the Partner, the main benefit is ability to win sales tham they might have missed without financing. “It also helps them get paid faster,” she said.

    Microsoft research has shown there is significant demand for competitive financing from customers, with more than 75 per cent indicating they would prefer a “pay as you go” payment structure.

    Partners are required to sing up with Microsoft to acce3ss the financing service but Aris says there’s nothing to stop any of them accessing the service.

     

    Kerry Stokes Says WAN Asleep At The Keyboard

    In a speech to WA Business News recently, Channel Seven head and aspiring owner of West Australian Newspapers (WAN) Kerry Stokes said that WAN have been alseep at their keyboards when it comes to implementing a digital strategy and claims this may cost them dearly in the long run

     


    Click to enlarge
    “In terms of a profitable and meaningful digital strategy, the WAN Board has quite simply been asleep at the keyboard. Their digital strategy consists of nothing more than a website that has barely evolved in eight years. To my mind it is seen as nothing more than a cost centre rather than a way to connect with customers, to cross promote, to market the brand and to ultimately make money” said Stokes, adding that, “This may make profits look good today but it threatens the long-term sustainability of earnings and dividends”.

    And Stokes knows a thing or two about digital media- with Channel 7 racking up revenues of $1.4 billion last year, Stokes notes that businesses like WAN “need to understand and exploit the interconnectivity between the different forms of media”.

    A few years ago, Stokes put his money where his mouth is and launched Yahoo!7 TV – an up-to-the-minute, comprehensive television and online resource. It supplies not only the latest TV listings but also TV-related headlines and links. Users can view daily television listings by selecting a free to air region or a Pay TV supplier.

    Only time will tell whether Stokes, who holds a 19.4 per cent share in WAN, can convince the Perth Establishment of the benefits of having such an online strategy.

    Lenovo-Branded SMB PCs in March

    Chinese PC manufacturer has included Australia as part of a major global roll-out of its brand following the acquisition of IBM’s PC Division last year.

    The new 3000 range, the first ever to be offered worldwide combines the benefits of Lenovo’s considerable experience in the consumer space with the technologies it gained through the IBM acquisition.

    Targeted squarely at the SMB space, there are several new desktop and notebook models with the latest processor technologies in a new silver chassis, says the company.

    Over and above the hardware though Lenovo brings to bear a number of built-in tools such as virus recovery, simplified network connectivity and automatic updates, al designed to simplify the IT environments in small business settings.

    For example, instead of manually locating and applying critical system updates, the Lenovo 3000 PC identifies and updates its own Lenovo software to take that arduous task off of the user, says the company. In addition, Lenovo Care tools can help users streamline maintenance tasks to keep PCs running like new.

    ThinkPad-inspired technologies and the latest Lenovo innovations are combined to create well designed, dependable PCs, said Alan Munro, Managing Director, Lenovo, Australia and New Zealand.

    The new Lenovo 3000 line includes new notebook PCs — the Lenovo C Series — and new desktop PCs — the Lenovo J Series and will be sold in addition to the legacy ThinkPad and ThinkCentre brands.

    The Lenovo C100 notebooks are designed for mobile small-business professionals. Weighing in at 2.8 kilos, the new Lenovo C100 notebook offers complete connectivity features, such as integrated 802.11 a/b/g wireless LAN, Bluetooth (select models) and 10/100 Ethernet and modem, and multimedia capabilities, such as stereo speakers with an integrated microphone for playing and recording audio and an integrated Combo or DVD Recordable drive. At 1.3-inches thin, the C100 also incorporates a 3-in-1 multi-card reader for downloading digital pictures, four USB ports and Firewire and S-Video slots.

    The C Series includes an Intel 915 GM Chipset with choice of either Pentium M or Celeron M processors. Select models also feature Intel Centrino Mobile technology. Mobile users will benefit from an 8-cell lithium ion battery offering up to five hours of battery life and Lenovo’s industry-leading keyboard.

    The Lenovo J100 and J105 desktop PCs are designed for small business customers and consumers they feature a choice of Intel or AMD configurations. The Lenovo J100 has the SiS 661 Chipset with choice of either Pentium 4 or Celeron D processors, while the J105 features an AMD Socket 754 board with either AMD Sempron or Athlon processors. Both the Lenovo J100 and J105 are equipped with serial ATA drive support, 6 USB 2.0 ports and front side audio.

    The Lenovo J Series desktop PCs and C Series notebooks will be available in Australia and New Zealand in March 2006. Australia pricing for the J105 and J100 desktop PCs will be announced by March 1st. Prices for the C100 start at AUS $1199.

     

    Culture Key To Staff Retention

    IT companies need to consider company culture in the recruitment process rather than simply throwing money at the problem says one HR specialist.

    Steve Grace, CEO of Fingerprint Consulting Services says that while IT companies are increasingly spending big money trying to retain staff, the smart players are re-assessing this practice and questioning whether they are hiring the right people in first place.

    Grace says that candidate personality and motivation are important factors to consider when hiring staff, but despite the focus all too often is on the skills a person brings to the job.

    This can be a major factor in recruitment at large companies and in outsourced recruitment where consultants or in-house hirers may not even know what sort of culture exists in the departments they are recruiting for?

    As the nation’s skills shortage increases, recruitment agency usage amongst growing and established companies is certainly on the rise, but how many are using this outsourced resource to its full potential? The answer is, sadly, all too few, says Grace.
    An employee who fits in with the company or departmental culture is more likely to stay with that organisation long term, even through the tough times. More so, a “culturally synergised department” will have better communication internally leading to a more effective workforce. But all too often this opportunity goes to waste during the hiring process.

    Grace lays some of the blame on external recruiters who don’t push the issue enough, but its also a problem caused by the client not understanding the importance of supplying the right information, often just passing on a two-year old job description and refusing to allow the recruiters to talk to the line manager in charge of the position.

    This one-dimensional briefing usually results in a ‘best fit’ for skills and experience hire with the consultants doing little more than asking a “standard set of behavioural questions, with perhaps one role-specific question thrown in,” sys Grace.

    Precious little time is spent considering whether the candidate will bring that elusive and vital quality of cultural synergy to their new role.

    Trading on Telstra Shares Halted

    Major telco Telstra has pre-empted vigorous trading on the stock exchange in response to today’s announcements by requesting a trading halt.

    The company has announced that planned restructuring and redundancies costs will have a negative impact on earnings for the next 18 months.

    The company’s Chief Executive Officer Sol Trujillo also announced today that the company plans to increase investment to as much as $3.5 Billion over the next there years as it builds a next6 generation network capable of delivering advanced integrated services.

    Redundancy provisions in the current fiscal year will increase the rate of earnings decline by as much as 30 per cent. The company has already announced a lowered earnings forecast in September this year when Trujillo told the ASX that earnings before interest and tax (EBIT) would fall between 19 per cent and 24 per cent.

    Once redundancies are factored into this the 30 per cent declines are expected to increase the decline by between 25 and 30 per cent.

    Trujillo spoke of a new economic model for the company based on revenue growth in the region of 2 – 2.5 per cent per annum.

    The statement to the stoack exchange said “The securities of Telstra Corporation Limited (the “Company”) will be placed in pre-open at the request of the Company, pending the release of an announcement by the Company. Unless ASX decides otherwise, the securities will remain in pre-open until the earlier of the commencement of  normal trading on Wednesday 16 November 2005 or when the announcement is released to the market.”

    Toshiba 20 Years On

    In 1985 Toshiba launched the world’s first notebook computer, the T11. Weighing in at a hefty four and a half kilos, an Intel 086 CPU and 256Kb RAM and no hard drive, just a 720K floppy.

    Priced at around US$4500, the T11 was pretty advanced for its time. The notebook was a good seller – the company shifted 11,000 units in

    the first year and it wasn’t even a full year.Twenty years after the launch of the first notebook computer, Toshiba’s Australian Information Systems Division is well past the million mark. Toshiba reached the one million notebook milestone in March last year, just as Ralph Stadus left the company, handing Mark Whittard the reins.
    Prior to 1985 Toshiba was a consumer products business in Australia. The 130-year-old company is highly diversified with 161,000 employees worldwide, and consolidated sales of over US$55 billion. The present day Toshiba has a dual history. In 1875 Tanaka Engineering Works became Japan’s first manufacturer of telegraphic equipment and later one of Japan’s largest manufacturers of heavy electrical apparatus. In 1890, Hakunetsu-sha & Co began making light bulbs, diversified into consumer products and was renamed Tokyo Electric in 1899. In 1939, they merged to form an integrated electric equipment manufacturer under the name Tokyo Shibaura Electric before becoming Toshiba in 1978.

    In Australia, Toshiba has operations in Consumer Products, Imaging and Medical, but it is the company’s Information Systems Division (ISD) which is responsible for the family of notebooks. Mark Whittard took over as general manager of the ISD last May, as Stadus retired from 12 years as a general manager in the PC business with Digital, Dell and Toshiba.

    Mike Sager, PC Analyst at IDC Australia, points out that Tosh hasn’t been out of the number one spot in the notebook market much recently. Seven out of the last nine calendar quarters is a good record during a time of leadership change. “Once in a while someone might tip them into second place,” he says. “It’s difficult to be number one all the time.”
    The first time was second quarter 2003. It happened because HP was doing great deals bundling an iPaq with their notebooks. The second time was first quarter this year. Of the factors at play in the latest shove, biggest was probably its standout quarter at the end of 2004 – getting a lot of stock out into the channel one month is hard to do again the next.

    Releasing the Q1 figures last month Sager said the Ingram/Tech Pacific merger had affected the market: “With so many vendors at Ingram, companies have to fight to hold their ground, so they are looking at their channel strategy.” Toshiba did and joined Acer at Brisbane’s Cellnet Group, as did HP. Both said it was to access the increasingly important telco market. As well as being a major distributor of mobile phones and accessories, Cellnet includes general computing distributor IT Wholesale. “If you want Queensland, you need ITW,” Sager adds.
    Whittard explains why that decision was made: “The customers are looking at buying that equipment together, so they know it works together. Also the traditional telco sellers were asking for product more and more often. We had been holding them off.” Whittard told SmartOffice Reseller he was watching the Smartphone market but made no commitment to enter it, though bundling 3G cards is…on the cards.

    MIXED BLESSINGS

    The PDA market is “not setting the world on fire”, Whittard says, but the pocket PC has never been a big part of ISDs business. He all but gave up the space to the handset manufacturers, though admits Toshiba does have product in that space.
    Mercie Clement, handheld analyst for IDC Australia, points out that one of the key factors in entering the Smartphone market in Australia is a relationship with one of the carriers. “They would have to get on with a carrier before Tosh could make it there,” she said. “The criteria are different for each of the carriers and it is a lengthy process. You have to have internal expertise to get it into the channels and markets.”

    Meanwhile, the notebook business has been a bit of a mixed blessing since Whittard took office. Though growing at 19 per cent, Whittard’s main business in commercial notebooks has also come under pressure. Since the introduction of new brands Asus, LG and Samsung into the competitive mix, the local dynamics of the market have been upset.

    In response to the invasion of its market share, Acer has cut prices which in turn puts pressure on Toshiba, says Sager. So as these new, well-branded competitors have gobbled up much of the growth from potential whitebook sales, it has also eaten into the growth that could have gone to the traditional players Tosh, HP, IBM, Dell and Acer.
    Toshiba’s strategy, according to Whittard, is two-fold. Notebooks are a commodity product at a price point and you have to be at every price segment with good quality features. Tosh can do this with economies of scale. Then, maintain differentiation through technology. At the moment that’s tablets, size, AV. Soon it will be Fuel Cells, that sort of thinking.
    Another point Whittard makes is that Toshiba sees its competition as the desktop market, not notebook manufacturers. “We don’t take it to our competitors head to head, we are about converting the desktop. If we can convert desktops across we’ll get 30 percent of that,” he says.
    It might not be a hollow promise. In Australia notebooks already constitute 35 to 40 per cent of the total PC market, he points out, and for the first time in the US notebooks now outsell desktops.
    Sager warns that Toshiba needs to stay out of the line of fire or it
    might get hurt by competitors trying to get marketshare. “Other vendors are doing things that might be considered crazy,” he says.

    Tosh needs to maintain its high presence in the channel, maintain its place in the market with low price, low spec, but do that without competing at the low-end and bringing the brand down. Sager says the company’s main strengths are the brand, channel relationships and product. That’s a good mix to have.

     

     

    Amazon Checkout Set To Kill PayPal

    According to reports, Amazon.com has decided to take ecommerce by the horns with two new payment options– Amazon Simple Pay and Checkout were launched today and are designed to directly compete with both Google Checkout and eBay’s PayPal.


    Click to enlarge

    According to the company, Checkout by Amazon is a complete e-commerce checkout solution, while Amazon Simple Pay enables payments, marketplace transactions and even donations.

    Checkout by Amazon is designed to identify Amazon.com customers and offer the now standard Amazon 1-Click experience, and also designed for merchants to upsell their products through the checkout pipeline.

    For transactions of $10 or more, the Amazon service incurs a 2.9% mark-up plus 30 cents per transaction; however transactions less than $10 will cost 5% plus 5 cents per transaction. By comparison, PayPal charges 2.9% plus 30 cents per transaction for monthly sales up to $3,000.

    Furthermore Checkout allows customers to view, edit, settle, and cancel orders; search orders by date; download orders in a text file; and print shipping labels and packing slips, as well as allowing merchants to co-brand the checkout pipeline with their own logo.