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 TBOadmin123, Author at Smart Office - Page 2 of 7

    Smart Office

    Google Delivers Business Email Security

    Google has announced a new suite of security products which the company says will provide businesses an affordable way to improve the security of their email.

    The security services ‘Powered by Postini’ work with any mail system, including Microsoft Exchange and Lotus Notes, and are designed to deliver message filtering, encryption and archiving for businesses.

    Customers can sign up online and pricing for the services starts at $3 per user per year.

    “As threats rise in volume and complexity, and compliance requirements pile up, IT is struggling to find the resources to keep up,” said Google director of product management, Scott Petry. “Now, Google can take care of this for you. Organizations of all shapes and sizes can get access to Google’s industry leading security and compliance technologies.”

    The services on offer, according to the company, include:

    Google Message Filtering

        * filters incoming spam and malware
        * for companies looking to handle the growth of spam, virus and other email threats, and want to shift the burden off of on-premises resources
        * $3 per user per year

    Google Message Security

        * includes Google Message Filtering, plus enhanced virus detection, outbound processing, and content policy management
        * for companies worried about growing external security threats and internal risks, such as email data leaks or content compliance violations
        * $12 per user per year

    Google Message Discovery

        * includes Google Message Security, plus one year of message data archiving, retention, and discovery
        * for companies seeking to reduce security exposure, and improve legal discovery readiness and message compliance
        * $25 per user per year for one year of archived data (additional years of data retention available separately)

    The new packages are part of the Google Apps platform and are available immediately at www.google.com/a/security, direct from Google, and through channel partners, and can be deployed within hours, the company says.

    Consumers Will Spend Spend Spend Claims Access Economics

    Despite warnings from GfK consumers are set to continue spending on CE products according to a retail report prepared by Access Economics and set to be released today.

    According to the Melbourne Herald Sun Access Economics Claim that consumers will shrug off interest rate rises and volatility in the share market and continue spending.

    “The fundamental supports are in place for a spender-bender 2007-08 the Melbourne Herald reports.

    Retail is travelling at its fastest pace since the east-coast housing surge faltered in early 2004,” the report says.

    “We see gains in retail turnover volumes peaking at 5.1 per cent in 2007-08 before moderating to 3.3 per cent in 2008-09 and bottoming at 1.4 per cent in 2009-10.”

    This comes after some of the country’s biggest retailers have shown strong profit growth during the recent reporting season.

    A surge in demand for plasma-screen televisions helped stand-out performer Harvey Norman lift profits 77 per cent to $407 million.

    The most recent Australian Bureau of Statistics data shows sales growing at almost double expectations to $19.4 billion.

    The ABS figures show that in the past four years, monthly consumer spending has risen almost 30 per cent from just over $15 billion to $19.4 billion.

     

    Yesterday’s Westpac-Melbourne Institute survey also showed a 4.2 per cent rise in consumer sentiment this month.

    Westpac chief economist Bill Evans said the survey findings showed confidence was highest among the younger generation and ALP voters.

    “Steady interest rates, a modest fall in petrol prices and continuing good news on the labour market and the broader economy would have been the supporters of the index,” he said.

    “These factors have clearly offset any concerns emanating from global financial markets.”

    The Westpac survey showed that confidence among consumers aged 18 to 44 was up 7 per cent, while those over 45 were much less optimistic, up only 0.6 per cent.

    According to the Australian Institute of Petroleum, prices at the bowser have fallen 2.5 per cent since the end of July.

    But CommSec chief equities economist Craig James said the strong oil prices of recent weeks could threaten petrol prices, which are currently close to a five-month low.

    “We expect oil prices to remain high in the short term, but gradually ease over the latter months of the year in line with normal seasonal practice,” he said.

     

    Union Peddling Lies & Untruths Over A380 Incident Claims Qantas

    The union representing Qantas Licenced Aircraft Engineers appear to have had a lapse in intelligence after they started peddling fear and untruths about the recent Qantas A 330 incident over Indonesia says Qantas.


    Desperate to push their case the Union claimed that engineers were set to be stood down because of the incident which saw the entire fleet of Qantas flights grounded after an engine exploded.Qantas claims this is blatent lies  and that ALAEA federal secretary Steven Purvinas is taking advantantage of a situation to “peddle lies”

    Qantas chief executive Alan Joyce said in a statement that Mr Purvinas was wrong to say Qantas engineers has been stood down because of the incident on QF32, which was forced to turn back to Singapore following the explosion.

    He said the cause of the engine failure was still being investigated, but it appeared likely to be a design problem.

    Joyce, said Mr Purvinas was wrong, and that he and the Union had demonstrated yet again that he was prepared to go to any lengths to further his industrial agenda.
    “It is clearly too soon to speculate on the cause of yesterday’s engine failure,” Mr Joyce said.

    “Regardless, Steve Purvinas continues to peddle prejudices and generalisations about aircraft maintenance and safety in the knowledge that his claims will more than likely go unchallenged. “The engineers he has referred to in a number of media interviews today are employed by QantasLink in Brisbane and are involved in ongoing enterprise agreement negotiations. Six employees were directed not to attend work last week, on full pay, while a disciplinary matter is appropriately investigated. This has nothing to do with our A380 fleet.”

    “Mr Purvinas also continues to raise overseas aircraft maintenance as though this was something only Qantas was not allowed to pursue. The overwhelming majority of our aircraft maintenance is undertaken in Australia, and he knows this.

    “We operate an international airline and aircraft that are manufactured overseas so it is inevitable some need to be serviced overseas and that has always been the case.
    “The A380 involved in the Singapore incident recently underwent its first heavy maintenance check by Lufthansa Technik in Germany. Lufthansa is a leading international airline, a top tier engineering and maintenance provider and an operator of the A380 itself. Rolls-Royce Trent 900 engines are overhauled at
    Rolls-Royce facilities.

    “To suggest that Lufthansa and Rolls-Royce do not have the expertise and experience to undertake the highest quality aircraft and checks is ludicrous.
    “All Mr Purvinas is interested in grabbing is a headline, regardless to the damage to the reputation of Qantas and its employees including members of his own union”
    Mr Joyce also confirmed that Qantas met all the requirements of two Airworthiness Directives (ADs) applying to the Trent 900 engine.

    “We take compliance with any Airworthiness Directives extremely seriously,” he said. “Two ADs applied to the Trent 900 engines we use on our A380s. One is no longer relevant to Qantas following an engine modification, and we are fully compliant with the other. Any claim otherwise would be wrong.

    A short while ago Qantas said that the Qantas B747-400 dispatched as a relief flight last night to Singapore to bring passengers affected by yesterday’s QF32 engine failure was scheduled to depart Singapore at 10.30am local time. QF8032 is expected to arrive in Sydney at 8.45pm tonight.

    Qantas continues to provide assistance to customers affected by the temporary suspension of A380 operations, including hotel accommodation, where needed, and meals, as arrangements are made to get people on flights as soon as possible. All available Qantas aircraft capacity is being used and the airline is also in discussions with other carriers regarding aircraft charter options in addition to the QF10 charter listed below.

    Qantas continues to work with Rolls-Royce and Airbus to fully understand the circumstances surrounding the engine failure ahead of taking the first steps toward to resuming operations. It is still too soon to be able to provide an indication of when this might be.

    Sensis Sells Off SMB Division

    Sensis has sold its small-business technology operation, Invizage, to startup IT services company PK Business Advantage (PKBA) for an undisclosed but presumably large sum. This almost doubles PKBA’s headcount and significantly expands its Australian footprint to cover each Australian State.
    The acquisition of Invizage was funded by shareholders, and was for a cash
    consideration, PKBA founder Peter Kazacos confirmed yesterday. It lifts the
    company’s headcount from 80 to 150, and, according to Kazacos, will add 7000
    customers to the 1000 PKBA already had on its books. It is the company’s
    fourth acquisition in six months.

    For Kazacos, who also founded Kaz, (later purchased by Telstra for a
    handsome sum), it is something of an ironic turnaround to now find himself
    purchasing a little piece of Telstra (the telco owns Sensis), but he has
    been eyeing Invizage for some time.

    “One of the benefits of being inside, (is) I knew it existed,” Kazacos
    confides, “I can’t give you a time as to when we actually did it, but it’s
    been in the plan.”

    The acquisition gives PKBA a presence in WA, Brisbane, Melbourne, and
    Sydney’s North Ryde, and adds to its existing facility in Adelaide. An
    earlier PKBA acquisition, Comstra, is located in Tasmania.

    “Particularly, I was keen to get coverage across all of Australia,” Kazacos
    notes. With the acquisition, PKBA inherits Invizage’s billing systems,
    customer base, and a well-known brand in PKBA’s target SMB market. “We’re
    planning on using the Invizage brand as our brand for managed services,”
    said Kazacos yesterday. Invizage employees will be retained, he added: “The
    great thing is there’s no overlap.”

    PKBA, which has been trading officially since last month, has acquired
    regional-based IT companies in SA, North Queensland and Tasmania.

    Invizage was established in Melbourne in 1995 and purchased by Sensis two
    years ago. Chris Smith, general manager Sensis Interactive, said the sale to
    PKBA meant the business would keep its profile in the IT-services market for
    small business.

    Earlier this week, Sensis announced revenue growth of 8 percent in the
    2006-07 financial year to $1.97 billion. Invizage’s performance was not
    reported, Sensis instead highlighting its $1.5 billion directories business,
    voice portfolio and “emerging businesses”. Sensis owns the Yellow and White
    Pages, Trading Post, CitySearch and Whereis brands. – Dorothy Kennedy

    Sound Future For In Car Infotainment?

    In car navigation and entertainment systems are getting ever more sophisticated, and distracting for drivers. But how far can the connected revolution for in-car entertainment and navigation go?


    Click to enlarge

    While integrated hard disk drives are disappearing from cars, the days for optical drives for CD and DVD are also numbered, according to research firm iSupply, in favour of digital in-car systems, devices like smartphones, and playing music off a USB or SD card. 

    Its predictions that iPads will also make their way into in-car infotainment as a backseat entertainment unit have already been realised by Range Rover, although a visit to any car forum on the net will show that there are several fanatics who have also included iPads on their dashboards.

    But what of the safety concerns? The Federal Government is currently investigating safety initiatives governing smartphones, navigation and other technology in cars following research released by the NSW Police and the RTA that revealed that up to 30% of people involved in accidents had been talking on a mobile phone or were sending a  text message while driving.

    “Road Safety is a very emotive issue,” said Graeme Redman, managing director of digital radio manufacturer, Pure Australasia. “If the traffic authorities have anything to do with it, it will be banned altogether.” 

    Last week, BMW became the first to offer digital radio as an add-on in their Series 5, 6 and 7 in Australia, with several other audio firms waiting in the wings to launch new products. 

    Speaking at the launch of a new subscription music service available to digital radio users, Redman said: “The problem is that drivers cannot manage the level of distractions they are subjected to yet. But, where safety is a concern, there may be moves to disable the information displays and still enable systems to play digital radio in the car,” he said. 

     

    Click to enlarge

    Orion has recently released an all-in-one system that packs navigation, safety, hands-free calling and multimedia into one in-car receiver. The AVR6.1 is a good example of what infotainment systems can offer today.


    With Australia gradually tuning into digital radio, at least in the capital cities, a DAB+ receiver comes standard in the unit. DVD and CD readers are part of the package, but are overshadowed by digital media inputs like SD, USB, Aux and Bluetooth.

    Some of the staples of modern in-car entertainment systems include Bluetooth connectivity for mobile phone integration and navigation options in tow. Motorola is taking these utilities and integrating them with its smartphones and the car dashboard.

    “Motorola has released its first generation of in-car entertainment products that compliment handsets,” said Angela Menabue, Motorola’s Business Manager for Companion Products.

    The In-Car Defy dock and Milestone2 docks integrate smartphone functionality to the (almost) hands-free entertainment experience.

    The Defy dock plugs a Motorola Defy into the car’s entertainment system with a clean, six button interface that stores everything from widgets and apps to navigation and entertainment.

    “It’s part of Motorola’s vision to create greater ecosystems, and we’ll see more of this with future products,” Menabue added.

     

    Throwing apps into the equation, just like smartphones and tablets, also looks to be part of the future of in-car infotainment systems, and the companies involved are already seeing growth.


    “We’re seeing a lot more apps being developed by third parties and people like Google. There’s the MotoSpeak app for in-car systems, for instance, that’s made specifically by Motorola.”


    Click to enlarge
    The Asteroid, from Parrot is due in Australia around July/August

    Parrot has taken this straight into the in-built car receiver with its Asteroid platform that integrates web apps and hands-free calling into a typical music player-style fixture.


    “We’re also looking to add text-to-speech later this year so you can do things like dictate text for SMS,” said Peter George, Parrot’s Country Manager for Australia.

    Parrot anticipates a launch of Asteroid around the July/August mark in Australia, bringing with it a slew of apps like Google maps, internet radio options, navigation and even services like Skype, though “that’s just the beginning,” according to Peter.

    While entertainment fixtures in cars are getting an upgrade, GPS units are also upgrading and tailoring themselves to the connected user.

    Marketing Manager for TomTom’s Asia Pacific unit, Nick Saisanas said that the in-car device market would probably see a move toward connected devices with dynamic content like sending traffic information to and from navigators.

    He points to a move from solely GPS to integrating GPRS – the difference being that GPRS is a data service technology that allows information to be sent from the device. 

     

    TomTom currently uses iQ Routes as a traffic condition notifier on its GPS units, but this software is based on historical data. What GPRS integration does is add the ability to send traffic data from the navigator so that everyone can have access to up-to-date traffic information.



    Click to enlarge
    Garmin uses an FM traffic subscription service to get data from an FM traffic antenna.

    Garmin currently uses an FM traffic subscription service that allows compatible devices to get traffic data from an FM traffic antenna/receiver.


    GPS companies are finding that their devices are changing to suit the style and functionality of a smartphone to stay ahead on the market. This means more functionality on a thinner unit with a bigger screen.

    “With everyone having a smartphone or iPhone, [GPS] units are getting slimmer and we’re adding dual orientation like a smartphone,” said Ian Edwards, National Sales Manager at Garmin.

    Apps jumping into the driver’s seat are extending into GPS navigation, with the big companies hopping onto the smartphone and tablet bandwagon.

    TomTom’s Nick Saisanas said that while the TomTom iPhone app was not garnering very large revenue compared to the main GPS devices, it was seeing growth.

    LG Steals $430m Ad Account From Dyson

    Korean electronics-maker LG Electronics is expected to recruit WPP Group’s MindShare to handle its global US$350 million media account, according to AdAge in New York.

    The decision is the latest in a string of account reviews for the company, which recently appointed its first chief marketing officer, Dermot Boden, who previously ran Pfizer’s operations for Asia.

    LG recently consolidated creative duties at Publicis Groupe-backed Bartle Bogle Hegarty, which will now look after the brand’s product and branding account for its four core divisions: mobile communications, digital media, digital appliances and digital display.

    According to AdAge however, LG’s US$350 million deal has stolen Bartle Bogle away from vacuum-maker Dyson, an account which has been active since 2005.

    “The relationship has come to an end as a result of LG,” an executive familiar with the matter, who called the decision “mutual,” told AdAge.

    Dyson spent US$45 million on US measured media in 2006, and US$37 million through September 2007, according to TNS Media Intelligence.

    News of this assignment comes amidst a marketing overhaul for LG, which has seen the electronics-maker announce its new CMO, Boden, will develop a global-marketing strategy for the brand and upgrade its marketing systems, according to AdAge.

    OZ Retailers Facing Mastercard & Visa Problems Today

    Australian retailers may have a few problems today processing Mastercard transactions after a group known as Anonymous hacked into the company’s online operations following Mastercard’s decision to stop processing payments to the whistle-blowing site Wikileaks.

    In what they called “Operation Payback”, a network of online activists have targeted firms including Mastercard and Visa, in the latest front of the battle over leaked US diplomatic cables.

    The group, known as Anonymous and thought to be 1,500 to 2,000-strong, flooded the websites of the credit card companies, and that of the Swedish prosecution authority, with millions of bogus visits.

    Their attack came after the financial giants, along with the online payment firm PayPal, announced they would no longer process donations to the anti-secrecy group.

    The credit card sites among several targeted by the group of hackers, who have pledged to pursue firms that have withdrawn services from Wikileaks. In other moves consumers are reporting that Visa’s website appears to be experiencing problems. Anonymous also claimed to have attacked Visa.

    A Harvey Norman franchisee said it was too early to tell whether there were problems in Australia while a JB Hi Fi operator said that to date no issues have been reported.

    In the UK the BBC was contacted by a payment firm linked to Mastercard that said its customers had “a complete loss of service”.

    In particular, it said that an authentication service for online payments known as Mastercard’s SecureCode, had been disrupted.

     

    Other readers have also said that they have had problems with online payments. The scale of the problems is still unclear.

    Mastercard has not responded to the claims.

    It said in a statement that it was making “significant progress” in restoring full service to its website as we wrote this story.

    “Our core processing capabilities have not been compromised and cardholder account data has not been placed at risk,” it said.

    “While we have seen limited interruption in some web-based services, cardholders can continue to use their cards for secure transactions globally.”

    Annonymous said that websites that are bowing down to government pressure have become targets.”

    PayPal, which has stopped processing donations to Wikileaks, has also been targeted. On Monday the US owned firm said Wikileaks’ account had violated its terms of services.

     

    “On 27 November the State Department, the US government, basically wrote a letter [to Wikileaks] saying that [its] activities were deemed illegal in the United States,” PayPal’s Osama Bedier told the Le Web conference in France.

    Before the Mastercard attack, a member of Anonymous, who calls himself Coldblood, told the BBC that “multiple things” were being done to target companies that had stopped working with Wikileaks or which were perceived to have attacked the site.

    “Websites that are bowing down to government pressure have become targets,” he said.

    “As an organisation we have always taken a strong stance on censorship and freedom of expression on the internet and come out against those who seek to destroy it by any means.”

    “We feel that Wikileaks has become more than just about leaking of documents, it has become a war ground, the people vs. the government,” he said.

    Supporters of Australian Julian Assange yesterday also launched cyber attacks on the Web site of the Swedish prosecutor’s office which is seeking the extradition of Assange form the UK over sexual misconduct charges.

    PandaLabs, a malware detection laboratory, says that the prosecutor’s Web site, aklagare.se, was brought down by members of the cyber “hacktivist” group.

     

    The attack came as Assange was refused bail by a British judge over the charges that aim to have him extradited to Sweden.

    Sean-Paul Correll, a threat researcher at PandaLabs, confirmed that the group had launched the attack, not only on the Swedish prosecutor’s Web site but also others including PayPal and the Swiss Post Office bank which have frozen WikiLeaks accounts – though the Swiss bank says he can have the $41,000 proceeds as soon as he establishes another, legal, account, something that may be difficult if he’s languishing in a Stockholm jail.

    How To Redesign Your Web Site

    Having a web site is critical today for any small- medium business. But what is more important is having a web site that is smart and appeals to visitors so that they keep returning.

    If you don’t keep improving your site on a regular basis, you may as well be serving sales prospects day-old doughnuts or sending out holiday cards in January. Want to hold the attention of your Web audience? Pay attention to your site. Here’s a roundup of our favourite articles to help you make improvements.

    Make Sure Everything Clicks

    The Perfect Host

    All Web hosts are not created equal. Our  technology columnist Anne Stuart describes how to evaluate Web hosts and to choose the one that’s best for your business.

    Checklist: Monitor Your Web Site’s Performance

    Discover what aspects of Web site performance are critical to your e-commerce success.

    Make Sure Your Web Site’s Working for You

    Internet logjams losing you sales? Speed up your site with these smart strategies.

    Weed Out Your Weak Links

    Everyone likes to link to other sites because, well, that’s what you do on the Web. But having too many links — or outdated links that don’t work — will distract and dismay your visitors.

    Site Maintenance Utilities

    Here’s an overview of various HTML checkers, which can help ensure that your Web-site visitors have an error-free experience on your site.

    Content Is King

    Writing Well on the Web

    Hardly anybody really likes reading online. No surprise there, since so many websites are so poorly written. Here are easy ways to make your Web words more reader-friendly.

    Traffic Magnets

    With imagination and a clear sense of their customers, Earth Treks and Merriman Capital Management keep their Web visitors coming back for more.

    Blogging for Business

    Blogging has been popular with teens, geeks, and flamboyant extroverts for years, but today, it’s garnering more attention from businesses as a way to connect with customers and prospects.

    When Blogs Go Bad

    Blogs can be a great marketing tool. But when they bite back, it’s all about damage control.

    Blog Rules

    The blogosphere is a world unto itself, with its own set of rules and regulations. Newcomers break them at their own peril. Here’s what you need to know before jumping into the fray.

    The Top 10 Things You Should Know Before You Blog

    Three business blogging experts share their best tips for getting started in the blogosphere.

    Don’t Focus on the Razzle-Dazzle

    Flashy graphics and shock-wave downloads do not a successful site make. Content is what really brings back customers.

    Create Your Own Web Content

    To take the last article a bit further, good content brings back customers. Second-rate editorial and graphics will send them away faster than an e-mail chain letter. Here’s how can make your site full of the former.

    Proofread Your Content

    There are a distressing number of typo-ridden, grammatically incorrect Web sites out there. Stand out by showing your potential customers that you pay attention to detail.

    Know What Your Users Want, and Give It to Them

    The Survey Says…

    Want to know what consumers think? Put down the comment cards and poll them online instead.

    The Skinny on Survey Software

    With more than 100 online polling software packages to choose from, picking the right one can be tricky. Here, three options to suit various needs.

    May I Help You

    New live-chat software helps Web merchants convert browsers into buyers.

    Live Aid

    There are scores of live-chat vendors, and finding the right one can be tricky. Here are three options to suit your various needs.

    Capture, Capture, Capture

    How to make every visit to your website a marketing goldmine.

    Pumping Your Visitors for Information

    Improving your site means getting inside the heads of your users. Here’s how you can do it without seeming like a telemarketer calling at dinnertime.

    Come In. I’ve Been Expecting You

    If you don’t treat visitors like they are the only person in cyberspace, don’t expect them to stick around. And personalization doesn’t need to be expensive.

    Building Your Brand in Cyberspace

    Building Brands on the Web: An Old Game with New Rules

    E-commerce may be changing the rules of business, but most of the traditional laws of marketing still apply. Here’s how to plan for the long-term success of your site.

     

    IBM Slashes Oz Jobs

    IBM Australia is set to slash jobs and restructure its operations. It is also shifting services work to Asia.

    The move comes at a time when IBM is tendering for work in Australia with major parts of the contracts based on work being done in India or outside of Australia. IBM has said that it is cutting hundreds of jobs amounting to three per cent of its Australian workforce.

    “This quarter IBM Australia is redeploying a number of employees across the business,” he told CDN. “Less than 3 percent of IBM Australia’s current workforce will be affected by this action.”

    The spokesman said the move is part of a rebalancing of its workforce to meet changing needs of its clients and to remain competitive.

    “This is especially so given that we run a solutions and services business operating in a globally competitive marketplace,” he said.

    “IBM Australia has a strong track record in successfully redeploying employees across the organisation, and will provide assistance, skills training and support for those affected to find other roles within the organisation. However, we expect some redundancies may result.

    “To put this figure into context, in the first quarter IBM Australia brought nearly twice this number of employees into the business in response to client demand for specific skills.

    “IBM continues to retain and win new business in the marketplace. In recent months we have signed significant agreements with clients such as Telstra, Russell Investment Group, Medibank Private, Mater Health Services, Ricoh, NAB and Queensland Government.”

    The jobs to go are said to be spread across the company, which has a workforce of around 10,000 in Australia. Some of the jobs may go to India under offshoring arrangements. – Kate Castellari