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; } } Credit Archives - Smart Office https://smartoffice.com.au/category/credit/ Thu, 16 Nov 2017 00:10:40 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 Mastercard Plans Oz Global Hub https://smartoffice.com.au/mastercard-plans-oz-global-hub/ https://smartoffice.com.au/mastercard-plans-oz-global-hub/#respond Thu, 16 Nov 2017 00:10:40 +0000 http://smartoffice.com.au/?p=95786 SYDNEY – Mastercard is setting up a new global tech hub and “innovation centre” in the inner Sydney suburb of St Leonards – one of five such centres Mastercard is establishing around the globe. All current Sydney-based employees are expected to move move to the new location. “As the Internet continues to reshape the payments ... Read more

    The post Mastercard Plans Oz Global Hub appeared first on Smart Office.

    ]]>
    SYDNEY – Mastercard is setting up a new global tech hub and “innovation centre” in the inner Sydney suburb of St Leonards – one of five such centres Mastercard is establishing around the globe.

    All current Sydney-based employees are expected to move move to the new location.

    “As the Internet continues to reshape the payments industry and create new opportunities, business must evolve their offerings to keep up with new demands,” said Mastercard Australasia division president Richard Wormald in a media release

    “Mastercard is leading the way, acquiring assets that place innovation at the core of our offering and bringing together all of our 560 Sydney-based people to unite in a practice of innovation.”

    Design and building of the new centre is expected to begin this year. Employees are expected to begin moving in from mid 2017.

    The post Mastercard Plans Oz Global Hub appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/mastercard-plans-oz-global-hub/feed/ 0
    CE & IT Industry Now In The Hands Of The Dollar https://smartoffice.com.au/ce-it-industry-now-in-the-hands-of-the-dollar-2/ https://smartoffice.com.au/ce-it-industry-now-in-the-hands-of-the-dollar-2/#respond Thu, 06 Jul 2017 05:47:54 +0000 http://smartoffice.com.au/ce-it-industry-now-in-the-hands-of-the-dollar-2/ Consumer electronics, IT and Hi Fi vendors are set to get hit hard by the falling Australian dollar. Yesterday Sony announced price increases by up to 30% with both Samsung, LG and Panasonic saying that they will have no price increases untill the new year when it expected that they will lift prices by up to 15%.

    The post CE & IT Industry Now In The Hands Of The Dollar appeared first on Smart Office.

    ]]>
    Consumer electronics, IT and Hi Fi vendors are set to get hit hard by the falling Australian dollar. Yesterday Sony announced price increases by up to 30% with both Samsung, LG and Panasonic saying that they will have no price increases untill the new year when it expected that they will lift prices by up to 15%.

    Speaking at the 2008 SmartHouse “Best Of The Best Awards” Carl Rose the Managing Director of Sony Australia told a large audience of industry executives that that one key issue will dominate the consumer electronics industry in the first quarter of 2009 price rises and the “dollar, dollar and the dollar”.

    Overnight the dollar has dropped  following the release of a US manufacturing activity report which is the worst in 26 years added to evidence the US was already in recession. A smaller than expected interest rate cut from the Reserve Bank of Australia (RBA) today is tipped to give the domestic currency a short-lived boost, but weaker than forecast domestic retail sales data could spark fears about the local economy.

    Already CE and IT distributors are feeling the effect of the falling dollar with some analysts now predicting a $0.60 dollar by Xmas which could result in further price hikes especially from Japanese manufacturers like Sony, Sharp, Pioneer, Mitsubishi and Fujitsu who are also having to battle the value of the Yen to the US dollar.

    At 7am AEDT, the dollar was trading at $US0.6453/57, down marginally from Monday’s close of $US0.6465/70.  During the offshore session, the local unit traded between a midnight low of $US0.6384 and a late high of $US0.6482.

    Risk appetite for high-yielding currencies came under pressure after the Institute for Supply Management’s US manufacturing report for last month posted its weakest reading since May 1982.   Manufacturing sector activity fell to 36.2 points in November, down from 38.9 in October, with a reading below 50 indicating a contraction.

     

    The dollar and the euro both weakened as equity markets struggled, with Wall Street’s S&P500 index losing more than five per cent during New York trade.  Bank of America senior currency strategist John Rothfield said the dollar and the euro recovered from their session lows later in offshore trade as US Federal Reserve chairman Ben Bernanke said the central bank would buy more longer-dated US Treasury notes.

    “That’s weighing a little bit on the US dollar, just this idea the Fed is doing what it can through quantitative easing to support the US economy,” Mr Rothfield said from San Francisco.  The supply of US dollars would increase if the US Fed bought more US Treasury bonds.

    With debt futures already pricing in a 100 basis point rate cut from the RBA, Mr Rothfield said the dollar would enjoy a temporary rally if interest rates were eased by a lesser 50 or 75 basis points.

    “That would be a temporary phenomenon until markets assessed if the Reserve Bank is behind the curve,” he said.  “Although the Australian dollar is undervalued, I’m not confident that if you get a spike you’ll get follow through.”

    A one percentage point move would take the cash rate to 4.25 per cent for the first time since May 2002.

    The RBA annoucement is due at 2.30pm AEDT.

    Australian retail sales data for October is due at 11.30am AEDT, with economists expecting a 0.4 per cent decline, seasonally adjusted.

    Mr Rothfield said a bigger than expected contraction in retail trade would spark a sell-off in the dollar, as traders worried about the possibility of the domestic economy sinking into a recession, despite assurances to the contrary from the RBA and the Treasury.

    “The onus is on the data to show the official sector is right in predicting no recession,” he said.

    The post CE & IT Industry Now In The Hands Of The Dollar appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/ce-it-industry-now-in-the-hands-of-the-dollar-2/feed/ 0
    OZ Interest Rates Not Cut As Expected https://smartoffice.com.au/oz-interest-rates-not-cut-as-expected-2/ https://smartoffice.com.au/oz-interest-rates-not-cut-as-expected-2/#respond Thu, 06 Jul 2017 05:47:00 +0000 http://smartoffice.com.au/oz-interest-rates-not-cut-as-expected-2/ At its meeting today, the Australian Reserve Bank Board decided to leave the cash rate unchanged at 3.25 per cent. In a statement to the markets Board Govenor Glenn Stevens said that Australia was in a better position than a lot of other Countries and that demand had not weakened.

    The post OZ Interest Rates Not Cut As Expected appeared first on Smart Office.

    ]]>
    At its meeting today, the Australian Reserve Bank Board decided to leave the cash rate unchanged at 3.25 per cent. In a statement to the markets Board Govenor Glenn Stevens said that Australia was in a better position than a lot of other Countries and that demand had not weakened.

    The statement said that recent data confirm that the world economy has remained very weak following the sharp decline in demand that occurred late last year. The major industrial economies reported large contractions in output in the December quarter, as did a number of emerging market economies across Asia and eastern Europe. Many countries are likely to be experiencing further falls in output in the current quarter.

    Conditions in global credit markets have improved since November, but sentiment remains fragile. Share prices have weakened and banking systems in several major countries are still under pressure, as authorities work towards a resolution of the balance-sheet problems. Significant macroeconomic policy stimulus is being put in place around the world, but it is too soon to see the effects of those measures.

    In Australia, demand has not weakened as much as in other countries and, on the basis of currently available information, the Australian economy has not experienced the sort of large contraction seen elsewhere. The Australian financial system remains strong and the monetary policy transmission process is working to deliver large reductions in interest rates to end borrowers. Nonetheless, economic conditions are clearly weak, and given the speed and scale of the global economic deterioration and its effect on confidence, weak conditions are likely to continue in the near term. Inflation is likely to decline over time.

     

    In response to that outlook, there has already been a major change in both monetary and fiscal policy. Market and mortgage rates are at very low levels by historical standards and business loan rates are below recent averages, reducing debt-servicing burdens considerably. Together with the substantial fiscal initiatives, the cumulative decline in interest rates will provide significant support to domestic demand over the period ahead. On this basis, notwithstanding evident economic weakness at present, the Board judged that the stance of monetary policy was appropriate for the moment. The Board will consider the position again at its next meeting.

    The post OZ Interest Rates Not Cut As Expected appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/oz-interest-rates-not-cut-as-expected-2/feed/ 0
    Wizard And Aussie Bargaining OK With ACCC https://smartoffice.com.au/wizard-and-aussie-bargaining-ok-with-accc-2/ https://smartoffice.com.au/wizard-and-aussie-bargaining-ok-with-accc-2/#respond Thu, 06 Jul 2017 05:46:03 +0000 http://smartoffice.com.au/wizard-and-aussie-bargaining-ok-with-accc-2/ Following the sale of Wizard Home Loans, owned by GE Money, to AHL Investments Pty Ltd (Aussie Home Loans), the Australian Competition and Consumer Commission has decided to not object to the collective bargaining agreements lodged by a group of franchisees in relation to negotiating aspects of franchise agreements.

    The post Wizard And Aussie Bargaining OK With ACCC appeared first on Smart Office.

    ]]>
    Following the sale of Wizard Home Loans, owned by GE Money, to AHL Investments Pty Ltd (Aussie Home Loans), the Australian Competition and Consumer Commission has decided to not object to the collective bargaining agreements lodged by a group of franchisees in relation to negotiating aspects of franchise agreements.

    Collective bargaining refers to two or more competitors collectively negotiating terms and conditions with a supplier or customer. Without protection, it can raise concerns under the competition provisions of the Trade Practices Act 1974. Small businesses can obtain protection from legal action under the Act for collective bargaining arrangements by lodging a notification with the ACCC. Provided the ACCC does not object to the notified arrangement, protection commences 14 days after lodgment.

    Under the Act, the ACCC will only object to and remove the immunity provided by a collective bargaining notification when it is satisfied that any public benefits from the proposed collective bargaining arrangement would not outweigh the public detriments.

    ACCC Chairman, Mr Graeme Samuel, said in this case the collective negotiations will result in transaction costs savings to the group and enable the franchisees to better consider their options in the limited time available. “The ACCC considers that the potential for anti-competitive impact is limited, taking into account the competitive nature of the industry, and the fact that participation in the negotiations is voluntary for all parties involved,” Mr Samuel said.

    The post Wizard And Aussie Bargaining OK With ACCC appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/wizard-and-aussie-bargaining-ok-with-accc-2/feed/ 0
    Interest Gouging Westpac Hit By Share Slump Despite 27% Jump In Profits https://smartoffice.com.au/interest-gouging-westpac-hit-by-share-slump-despite-27-jump-in-profits-2/ https://smartoffice.com.au/interest-gouging-westpac-hit-by-share-slump-despite-27-jump-in-profits-2/#respond Thu, 06 Jul 2017 05:39:08 +0000 http://smartoffice.com.au/interest-gouging-westpac-hit-by-share-slump-despite-27-jump-in-profits-2/ Westpac who are hitting individuals with 11% interest on borrowings as low as $100,000 despite holding millions in assets has announced a 27% jump in profits to$1.4 Billion.

    The post Interest Gouging Westpac Hit By Share Slump Despite 27% Jump In Profits appeared first on Smart Office.

    ]]>
    Westpac who are hitting individuals with 11% interest on borrowings as low as $100,000 despite holding millions in assets has announced a 27% jump in profits to$1.4 Billion.

    Westpac who are hitting individuals with 11% interest on borrowings as low as $100,000 despite holding millions in assets has announced a 27% jump in profits to$1.4 Billion.
    The bank which is gouging interest from Australians despite a Reserve Bank cash rate of 4.5% is also taking money both ways by only offering interest of 5% on savings between $450,000 and $600K.
    In one instance recently a customer who had over $10M in property secured by the bank was told he had to pay 11% interest on borrowings which were needed for an 8 week period as well as establishment fees of $400.
    The bank who claims that they are “not” interest gouging saw third-quarter cash profits rise, due a sharp fall in the level of bad debts and potential bad debts.
    Westpac shares are expected to come under pressure today after the bank said that revenues were down and its interest margins had been squeezed during the quarter.
    Earlier in the year Westpac was slammed for raising interest rates ahead of other banks following a Reserve Bank interest rate rise. 
     Earlier this month the High Court has ordered Westpac Banking Corporation to pay a former real estate agent $50,000 in damages for defamation arising from its mistaken dishonouring of his company’s cheques. The case arose after Westpac dishonoured 30 cheques drawn by the Homewise real estate agency, located in Auburn, Sydney.
    The cheques were returned to Aktas’ clients, mostly landlords, stamped “refer to drawer”, inferring there were insufficient funds to meet the payment.

    The post Interest Gouging Westpac Hit By Share Slump Despite 27% Jump In Profits appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/interest-gouging-westpac-hit-by-share-slump-despite-27-jump-in-profits-2/feed/ 0
    Woolworths Gets Into Bed With Qantas https://smartoffice.com.au/woolworths-gets-into-bed-with-qantas-2/ https://smartoffice.com.au/woolworths-gets-into-bed-with-qantas-2/#respond Thu, 06 Jul 2017 05:37:37 +0000 http://smartoffice.com.au/woolworths-gets-into-bed-with-qantas-2/ Woolworths is to launch an Everyday Rewards Qantas credit card next week which will carry a low annual fee of $89. The card is said to be one of the best value frequent flyer reward cards in the market offering customers one Qantas Frequent Flyer point for every $1 spent in stores accepting Mastercard.

    The post Woolworths Gets Into Bed With Qantas appeared first on Smart Office.

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


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

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

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

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

     

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


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

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

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

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

    The post Woolworths Gets Into Bed With Qantas appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/woolworths-gets-into-bed-with-qantas-2/feed/ 0
    Faulty Goods Hurt Panasonic's Bottom Line https://smartoffice.com.au/faulty-goods-hurt-panasonics-bottom-line/ https://smartoffice.com.au/faulty-goods-hurt-panasonics-bottom-line/#respond Tue, 04 Jul 2017 12:00:00 +0000 http://smartoffice.com.au/faulty-goods-hurt-panasonics-bottom-line/ Pansonic has had a bad year according to profit results from its parent-company, Matsushita, which indicate the electronics giant was hurt badly by a massive mobile phone battery recall last month.

    The post Faulty Goods Hurt Panasonic's Bottom Line appeared first on Smart Office.

    ]]>
    Pansonic has had a bad year according to profit results from its parent-company, Matsushita, which indicate the electronics giant was hurt badly by a massive mobile phone battery recall last month.Matsushita reported its profits for the second quarter (July to September) were down a significant 17 per cent from the same period a year ago, which is unusual given Panasonic’s toe-hold in both the plasma and digital camera sectors, both of which are going gangbusters in the worldwide market.

    Market commentators are blaming the huge Nokia phone battery recall which saw the mobile phone manufacturer recall 46 million of the Matsushita-made lithium-ion batteries due to fears they may overheat and ignite, following a mystery fire breaking out in a Matsushita battery manufacturing plant in Osaka. 

    The 79.29 billion yen (AUD$761 million) fall in profit could also be the result of Matsushita-made faulty parts in microwaves, refrigerators, dryers and massage products which were sold in Japan, according to a report from the Associated Press.

     

    However, quarterly sales for the brand rose one per cent to 2.286 trillion yen (AUD$21.53 billion) from a year ago, due to demand for flat-panel TVs, air conditioners and digital cameras.

    The company is forecasting profits of 246 billion yen (AUD$2.31 billion) for the year ending March 2008, accompanied by sales of 8.78 trillion yen (AUD$82.7 billion).

    The post Faulty Goods Hurt Panasonic's Bottom Line appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/faulty-goods-hurt-panasonics-bottom-line/feed/ 0
    More Australians Going Bankrupt Than Ever Before https://smartoffice.com.au/more-australians-going-bankrupt-than-ever-before/ https://smartoffice.com.au/more-australians-going-bankrupt-than-ever-before/#respond Tue, 04 Jul 2017 12:00:00 +0000 http://smartoffice.com.au/more-australians-going-bankrupt-than-ever-before/ The SMB market is feeling the brunt of a massive rise in bankruptcies with up to 86% of all new businesses failing. At the same time the high cost of living and easy access to credit have led to the highest number of bankruptcies in NSW since records began more than 20 years ago, the Insolvency and Trustee Service Australia (ITSA), accountants Hall Chadwick has said.

    The post More Australians Going Bankrupt Than Ever Before appeared first on Smart Office.

    ]]>
    The SMB market is feeling the brunt of a massive rise in bankruptcies with up to 86% of all new businesses failing. At the same time the high cost of living and easy access to credit have led to the highest number of bankruptcies in NSW since records began more than 20 years ago, the Insolvency and Trustee Service Australia (ITSA), accountants Hall Chadwick has said.

    Referring to statistics released by the federal government body Hall Chadwick said that some consumers were struggling to manage burgeoning levels of debt.

    According to ITSA, there has been a 23.39 per cent increase in bankruptcies in NSW for the year to June 30, with the figure of 9248 the largest on record since monitoring began in 1986.

    Queensland recorded the second highest number at 5751, up 6.94 per cent, followed by Victoria on 5700, up 13.68 per cent.

    Only one state, Western Australia, recorded a fall in the annual number of bankruptcies, down 1.42 per cent to 1392.

    Australia-wide, the number of bankruptcies was up 13.2 per cent to 25,242.

     

    The figures showed that some consumers were getting lost in the economic boom, insolvency partner with Hall Chadwick Paul Leroy said.

    “Some say Australia’s prosperity and booming economy is great for everyone, but certainly the figures reflect another side to the story,” Mr Leroy said.

    “These statistics are very significant and confirm that people are struggling with the increase in the cost of day-to-day living.

    “It is especially hard for the battlers who don’t own their home, with rents rising, as the rental squeeze in Sydney bites.”

    Rising petrol prices were also having an impact, Mr Leroy said, while the ease of obtaining credit was of major concern.

    “With credit card growth at such record levels, it is clear why misused credit cards are behind so many personal bankruptcies,” he said.

    “In an age when people are relying more and more on credit, something has to happen, we can’t continue to raise debt levels without long-term consequences.”

    The post More Australians Going Bankrupt Than Ever Before appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/more-australians-going-bankrupt-than-ever-before/feed/ 0
    IBM Slashes Oz Jobs https://smartoffice.com.au/ibm-slashes-oz-jobs/ https://smartoffice.com.au/ibm-slashes-oz-jobs/#respond Tue, 04 Jul 2017 05:45:52 +0000 http://smartoffice.com.au/ibm-slashes-oz-jobs/ IBM Australia is set to slash jobs and restructure its operations. It is also shifting services work to Asia.

    The post IBM Slashes Oz Jobs appeared first on Smart Office.

    ]]>
    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

     

    The post IBM Slashes Oz Jobs appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/ibm-slashes-oz-jobs/feed/ 0
    Convoy Seeks Sales Manager https://smartoffice.com.au/convoy-seeks-sales-manager/ https://smartoffice.com.au/convoy-seeks-sales-manager/#respond Tue, 04 Jul 2017 05:44:34 +0000 http://smartoffice.com.au/convoy-seeks-sales-manager/ ADVERTISMENT: Leading CE distributor Convoy is looking for a senior sales executive in NSW to sell across some of the most successful brands in the CE market today.

    The post Convoy Seeks Sales Manager appeared first on Smart Office.

    ]]>
    ADVERTISMENT: Leading CE distributor Convoy is looking for a senior sales executive in NSW to sell across some of the most successful brands in the CE market today.

     Area Manager – Sydney Metro Based

    · Convoy is a national distributor of consumer audio and video products

    · Leading world class brand portfolio

    ·Great earning potential!

    · Intrastate travel

    Are you looking for a new challenge? This is an excellent business opportunity for a Professional sales person to join a Company that is growing has leading brands and has a great future ahead.

    Convoy International was established in 1965 and is today a leading wholesale distributor and marketer of a wide range of leading branded audio, video and cable products. We have offices in all States.

    We represent throughout Australia Harman Kardon, Bowers & Wilkins, JBL Home and Car products, Monster Cable & OmniMount. Sales are to both Independent retailers and the major Chains.

     We are looking for an Area Manager to service Sydney and NSW Southern regions. Reporting directly to the Managing Director in the Sydney Office, this is a broad based position that will allow you to use and develop all your skills and encourages creative selling.

     Your main responsibilities will include:

    · Maintain and expand the dealer network within the allocated territory

    · Manage sales, promotion, display, advertising and service for all the Convoy

    Brands within the territory

    · Instigate regular dealer staff training for the Convoy Brands

    · Event manage local product releases

    · Actively seek and investigate new opportunities for growth

    This position will also entail regular travel within the territory as well as to bi-annual marketing conferences in Sydney.

     We offer great earnings potential, a fantastic product portfolio, a friendly and dedicated Head Office team and full support for your sales efforts. In turn, you will be a professional and enthusiastic sales individual with great organisational and time management skills. You will be a creative thinker with the ability to thrive in an independent and continually challenging role and of course, you will be able to liaise effectively with people at all levels.

    Does this sound like you? If you are ready to take on a new and interesting role in a progressive company, then we need to hear from you. Please note that only short listed candidates will be contacted.  Please email your resume using the “Apply Now” at jobs@convoy.com.au

    The post Convoy Seeks Sales Manager appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/convoy-seeks-sales-manager/feed/ 0