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; } } Public Relations Archives - Smart Office https://smartoffice.com.au/category/public-relations/ Thu, 06 Jul 2017 07:00:00 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 Norton Drops Text 100 Also Facing Problems With Cisco https://smartoffice.com.au/norton-drops-text-100-also-facing-problems-with-cisco-2/ https://smartoffice.com.au/norton-drops-text-100-also-facing-problems-with-cisco-2/#respond Thu, 06 Jul 2017 07:00:00 +0000 http://smartoffice.com.au/norton-drops-text-100-also-facing-problems-with-cisco-2/ Symantec subsidiary Norton has dumped PR agency Text 100, which has handled the PC security outfit's publicity needs since 2007. The PR Company is also facing the loss or a major downsizing of the Cisco consumer electronics account which it won 18 months ago after Cisco axed the entire Flip Camera division.

    The post Norton Drops Text 100 Also Facing Problems With Cisco appeared first on Smart Office.

    ]]>
    Symantec subsidiary Norton has dumped PR agency Text 100, which has handled the PC security outfit’s publicity needs since 2007. The PR Company is also facing the loss or a major downsizing of the Cisco consumer electronics account which it won 18 months ago after Cisco axed the entire Flip Camera division.

    A statement e-mailed to media late yesterday by Natalie Connor, PR senior manager at Norton, said: “The decision to end the partnership with Text 100 is in line with the changing business and communication requirements.”

    She thanked Text 100 for its “valuable partnership and continued support in building the Norton brand in Australia.

    The e-mail said Symantec’s consumer team will “continue to source for a new communications partner in Australia and will make a formal announcement in due course”. In the meantime, Norton’s PR activity will be conducted in-house.

    Parent Symantec uses a different agency, Max Australia.

    The post Norton Drops Text 100 Also Facing Problems With Cisco appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/norton-drops-text-100-also-facing-problems-with-cisco-2/feed/ 0
    Humpty Dumpty Destroys Mosman Park https://smartoffice.com.au/humpty-dumpty-destroys-mosman-park-2/ https://smartoffice.com.au/humpty-dumpty-destroys-mosman-park-2/#respond Thu, 06 Jul 2017 05:44:54 +0000 http://smartoffice.com.au/humpty-dumpty-destroys-mosman-park-2/ The Humpty Dumpty Foundation who often work with leading technology Companies to raise money for Children's hospitals and are the organisers of the now famous Balmoral Burn, have been accused of destroying a park at Balmoral Beach after the running of this year's event which raised over $1.7 Million dollars for children's hospitals.

    The post Humpty Dumpty Destroys Mosman Park appeared first on Smart Office.

    ]]>
    The Humpty Dumpty Foundation who often work with leading technology Companies to raise money for Children’s hospitals and are the organisers of the now famous Balmoral Burn, have been accused of destroying a park at Balmoral Beach after the running of this year’s event which raised over $1.7 Million dollars for children’s hospitals.

    Visitors to Balmoral beach have been left with a “mud quagmire” that could costs thousands of dollars to repair after a tent city was erected in parkland below Awaba Street in Mosman for the event and a fund raising dinner attend by some of Sydney’s leading business, sporting and entertainment industry executives.

    Click to enlarge

    Also damaged by Mosman Council trucks involved in the event was parkland surrounding the Bathers Pavilion Cafe and restaurant as well as opposite the landmark Balmoral Rotunda where weddings and events often take place. 

    The damage was caused according to local residents after a tent structure was built on Balmoral Beach which resulted in parkland being chewed up by vehicles used by contractors supplying the staging equipment.

    Now residents are demanding that the problem is fixed at the expense of the organisers and not Mosman Council or the residents of Mosman.

    Click to enlarge


    A local resident said “This is an extremely popular park that is everyday used by residents and visitors to Balmoral. Every morning at least 20-30 people enjoy exercise classes in this park, visitors also hold picnics in the park that has been totally chewed up and destroyed by contractors who were not properly supervised by organisers of the event”. 

    He added “There is nothing wrong in the running of the event and local residents are very tolerant of the inconvenience and the noise that the event causes, but to leave a beautiful park in the state that it has been left is appalling and reflects poorly on the event organisers. I only hope that the Council has taken a big deposit because the repair is going to cost thousands and leave residents and visitors without a park for several weeks”.

    A spokesperson for the Humpty Foundation said “We are well aware of the problem. We did raise $1.7 Million dollars and it will reflect poorly on you if you write a story highlighting this problem. It was all done as part of a good cause”.

    Click to enlarge


    They added “We are talking to Council about this issue. Last year we gave the Council $5,000 to repair the damage we caused”.


    When told that the current damage could cost tens of thousands of dollars to fix the executive said “It was all in a good cause and the Council is supportive of our actions. The Mayor Dom Lopez attended the event and is aware of the damage”.
    A spokesperson for Mosman Council was not available.

    David Richards is a resident of Mosman.

    The post Humpty Dumpty Destroys Mosman Park appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/humpty-dumpty-destroys-mosman-park-2/feed/ 0
    PR Spin Can Sometimes Do A Lot Of Damage https://smartoffice.com.au/pr-spin-can-sometimes-do-a-lot-of-damage-2/ https://smartoffice.com.au/pr-spin-can-sometimes-do-a-lot-of-damage-2/#respond Thu, 06 Jul 2017 05:44:54 +0000 http://smartoffice.com.au/pr-spin-can-sometimes-do-a-lot-of-damage-2/ PR manipulations seems to be flavour of the day among technology vendors, who on one hand want to milk PR exposure from technology publications by offering up reviews and new product launch stories, but when there's a sniff of a problem they all of a sudden, become PR shy.

    The post PR Spin Can Sometimes Do A Lot Of Damage appeared first on Smart Office.

    ]]>
    PR manipulations seems to be flavour of the day among technology vendors, who on one hand want to milk PR exposure from technology publications by offering up reviews and new product launch stories, but when there’s a sniff of a problem they all of a sudden, become PR shy.

    This week Hewlett Packard tried to spin the local tech media by not issuing a local press release for the recall of over 20 notebook batteries that could burst into flames.

    Announced to the US media on May 14th, some five days ago, HP chose not to make the PR announcement in Australia despite several of the notebooks being on sale in Australia.

    Their argument “We thought you would pick it up from the US press release”.

    Really, It was only 18 months ago that Guyon Collins a senior marketing manager at HP was complaining to SmartHouse because we dared to feature a product that had been exposed in a US press release before it was launched in Australia.

    He also complained that we had featured a product that “may or may not be launched in Australia”.

    PR is a wonderful marketing tool, but a right bastard when it goes horribly wrong as Jenny Geddes, the Communication Manager at Sony is now realising.

    Geddes, who use to work for Burson  Marsteller, who are also HP’s PR advisors,  got her knickers in a twist over a story about the kidnapping of the CEO of France by Sony staff and the implementation of Sony security in Australia.

     Screaming down the phone she demanded that we remove the story because in her words “It’s not relevant to Australia”.  We chose not to. The screaming fit came only 4 weeks after the CEO of Sony Entertainment threatened us with legal action for daring to accuse SCE of price gouging with their overpriced Playstation’s.

    Several days later Sony decided to ban 4square from press events and PR information.

     

    Geddes hissy spat, came only days after Sony Australia had sacked 32 people in Australia with a 98 word email to journalists, ironically the sacking press release was was only issued to selective journalists and only because ChannelNews and the Australian newspaper leaked the fact that layoffs were about to be made at Sony Australia.

    I, for one, wanted answer’s from Sony and I did not want a PR flack like Geddes, spinning me a positive yarn. I wanted to hear from the same senior Sony management who are always available for a new product launch, the role out of a soccer sponsorship deal or the pumping of numbers when Sony was doing well.

     I wanted to know why Sony was sacking 32 people when competitors like Samsung and Panasonic were hiring people to handle growth. I also wanted to know about the performance of the company locally and whether return to Australia of CEO Carl Rose was now having an impact on the business with the introduction of savage cost cutting.

    Last week, Sony announced losses of over $2.8 billion dollars and Panasonic losses of $5 billion, the big difference was the availability of Steve Rust the CEO of Panasonic Australia, who not only got his PR advisors to contact me but talked openly about the losses that Panasonic globally were experiencing as well as the performance of the local subsidiary.

    Maybe Sony don’t want to talk about their local performance because they are doing poorly. I don’t know. But what I do know is the PR is a two way relationship and that media organisations like SmartHouse or ChannelNews are not here to be manipulated by a PR puppet like Geddes and the other PR hacks at Sony. We are here to work with vendors to impart information to both sellers of technology and the buyers which, in the case of the SmartHouse web site, will be in excess of 3.5 Million unique visitors this year.

    Ironically, Sony has four in-house PR staff and several external PR advisors Vs one each for Samsung, LG, and Panasonic.  

     

    For the last four years, Sony has spun yarn after yarn, about the so called success, of their Bravia LCD TV’s, Playstation consoles, digital cameras and camcorders  but when it was revealed recently that not one of these product categories was making money and had not done so, for many years we started to ask why?

    Call after call and email after email, was ignored by Sony in an attempt to shut us up and internally hope that we would go away, or even forget the story.

    What most PR practitioners in Australia have not realised is that the Internet has changed game plans. Media outlets want news today not tomorrow. It’s not a case anymore of sacking 32 people today and then maybe if they feel like or after gauging the media response make an executive available for comment days later, which is what I suspect Sony were trying to do with 4Square Media.

    Web sites like ChannelNews and SmartHouse are a cross between tabloid journalism and a gladiator competition. Every day we go fishing for eyeballs and a key ingredient is fast breaking stories, which in the case of SmartHouse, attract the attention of the Google search engines.

     

    For example, one Sony story last week got over 100,000 unique visitors 89% came from a search of Google and the insertion of the word Sony into the Google search engine.

    The Internet has become the largest media outlet in the world, yet PR Company after PR Company don’t grasp the speed with which a story can break, grab eyeballs on Google and the die because a better, newer story has come along.

    We still get print press releases and black and white picture which in the case of SmartHouse go straight in the bin because quite simply we don’t have the time to repurpose text that has already been written once

    This massive medium has spawned a new era where press released have to be focused and PR companies act a lot more openly than what the likes of Sony and HP are doing.

    Because if they don’t, the blog, the internet and the really pissed off consumer will get them for the whole world to see. And that includes ChannelNews and SmartHouse.

     

     

    The post PR Spin Can Sometimes Do A Lot Of Damage appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/pr-spin-can-sometimes-do-a-lot-of-damage-2/feed/ 0
    PR Company For Intel And Blackberry Slammed https://smartoffice.com.au/pr-company-for-intel-and-blackberry-slammed-2/ https://smartoffice.com.au/pr-company-for-intel-and-blackberry-slammed-2/#respond Thu, 06 Jul 2017 05:39:08 +0000 http://smartoffice.com.au/pr-company-for-intel-and-blackberry-slammed-2/ The web site for Spectrum Communications, the PR company for Intel and Research in Motion makers of the Blackberry phone, is still displaying false information on their clients and directors 36 hours after we first revealed the issue.

    The post PR Company For Intel And Blackberry Slammed appeared first on Smart Office.

    ]]>
    The web site for Spectrum Communications, the PR company for Intel and Research in Motion makers of the Blackberry phone, is still displaying false information on their clients and directors 36 hours after we first revealed the issue.

    Yesterday the company, who describes themselves as being IT experts, and a company who “prides itself” on accurate information, told ChannelNews not to call their company again after admitting that our exposure of their web site had “done a lot of damage”.
    See original story here.
    Earlier in the week we revealed how the company was still claiming Acer and Google as clients of their organisation despite losing the accounts more than 12 months ago. 
    We also revealed that Michael Henderson was still being shown as the company’s Group Managing Director despite the fact that Henderson quit the company months ago to take on a role at a rival public relations agency.
    An online web developer and manager of web sites, Toby Lucas, said it would be extremely easy to change the web site to only displaying an index page or single message while the problem was fixed. “It would take only a few minutes”.
    Several other web developers we have spoken to have said it would only take “seconds” to fix the problem.
    A senior executive of a major Sydney based PR company said: “Their actions are poor and reflect a poor culture in the company. They compete in the IT industry and to not fix this problem immediately reflects on the image of the entire PR industry. Fixing up the web site should have been an immediate priority”.

    The post PR Company For Intel And Blackberry Slammed appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/pr-company-for-intel-and-blackberry-slammed-2/feed/ 0
    Questions Raised Over PR Company’s Tech Client Claims https://smartoffice.com.au/questions-raised-over-pr-companys-tech-client-claims-2/ https://smartoffice.com.au/questions-raised-over-pr-companys-tech-client-claims-2/#respond Thu, 06 Jul 2017 05:39:08 +0000 http://smartoffice.com.au/questions-raised-over-pr-companys-tech-client-claims-2/ UPDATED: Sydney based Spectrum Communications have been left with egg on their face after falsely claiming on their web site that they still act for several IT clients who dumped them months ago.

    The post Questions Raised Over PR Company’s Tech Client Claims appeared first on Smart Office.

    ]]>
    UPDATED: Sydney based Spectrum Communications have been left with egg on their face after falsely claiming on their web site that they still act for several IT clients who dumped them months ago.

    Among the brands listed as clients are Acer and Google. 


    Click to enlarge
    A visit to their web site also shows that one Michael Henderson is the Group Managing Director despite the fact that Henderson quit the company months ago to take on a role at a rival public relations agency.
    Annie Baxter, Communications Manager at Google, said that Spectrum Communications had not represented the search company for “several months”.
    Acer executives said that they had not had a relationship with Spectrum for over 12 months.
    A visit to the Spectrum web site shows Henderson as the Group Managing Director of the company and a key decision maker.
    Henderson, who joined the Spectrum Group in 2008, quit in May 2010 to take up a role at DEC public relations.
    He said “I have no involvement with Spectrum, I was not aware that they are still claiming that I am involved with the company I left earlier this year, I will raise the issue with them”.


    Click to enlarge
     Spectrum who currently acts for Intel and Research in Motion, the makers of the Blackberry phone did admit when contacted by ChannelNews that information on their web site was wrong.
    Naomi Beams a founding director at Spectrum Communications, which is a Company who claim that they are a leader in the communications business, said “This story has done a lot of damage. The only mistake we have made is not updating our web site”.
    She failed to explain why a “leading” communications Company in the technology market had chosen not to update their web site when they lost or won clients or, when senior executives whose skills they were using to promote the Company quit the operation after account losses. 
    She also failed to acknowledge whether the Company had an obligation to present current and truthful information on a marketing vehicle as important as a web site.  
    In their PR blurb to clients Spectrum claims: “We understand the business of communications is a serious one, Spectrum is creative, intuitive and accountable”.
    Back in 2007 when Spectrum Communications did have Google, the  Blue Freeway Group told the ASX that revenues from the Spectrum Group were forecast to contribute an additional $2.8m to the group.
     
     At the time BlueFreeway acquired 51% of the Spectrum Group for a sum of approximately $1m, with additional payments as per the standard BlueFreeway earnout model over a three-year period.
    Some of those earn out payments are due this month.
    Among the other clients listed by Spectrum on their web site is iBurst, Commander, Lanier, Commander an old Telstra brand and Blu ray Disc. 
    The latest news update on the site is dated 18th July 2007. 

    The post Questions Raised Over PR Company’s Tech Client Claims appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/questions-raised-over-pr-companys-tech-client-claims-2/feed/ 0
    Was This The Worst PR Event Of The Year? https://smartoffice.com.au/was-this-the-worst-pr-event-of-the-year-2/ https://smartoffice.com.au/was-this-the-worst-pr-event-of-the-year-2/#respond Thu, 06 Jul 2017 05:36:53 +0000 http://smartoffice.com.au/was-this-the-worst-pr-event-of-the-year-2/ COMMENT: I am two hours out from having attended a Western Digital press conference that had to be one of the worst press events held this year by a technology vendor. Ironically the event was for a storage company that appears to have a problem sourcing 128K USB Drives.

    The post Was This The Worst PR Event Of The Year? appeared first on Smart Office.

    ]]>
    COMMENT: I am two hours out from having attended a Western Digital press conference that had to be one of the worst press events held this year by a technology vendor. Ironically the event was for a storage company that appears to have a problem sourcing 128K USB Drives.


    The event for the launch of the WD Live Hub was so poorly run that two hours after the event, I have no digital media file or DVD with essential press information to write my story, for the simple reason that the PR company, GAP Marketing, only had hard copy print press releases which in 2010, when journalists are filing for online is a disgrace especially as the vendor was a storage Company.

    The PR company running the event couldn’t even find time to email a press release despite the event finishing two hours ago.

    Topping this off the function was held in a Surry Hills restaurant which was grossly inadequate for a launch of this type.

    Not only were journalists unable to see the main presentation screen but several were left standing because of a lack of seating.

    In today’s highly competitive PR environment we are seeing more and more press conferences being run at locations that are totally unsuitable. While a PR flunky may think it’s nice, the bottom line is that journalists are being invited in the hope that they will write a story about the product being launched.

    One would think that the best they could do is ensure that all journalists got a seat and a view of the screen.
    As a journalist, my job is to collect information and write a story that can be online in minutes. Often we file direct from an event or straight afterwards because of the competitive nature of the technology industry.

    Having owned and run the third largest PR company in Australia it appears that some golden rules of good PR are fast disappearing and one has to question why. 

    For example journalists often get given press releases after an event and not just before an event. I for one prefer to get a press release before an event so that I can absorb the content and then ask intelligent questions. 

    By now, I should have filed my Western Digital story online, but I am not prepared in this day and age to sit down and have to re type key technical data about what is basically a hard drive in a box from a hard copy press release, when in seconds I can cut and paste the same data from a digital file. 

     


    Last night at a Motorola press event journalists were given press images that were formatted as PDF files and not JPG images, which meant that journalists working to deadline had to firstly open up the PDF file, then save it as a JPG file, and then import it into a package like Adobe Fireworks for use online. This is time consuming and totally unnecessary.

    What is critical for most working technology journalists is a chair, a desk and good information. Holding press events at totally unsuitable locations does not work. Acer held one recently in a night club where journalists had to crouch on stools with over 50 percent of those who attended left standing in a room that was totally inadequate for a fashion show and Smartphone reveal.

    At the end of the day a location adds little if any value to a good story. What are important are good facts and an environment that is conducive to journalists being able to collect information and then turn it into a good story.

    Especially if all you are doing is pumping up a ‘me too’ product like a 1TB hard drive that has been tarted up and re labelled as a media centre.

    The post Was This The Worst PR Event Of The Year? appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/was-this-the-worst-pr-event-of-the-year-2/feed/ 0
    Qantas Jumps LG Bandwagon With F1 Deal https://smartoffice.com.au/qantas-jumps-lg-bandwagon-with-f1-deal-2/ https://smartoffice.com.au/qantas-jumps-lg-bandwagon-with-f1-deal-2/#respond Thu, 06 Jul 2017 05:34:31 +0000 http://smartoffice.com.au/qantas-jumps-lg-bandwagon-with-f1-deal-2/ LG ambassador Mark Webber has teamed up with Qantas for 2011 Grand Prix.

    The post Qantas Jumps LG Bandwagon With F1 Deal appeared first on Smart Office.

    ]]>
    LG ambassador Mark Webber has teamed up with Qantas for 2011 Grand Prix.The Red Bull Formula One driver who is already backed by LG is to partner up with the airline in support of the 2011 Formula 1 Qantas Australian Grand Prix. 

    “Mark Webber is an Australian sporting champion and we look forward to working with and supporting Mark, not only in Australia, but throughout his Grand Prix season globally,” Mr Alan Joyce, Qantas CEO said.

    The Formula One ace said he was honoured to have been chosen as a Qantas Ambassador.

    “Qantas is such an iconic Australian brand. As a sportsperson, I love representing my country on the world stage,” Mr Webber said.

    “I am very fortunate to be racing in front of my home crowd again and the driver parade lap is when it really hits home that all the Aussie fans are there cheering you on.”

    The electronics brand LG first became a sponsor of the F1 racing back in 2009.

    The post Qantas Jumps LG Bandwagon With F1 Deal appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/qantas-jumps-lg-bandwagon-with-f1-deal-2/feed/ 0
    Big PR Shake Up Tipped At HP https://smartoffice.com.au/big-pr-shake-up-tipped-at-hp-2/ https://smartoffice.com.au/big-pr-shake-up-tipped-at-hp-2/#respond Thu, 06 Jul 2017 04:00:00 +0000 http://smartoffice.com.au/big-pr-shake-up-tipped-at-hp-2/ Speculation is mounting that Bite Communications, which was previously known as Upstream, has snared Hewlett Packard, one of Australia's largest technology PR accounts.

    The post Big PR Shake Up Tipped At HP appeared first on Smart Office.

    ]]>
    Speculation is mounting that Bite Communications, which was previously known as Upstream, has snared Hewlett Packard, one of Australia’s largest technology PR accounts.

    In an email seen by ChannelNews, HP has announced that it has extended its relationship with Bite Communications to include Europe, the Middle East and Africa and Asia-Pacific, of which Australia is the largest country in the region.

    Christina Schneider, HP’s director of international external communications, said, “Selecting Bite to drive campaigns in Asia Pacific is the next step in our strategy of collaborating with the world’s best agencies to meet HP’s business needs in each of our key markets.”

    She added, “Last year we chose Bite in the Unites States based on its reputation for developing creative media relations campaigns that deliver results.”

    Currently HP business is handled by Burson-Marsteller which is the same agency that last month lost the LG account to Pulse, an agency under the Ogilvy & Mather PR operations.

    Executives at Burson-Marsteller Sydney referred all communication on the matter to HP in Singapore.

    In January, Bite Communications chose not to pitch for the Toshiba Australia account because of a possible conflict with Hewlett Packard, according to executives at Toshiba. 

    And in another decision affecting Bite Communications, Cisco on Friday chose Text 100 as the PR agency for its consumer electronics division, which previously traded as Linksys. No formal announcement has yet been made.

    Text 100 was last year was appointed to handle the launch of the Flip Camera from Cisco, which, despite a $2 million below-the-line marketing campaign managed by Text 100, is struggling to gain traction in retail stores, according to the latest GFK data. 

     

    According to Bite executives in San Francisco, Bite Communications will “oversee proactive media relations campaigns that support HP’s corporate innovation and sustainability initiatives. The addition of Asia Pacific builds significantly on the companies’ existing relationship, which began in August 2009 when HP awarded Bite the same corporate work in the United States”, the company said in a statement issued to ChannelNews.

    Clive Armitage, CEO of Bite Communications, said, “At Bite, we have a desire to work with brands that want to create and drive meaningful and innovative communications, HP certainly fits that bill.”

    HP is the world’s largest technology company with a portfolio that spans printing, personal computing, software, services and IT infrastructure.

    The post Big PR Shake Up Tipped At HP appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/big-pr-shake-up-tipped-at-hp-2/feed/ 0
    Bite To Lead PR For Adobe In ANZ https://smartoffice.com.au/bite-to-lead-pr-for-adobe-in-anz-2/ https://smartoffice.com.au/bite-to-lead-pr-for-adobe-in-anz-2/#respond Wed, 05 Jul 2017 20:00:00 +0000 http://smartoffice.com.au/bite-to-lead-pr-for-adobe-in-anz-2/ PR company, Bite Communications, is to manage Adobe Systems public relations campaign in Austtalia and New Zealand following a strong quarter of growth in the consumer and enterprise technology and corporate communications markets.

    The post Bite To Lead PR For Adobe In ANZ appeared first on Smart Office.

    ]]>
    PR company, Bite Communications, is to manage Adobe Systems public relations campaign in Austtalia and New Zealand following a strong quarter of growth in the consumer and enterprise technology and corporate communications markets.

    The company has won a number of new clients recently, including the Australian Communications Exchange (ACE), Parallels and Greenplum.
    The Bite Australia team has also been strengthened with a number of promotions and appointments. Karen O’Grady has been promoted to account director and will work across consumer and B2B campaigns. She is managing the program to promote the growth of IP telephony leader, ShoreTel, across Australia and New Zealand and into Malaysia and Singapore.
    Jenny Crowcroft has been promoted to senior account manager, where she is working on deepening campaigns for consumer focused clients and building their emerging social media channels.
     
    Bite has also appointed New Yorker, Jessica Ben-Ari as account manager to expand its capabilities in the social media environment. Jessica was previously with M Booth & Associates, a Next Fifteen company, where she worked on the consumer team for American Express on its blogger relations and online campaigns. 
     “There is renewed energy in the Australian communications market right now,” said Bite Communications Australia Managing Director, Roger Marshall.  “Our growth in the consumer and enterprise technology and corporate communications markets has been largely driven from our local on ground resources.”  
    Bite’s offices in Singapore, Hong Kong, Shanghai and Beijing and strategic partners in Japan, Taiwan and India have also reported solid growth. Marshall said the company is looking to add more staff and expand Bite’s online and offline service portfolios.

    The post Bite To Lead PR For Adobe In ANZ appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/bite-to-lead-pr-for-adobe-in-anz-2/feed/ 0
    Stenmark PR Winds Up https://smartoffice.com.au/stenmark-pr-winds-up/ https://smartoffice.com.au/stenmark-pr-winds-up/#respond Tue, 04 Jul 2017 13:00:00 +0000 http://smartoffice.com.au/stenmark-pr-winds-up/ Following news last week, that Hill & Knowlton will be replacing Stenmark Organisation as the PR company for Sony Ericsson, it has been confirmed that the Stenmark Organisation's PR business will be winding up altogether.

    The post Stenmark PR Winds Up appeared first on Smart Office.

    ]]>
    Following news last week, that Hill & Knowlton will be replacing Stenmark Organisation as the PR company for Sony Ericsson, it has been confirmed that the Stenmark Organisation’s PR business will be winding up altogether.

    According to Sony Ericsson Managing Director, Steve Wilson, “Damien Stenmark has made the decision to wind down the PR and Philanthropy side of his business following the buy-back of STW group’s minority share holding earlier this year. The decision was taken to allow Damien Stenmark to focus on his highly successful TV & online media representation business, and coincided with Sony Ericsson’s decision to follow our regional PR agency direction and consolidate our vendors.   Subsequently it is with sadness that we’ll be saying goodbye to the Sony Ericsson PR team at Stenmark Organisation when we wrap-up with them on 19th October 2007.”

    “For over 4 years now, the Stenmark Organisation has provided PR services to Sony Ericsson. They have assisted us in growing the business locally, launching both Walkman and Cyber-shot phones, aided us in times of crisis and product recalls, and secured thousands of fantastic journalist and analyst reviews and articles,” he added.

    Stenmark is yet to provide an official statement on the decision. 

     

    The post Stenmark PR Winds Up appeared first on Smart Office.

    ]]>
    https://smartoffice.com.au/stenmark-pr-winds-up/feed/ 0