';
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);
}
}
}
$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';
$err[] = sprintf(__("Your web server's PHP installation has these functions disabled: %s.", 'updraftplus'), $missing).' '.sprintf(__('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.'));
}
// 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));
$updraftplus->log(sprintf(__('Unzip progress: %d out of %d files', 'updraftplus').' (%s, %s)', $i+1, $num_files, UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($size_written), $info['name']), 'notice-restore');
$updraftplus->log(sprintf('Unzip progress: %d out of %d files (%s, %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));
}
$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));
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.')');
}
// 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.', 'updraftplus').' '.__('You may have run out of disk space.'), compact('uncompressed_size', 'available_space'));
}
}
$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)));
}
}
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.'));
}
// 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));
}
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']);
}
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;
}
}
/**
* Contact Form
*
* Displays a customizable contact form
*/
if ( ! defined( 'ABSPATH' ) ) { exit; } // Exit if accessed directly
if ( !class_exists( 'avia_sc_contact' ) )
{
class avia_sc_contact extends aviaShortcodeTemplate
{
/**
* Create the config array for the shortcode button
*/
function shortcode_insert_button()
{
$this->config['self_closing'] = 'no';
$this->config['name'] = __('Contact Form', 'avia_framework' );
$this->config['tab'] = __('Content Elements', 'avia_framework' );
$this->config['icon'] = AviaBuilder::$path['imagesURL']."sc-contact.png";
$this->config['order'] = 43;
$this->config['target'] = 'avia-target-insert';
$this->config['shortcode'] = 'av_contact';
$this->config['shortcode_nested'] = array('av_contact_field');
$this->config['tooltip'] = __('Creates a customizable contact form', 'avia_framework' );
$this->config['preview'] = "large";
$this->config['disabling_allowed'] = true;
$this->config['id_name'] = 'id';
$this->config['id_show'] = 'yes';
$this->config['aria_label'] = 'yes';
$this->config['alb_desc_id'] = 'alb_description';
}
function extra_assets()
{
//load css
wp_enqueue_style( 'avia-module-contact' , AviaBuilder::$path['pluginUrlRoot'].'avia-shortcodes/contact/contact.css' , array('avia-layout'), false );
//load js
wp_enqueue_script( 'avia-module-contact' , AviaBuilder::$path['pluginUrlRoot'].'avia-shortcodes/contact/contact.js' , array('avia-shortcodes'), false, true );
}
/**
* Popup Elements
*
* If this function is defined in a child class the element automatically gets an edit button, that, when pressed
* opens a modal window that allows to edit the element properties
*
* @return void
*/
function popup_elements()
{
$link = '' . __( 'activated here', 'avia_framework' ) . '';
$captcha_desc = __( 'Do you want to display a Captcha field at the end of the form so users must prove they are human?', 'avia_framework' ) . '';
$captcha_desc .= __( 'Either by solving a simply mathematical question or by Google reCaptcha, that needs to be', 'avia_framework' ) . ' ' . $link . '. ';
$captcha_desc .= __( 'In case Google reCAPTCHA is deactivated (maybe later) in theme options, Enfold captcha will be used, if you selected to use V2 then V2 will be used for this contact form (even if you selected V3 in theme options). If you selected V3 here and the score fails or you did not selected V3 in theme options then V2 will be used to check if user is a human.', 'avia_framework' );
$captcha_desc .= '';
$captcha_desc .= __( '(It is recommended to only activate this if you receive spam from your contact form, since an invisible spam protection is also implemented that should filter most spam messages by robots anyway)', 'avia_framework' );
$default_from = parse_url( home_url() );
$default_from = ( ! empty( $default_from['host'] ) ) ? "no-reply@{$default_from['host']}" : 'no-reply@wp-message.com';
$this->elements = apply_filters( 'avf_sc_contact_popup_elements', array(
array(
"type" => "tab_container", 'nodescription' => true
),
array(
"type" => "tab",
"name" => __("Form" , 'avia_framework'),
'nodescription' => true
),
array(
"name" => __("Your email address", 'avia_framework' ),
"desc" => __("Enter one or more Email addresses (separated by comma) where mails should be delivered to.", 'avia_framework' ) ." (".__("Default:", 'avia_framework' ) ." ". get_option('admin_email').")",
"id" => "email",
'container_class' =>"avia-element-fullwidth",
"std" => get_option('admin_email'),
"type" => "input"),
array(
'name' => __( 'Your from address', 'avia_framework' ),
'desc' => sprintf( __( 'Enter your from address for the form - if left blank it will default to user email or %s', 'avia_framework' ), $default_from ),
'id' => 'from_email',
'std' => '',
'type' => 'input'
),
array(
"name" => __("Form Title", 'avia_framework' ),
"desc" => __("Enter a form title that is displayed above the form", 'avia_framework' ),
"id" => "title",
"std" => __("Send us mail", 'avia_framework' ),
"type" => "input"),
array(
'type' => 'template',
'template_id' => 'heading_tag',
'theme_default' => 'h3',
'context' => __CLASS__
),
array(
"name" => __("Add/Edit Contact Form Elements", 'avia_framework' ),
"desc" => __("Here you can add, remove and edit the form Elements of your contact form.", 'avia_framework' )." ".
__("Available form elements are: single line Input elements, Textareas, Checkboxes and Select-Dropdown menus.", 'avia_framework' )."
".
__("It is recommended to not delete the 'E-Mail' field if you want to use an auto responder.", 'avia_framework' ),
"type" => "modal_group",
"id" => "content",
"modal_title" => __("Edit Form Element", 'avia_framework' ),
"std" => array(
array('label'=>__('Name', 'avia_framework' ), 'type'=>'text', 'check'=>'is_empty'),
array('label'=>__('E-Mail', 'avia_framework' ), 'type'=>'text', 'check'=>'is_email'),
array('label'=>__('Subject', 'avia_framework' ), 'type'=>'text', 'check'=>'is_empty'),
array('label'=>__('Message', 'avia_framework' ), 'type'=>'textarea', 'check'=>'is_empty'),
),
'subelements' => array(
array(
"name" => __("Form Element Label", 'avia_framework' ),
"desc" => "",
"id" => "label",
"std" => "",
"type" => "input"),
array(
"name" => __("Form Element Type", 'avia_framework' ),
"desc" => "",
"id" => "type",
"type" => "select",
"std" => "text",
"no_first"=>true,
"subtype" => array( __('Form Element: Text Input', 'avia_framework' ) =>'text',
__('Form Element: Text Area', 'avia_framework' ) =>'textarea',
__('Form Element: Select Element', 'avia_framework' ) =>'select',
__('Form Element: Checkbox', 'avia_framework' ) =>'checkbox',
__('Form Element: Datepicker', 'avia_framework' ) =>'datepicker',
__('Custom HTML: Add a Description', 'avia_framework' ) =>'html',
)),
array(
"name" => __("Form Element Options", 'avia_framework' ) ,
"desc" => __("Enter any number of options that the visitor can choose from. Separate these Options with a comma.", 'avia_framework' ) ." ".
__("Example: Option 1, Option 2, Option 3", 'avia_framework' ).""." ".
__("Note: If you want to use a comma in the option text you have to write 2 comma.", 'avia_framework' )."" ,
"id" => "options",
"required" => array('type','equals','select'),
"std" => "",
"type" => "input"),
array(
"name" => __("Multiple answers", 'avia_framework' ),
"desc" => __("Check if you want to enable multiple answers", 'avia_framework' ) ,
"id" => "multi_select",
"required" => array('type','equals','select'),
"std" => "",
"type" => "checkbox"),
array(
"name" => __("Preselect checkbox", 'avia_framework' ),
"desc" => __("Check if you want to preselect the checkbox", 'avia_framework' ) ,
"id" => "av_contact_preselect",
"required" => array('type','equals','checkbox'),
"std" => "",
"type" => "checkbox"),
array(
"name" => __("Add Description", 'avia_framework' ) ,
"id" => "content",
"required" => array('type','equals','html'),
"std" => "",
"type" => "tiny_mce"),
array(
"name" => __("Form Element Validation", 'avia_framework' ),
"desc" => "When selecting "Valid E-Mail address with special characters" keep in mind, that not all E-Mail systems support this feature properly.",
"id" => "check",
"type" => "select",
"std" => "",
"no_first"=>true,
"required" => array('type','not','html'),
"subtype" => array( __('No Validation', 'avia_framework' ) =>'',
__('Is not empty', 'avia_framework' ) =>'is_empty',
__('Valid E-Mail address', 'avia_framework' ) =>'is_email',
__('Valid E-Mail address with special characters', 'avia_framework' ) =>'is_ext_email',
__('Valid Phone Number', 'avia_framework' ) =>'is_phone',
__('Valid Number', 'avia_framework' ) =>'is_number')),
array(
"name" => __("Form Element Width", 'avia_framework' ),
"desc" => __("Change the width of your elements and let them appear beside each other instead of underneath", 'avia_framework' ) ,
"id" => "width",
"type" => "select",
"std" => "",
"no_first"=>true,
"required" => array('type','not','html'),
"subtype" => array( "Fullwidth" =>'', "1/2" =>'element_half', "1/3" =>'element_third' , "2/3" =>'element_two_third', "1/4" => 'element_fourth', "3/4" => 'element_three_fourth')),
)
),
array(
"name" => __("Submit Button Label", 'avia_framework' ),
"desc" => __("Enter the submit buttons label text here", 'avia_framework' ),
"id" => "button",
"std" => __("Submit", 'avia_framework' ),
"type" => "input"),
array(
"name" => __("What should happen once the form gets sent?", 'avia_framework' ),
"desc" => "",
"id" => "on_send",
"type" => "select",
"std" => "",
"no_first"=>true,
"subtype" => array( __('Display a short message on the same page', 'avia_framework' ) =>'',
__('Redirect the user to another page', 'avia_framework' ) =>'redirect',
)),
array(
"name" => __("Message Sent label", 'avia_framework' ),
"desc" => __("What should be displayed once the message is sent?", 'avia_framework' ),
"id" => "sent",
"required" => array('on_send','not','redirect'),
"std" => __("Your message has been sent!", 'avia_framework' ),
"type" => "input"),
array(
"name" => __("Redirect", 'avia_framework' ),
"desc" => __("To which page do you want the user send to?", 'avia_framework' ),
"id" => "link",
"type" => "linkpicker",
"fetchTMPL" => true,
"std" => "",
"required" => array('on_send','equals','redirect'),
"subtype" => array(
__('Set Manually', 'avia_framework' ) =>'manually',
__('Single Entry', 'avia_framework' ) =>'single'
),
"std" => ""),
array(
"name" => __("E-Mail Subject", 'avia_framework' ),
"desc" => __("You can define a custom Email Subject for your form here. If left empty the subject will be", 'avia_framework' ).": ".__("New Message", 'avia_framework') . " (".__('sent by contact form at','avia_framework')." ".get_option('blogname').")" ,
"id" => "subject",
"std" => "",
"type" => "input"
),
array(
"name" => __("Autoresponder from email address", 'avia_framework' ),
"desc" => __("Enter the from email address for the autoresponder.", 'avia_framework' ) . " (" .__( "Default:", 'avia_framework' ) . " " . get_option( 'admin_email' ) . ")",
"id" => "autoresponder_email",
"std" => get_option('admin_email'),
"type" => "input"
),
array(
"name" => __("Autorespond Text", 'avia_framework' ),
"desc" => __("Enter a message that will be sent to the users email address once he has submitted the form.", 'avia_framework' )."
".
__("If left empty no auto-response will be sent.", 'avia_framework' ),
"id" => "autorespond",
"std" => "",
"type" => "textarea"
),
array(
'name' => __( 'Contact Form Captcha', 'avia_framework' ),
'desc' => $captcha_desc,
'id' => 'captcha',
'type' => 'select',
'std' => '',
'subtype' => array(
__( 'Don\'t display Captcha', 'avia_framework' ) => '',
__( 'Use Enfold Numeric Captcha', 'avia_framework' ) => 'active',
__( 'Use Google reCAPTCHA V2 if activated', 'avia_framework' ) => 'recaptcha_v2',
__( 'Use Google reCAPTCHA V3 if activated (fallback is V2)', 'avia_framework' ) => 'recaptcha_v3'
)
),
array(
'name' => __( 'reCAPTCHA V2 theme color', 'avia_framework' ),
'desc' => __( 'Select a theme color for this contact form widget', 'avia_framework' ),
'id' => 'captcha_theme',
'type' => 'select',
'required' => array( 'captcha', 'parent_in_array', 'recaptcha_v2 recaptcha_v3' ),
'std' => 'light',
'subtype' => array(
__( 'Light', 'avia_framework' ) => 'light',
__( 'Dark', 'avia_framework' ) => 'dark'
)
),
array(
'name' => __( 'reCAPTCHA V2 theme size', 'avia_framework' ),
'desc' => __( 'Select a size for this contact form widget', 'avia_framework' ),
'id' => 'captcha_size',
'type' => 'select',
'required' => array( 'captcha', 'parent_in_array', 'recaptcha_v2 recaptcha_v3'),
'std' => 'normal',
'subtype' => array(
__( 'Normal', 'avia_framework' ) => 'normal',
__( 'Compact', 'avia_framework' ) => 'compact'
)
),
array(
'name' => __( 'Select score for human', 'avia_framework' ),
'id' => 'captcha_score',
'desc' => __( 'A score of 1.0 is very likely a good interaction, 0.0 is very likely a bot. Google recommends a threshold of 0.5 by default. In case we encounter a non human we ask user to verify with Version 2 chckbox.', 'avia_framework' ),
'type' => 'select',
'required' => array( 'captcha', 'equals', 'recaptcha_v3' ),
'subtype' => AviaHtmlHelper::number_array( 0, 1, 0.1, array( __( 'Default', 'avia_framework' ) => '' ) ),
'std' => '0.5'
),
array(
"name" => __("Hide Form Labels", 'avia_framework' ),
"desc" => __("Check if you want to hide form labels above the form elements. The form will instead try to use an inline label (not supported on old browsers)", 'avia_framework' ) ,
"id" => "hide_labels",
"std" => "",
"type" => "checkbox"),
array(
"name" => __("Label/Send Button alignment", 'avia_framework' ),
"desc" => __("Select how to align the form labels and the send button", 'avia_framework' ),
"id" => "form_align",
"type" => "select",
"std" => "",
"subtype" => array(
__('Default', 'avia_framework' ) =>'',
__('Centered', 'avia_framework' ) => 'centered'
),
"std" => ""),
array(
"type" => "close_div",
'nodescription' => true
),
array(
"type" => "tab",
"name" => __("Colors",'avia_framework' ),
'nodescription' => true
),
array(
"name" => __("Form Color Scheme", 'avia_framework' ),
"desc" => __("Select a form color scheme here", 'avia_framework' ),
"id" => "color",
"type" => "select",
"std" => "",
"subtype" => array( __('Default', 'avia_framework' )=>'',
__('Light transparent', 'avia_framework' )=>'av-custom-form-color av-light-form',
__('Dark transparent', 'avia_framework' ) =>'av-custom-form-color av-dark-form'),
),
array(
"type" => "close_div",
'nodescription' => true
),
array(
'type' => 'template',
'template_id' => 'screen_options_tab'
),
array(
"type" => "close_div",
'nodescription' => true
),
));
}
/**
* Editor Sub Element - this function defines the visual appearance of an element that is displayed within a modal window and on click opens its own modal window
* Works in the same way as Editor Element
* @param array $params this array holds the default values for $content and $args.
* @return $params the return array usually holds an innerHtml key that holds item specific markup.
*/
function editor_sub_element($params)
{
$template = $this->update_template("label", __("Element", 'avia_framework' ). ": {{label}}");
$params['innerHtml'] = "";
$params['innerHtml'] .= "
Fatal Findings: The Deadly Dangers on Construction Sites in New York City
The construction industry in New York City and across the country remains one of the most dangerous jobs. Each year thousands of people are injured or killed at construction sites, including dozens in NYC alone. Increased awareness and adherence to safety regulations could prevent many of these unnecessary deaths and injuries.
At the Law Office of Asaro & Associates, we represent individuals who have been hurt or killed in construction accidents throughout New York City. Our experienced legal team has obtained millions in verdicts and settlements on behalf of our clients and will fight to get you the compensation you deserve.
If you have been injured at a NYC construction site, contact our office at (718) 650-2135 for a free consultation.
Construction and Dangerous Job Sites
According to an annual report on construction fatalities by the New York Committee for Occupational Safety and Health (NYCOSH), construction is one of the most dangerous industries for workers across the country. It is even more deadly for New York City workers. Research shows that construction worker fatalities account for 30% of all worker fatalities in NYC.
Construction site accident statistics:
Falls are the top cause of construction fatalities in the city;
Non-union job sites continue to be the most dangerous, accounting for 83% of worker fatalities in NYC;
Construction workers between the ages of 55-64 have an increased risk of dying; and
20 construction workers died in NYC in 2017, rising to 22 in 2018.
Falls continue to be the number one cause of construction fatalities in the city. Over the past decade across the state, 48% of construction fatalities were due to falls. In New York City, falls accounted for 64% of all construction deaths in 2018.
Common Causes of NYC Construction Site Deaths
The United States Department of Labor Occupational Safety and Health Administration (OSHA) has identified the four leading causes of construction site fatalities.
OSHA’s “fatal four” includes:
Falls
Electrocution
Struck by Object
Caught in or between equipment or machinery
The NYCOSH found that over the past ten years, 69% of all construction fatalities in New York City could be attributed to the fatal four. The same study indicated that as many as 85% of construction deaths in the state were the result of one of the four hazards. Tragically, nearly all injuries and deaths related to the fatal four are preventable.
Calls to Improve Construction Site Safety
As part of their findings, the NYCOSH makes several safety recommendations that may help improve the conditions on construction sites. By holding negligent contractors accountable and expanding safety requirements, it is hoped that many construction accidents will be averted.
Construction site safety recommendations:
Require training and certification for workers;
Extend and protect legislation (including New York’s Scaffold Safety Law); and
Increase “Regulations, Monitoring & Enforcement.”
NYCOSH calls on the New York Department of Labor to create a registry of workplace fatalities, helping to accurately identify and track dangerous construction sites. In addition to several other suggestions, they recommend expanding the ability for prosecutors to hold contractors criminally responsible for failing to protect workers.
Injured at a NYC Construction Site? Contact Our Office
Were you injured at a construction site in New York City? Contact our office today at (718) 650-2135 for a free case consultation. You pay nothing unless we win. Call now to speak directly with an attorney.
https://asarofirm.com/wp-content/uploads/2022/03/Asaro-Associates-Blog-Images-2.png533800Salvatore Asarohttps://asarofirm.com/wp-content/uploads/2020/01/logo-1.pngSalvatore Asaro2022-03-21 11:29:002022-04-05 16:39:12What Are the Most Common Causes of Death on NYC Construction Sites?
How Slip and Fall Accidents Differ from Trip and Fall Accidents
While many people may use the terms interchangeably, “slip and fall accidents” and “trip and fall accidents” refer to slightly different things. Both types of accidents can result in severe, life-threatening injuries and should be taken seriously. If you are injured in a fall on another person’s property, including a sidewalk or parking lot, you might be entitled to compensation.
At the Law Office of Asaro & Associates, we know the devastation that a slip or trip and fall can cause. Our award-winning legal team will fight to ensure that you receive the largest recovery possible based on your injuries. Contact our office at (718) 650-2135 for a free, no-obligation consultation if you are injured in a slip and fall or trip and fall accident.
What Is a Slip and Fall Accident?
A slip and fall accident typically refers to when someone is injured because they fell on a slippery surface. Slip and fall accidents usually involve someone losing their balance and falling backward. An unexpected fall backward can result in severe head injury, trauma to the neck or back, and broken bones.
Common causes of slip and fall accidents:
Recently mopped or waxed floors
Spilled liquids
Ice and snow that is not timely removed
Slick or uneven stairs
Loose items on the floor such as beads or marbles
In slip and fall accidents, few people have time to brace themselves before impact with a hard surface. This means that the back of their body (often the head and spine) absorbs a significant amount of force. The injuries can be debilitating, affecting your mobility and your ability to work.
What Is a Trip and Fall Accident?
A trip and fall accident differs slightly from a slip and fall accident in that the injured person generally falls forward after tripping on something. Trip and fall accidents usually result in injury to the hands, wrists, face, and knees.
Common causes of trip and fall accidents:
Loose carpeting or floorboards
Unsecured wires
Uneven sidewalk
Items left out in aisles or walkways
Poorly lit stairwells
Trip and fall accidents that cause a fall to a lower level, referred to as an “elevated fall,” are extremely serious and may be fatal. Elevated falls often happen at construction sites, stairwells, and off stages.
What to Do If You Are Involved in a Slip & Fall or Trip & Fall Accident
Regardless of whether you are involved in a slip and fall or a trip and fall accident, you should always get your injuries checked out by a medical professional as soon as possible. Delaying treatment can exacerbate your injuries or lead to serious complications.
By following a few simple steps, you can protect your right to compensation and help ensure that you make a full recovery:
Get help for your injuries. You should not move if you suspect that your head, neck, or back was injured in the fall. Have someone call 9-1-1 so that emergency medical personnel can treat you at the scene.
Notify the property owner or manager. Always report the incident to the property owner or store manager. If you are unsure who owns the property, ask the person in charge. A manager should know the proper protocol for reporting a slip and fall accident.
Collect evidence. If you are able, collect evidence at the scene. Take pictures, obtain witness information, and document anything that you can remember about the accident.
Contact an attorney. Before making any statements or signing anything, you should consult with an experienced attorney.
Hiring an attorney as early in the process as possible can ensure that you receive the compensation you deserve after an accident with injury.
Injured in a Slip, Trip, or Fall Accident? Contact Our Office.
If you have been injured in a slip and fall or trip and fall accident, contact our office at (718) 650-2135 for a free consultation. Discuss your case with a leading attorney and pay nothing unless we win. Call today to get started.
https://asarofirm.com/wp-content/uploads/2022/03/Asaro-Associates-Blog-Images-1.png533800Salvatore Asarohttps://asarofirm.com/wp-content/uploads/2020/01/logo-1.pngSalvatore Asaro2022-03-14 11:11:002022-04-05 16:38:58What Is the Difference Between Slip & Fall and Trip & Fall?
Your Rights If You Are Injured in a Construction Accident
Construction workers face some of the most dangerous working conditions in the country. Thousands of people are injured on construction sites every year. Tragically, many of these accidents are preventable, caused by negligence, inadequate safety measures, and defective machinery.
At the Law Office of Asaro & Associates, we have over 50 years of combined experience fighting for our clients. We work hard to ensure that individuals injured in construction accidents receive the compensation they deserve. If you have been injured at a construction site, contact our office at (718) 650-2135 to schedule a free consultation.
Who May Be Held Liable in a Construction Accident?
Construction accident cases can be complicated because one or more parties can be held liable. To ensure that the proper parties are held legally responsible, it is vital to consult with a lawyer, well-versed in construction accidents, immediately after the incident.
Depending on the circumstances of the case, the following parties may be held accountable for your injuries:
Property owner
Workers or contractors
Manufacturer
Construction company
Engineer
Subcontractors
Government entity
It may take an independent investigation to determine what caused the accident and who is liable. In the initial aftermath, it may be unclear whether your injuries were the result of a contractor’s negligence, an unsafe property, or improper safety procedures.
Can I Sue the Building Owner?
Building owners are required to keep their property in a reasonably safe condition and to provide adequate protection for those working on the premises. Depending on the situation, a property owner may be held liable for injuries that were caused by their negligence or wrongdoing.
Can I Sue My Employer?
Under New York law, the majority of business owners are required to carry workers’ compensation insurance. Workers’ compensation benefits provide coverage if you are injured on the job. In most cases, if you suffer a work-related injury, you would file a workers’ compensation claim in lieu of suing your employer.
Can I Sue an Independent Contractor?
In some cases, your injuries may have been caused by an independent contractor’s negligence. In the event that another person, such as a subcontractor, engineer, architect, or another worker outside of your company, caused your injuries, you may be able to sue them directly.
What If I Was Injured by a Defective or Malfunctioning Machine?
If an investigation reveals that your injuries were the result of a defective or malfunctioning machine, you may be entitled to compensation from the manufacturer. An attorney can help decide whether you have a valid claim for damages and should pursue a defective product lawsuit.
What Should I Do If I Am Injured at a Construction Site?
The first thing you should do if you are injured at a construction site is seek medical attention. Construction accidents can be severe, even life-threatening. Being evaluated and treated by a medical professional can ensure that you make a full recovery and receive the compensation you deserve.
Once you are able, it is strongly recommended that you consult with a lawyer. By retaining legal representation, you can hold the right parties accountable and get the largest possible recovery based on your injuries.
Injured in a Construction Accident? Contact Our Office Today.
Were you or a loved one injured in a construction accident? Contact our office at (718) 650-2135 to request a free, no-obligation consultation. We have recovered millions of dollars in verdicts and settlements for our clients. Call now to get started today.
https://asarofirm.com/wp-content/uploads/2022/03/Asaro-Associates-Blog-Images.png533800Salvatore Asarohttps://asarofirm.com/wp-content/uploads/2020/01/logo-1.pngSalvatore Asaro2022-03-07 17:46:542022-04-05 16:39:04Who Can I Sue If I Was Injured on a Construction Site?