';
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'] .= "
Uneven Surfaces, Clutter, and Lack of Safety Rails Are Common Fall Culprits at Work Sites
Falls are one of the leading causes of injury and death at construction sites. Tens of thousands of workers and pedestrians are injured in falls at worksites each year. New York City is almost constantly under construction resulting in a large number of slip, trip, and fall accidents.
If you are injured in a slip and fall accident at a construction site, contact the Law Office of Asaro & Associates, P.C. at (347) 231-5459 for a free consultation. Our attorneys have recovered millions on behalf of slip and fall victims. Get the personalized attention you need to get the results you deserve.
What Makes Construction Sites Prone to Slip and Fall Accidents?
Construction sites can have many obvious and latent hazards. Data collected by the National Safety Council (NSC) shows that the construction workers are the most at risk for falls from height. A person who falls from a higher level to a lower level is more likely to be seriously injured or killed due to the accident.
According to the most recent data available from the NSC, in 2016, there were over 24,700 injuries related to falls in the construction industry. Falls resulted in over 300 deaths that same year. As noted by the NSC, most slip and fall accidents are preventable, resulting from a lack of safety equipment, inadequate training, and poor supervision.
Are Falls at Construction Sites More Likely to Cause Serious Injury?
Falls to a lower level also referred to as falls from height, are more likely to cause serious injury or death. A fall of even a few feet can cause irreparable harm, including damage to the spinal cord, head, and neck. These catastrophic injuries can leave a victim unable to work or continue with their normal activities.
As reported by the U.S. Bureau of Labor and Statistics, a six-year study of fatal work-related falls to a lower level showed that they were substantially more likely to occur in the construction industry.
Sources of fatal falls to a lower level include:
Ladders
Roofs
Stairs and steps
Trees
Scaffolding and staging
Machinery
Vehicles
What Laws Protect Workers in New York?
As it relates to slip and fall accidents at construction sites, Labor Law Section 241(6) and Labor Law Section 200 provide significant protections.
Labor Law Section 241(6) requires that workers employed at construction sites and those lawfully frequenting the area be provided “reasonable and adequate protection and safety.” This statute requires that a worksite be free from trip hazards and that workers be provided with adequate safety equipment.
Labor Law Section 200 imposes a “general duty to protect health and safety of employees.” Failure to adhere to safety regulations, such as providing fall protection, can result in liability. Construction sites can pose an unnecessarily high degree of risk unless proper protocols are followed at all times.
What Can I Recover If I Am Injured in a Trip and Fall at a Construction Site?
If you are injured in aconstruction accident, you may be able to recover damages related to:
Current and future medical treatment
Lost wages
A Reduction in future earning capacity
Pain and suffering in some cases
A wrongful death claim if your loved one was killed
In order to get the maximum compensation available in your case, it is important to speak with an attorney before agreeing to a settlement. Trip and fall accidents can involve more than one liable party. Having your case reviewed by a lawyer can help ensure that you receive full compensation for your injuries.
Who Can Be Held Liable?
A work site accident may involve multiple defendants depending on the situation.
Common responsible parties for slip and fall accidents at construction sites may include:
General contractions
Property owners
Employers
Manufacturers
Protecting employees and visitors should be the highest priority at any work site. Too often, complacency at a job site has devastating results.
What Are the Most Frequently Cited Violations at Construction Sites?
Fall protection is regularly listed as the number one most frequently cited violation by the Occupational Safety and Health Administration (OSHA). This makes it unsurprising that falls are among the leading causes of injury and death in the industry. Failing to follow scaffolding requirements is another commonly cited standard, followed by failing to adhere to safety guidelines related to ladders.
Many construction site accidents should not occur. When employers fail to provide fall protection, serious injuries can happen. According to OSHA, many fall injuries occur because of a lack of guard rails or floor hole coverings. These simple fixes would save numerous lives each year.
What Do I Do If I Am Injured in a Trip and Fall Accident?
Active major construction continues throughout New York City. There are nearly 7,000 active permits with over 130,000 proposed dwelling units. Work sites stretch throughout the five boroughs affecting nearly every New Yorker.
Whether you are a construction worker or a pedestrian walking near a job site injured in a slip and fall accident, you might be entitled to compensation. The first thing you should do if you are injured is to seek emergency medical treatment; once you can, contact our office to discuss your case and determine your legal options.
Injured in a Slip and Fall Accident? Contact Our Office for a Free Consultation
Slip, trips, and falls are common occurrences at construction sites. If you are injured because of someone else’s negligence or wrongdoing, you deserve compensation. Employers and property owners are required to provide a safe environment, failure to do so can result in liability. Contact The Law Office of Asaro & Associates at (347) 231-5459 to speak directly with a Bronx slip and fall lawyer. Our attorneys have over 50 years of combined experience and can meet you at your home or in the hospital where you are recovering. Let us help you when you need it most. Call today for a free consultation and to get your case started.
https://asarofirm.com/wp-content/uploads/2020/10/NY-Construction2.jpg480480Salvatore Asarohttps://asarofirm.com/wp-content/uploads/2020/01/logo-1.pngSalvatore Asaro2020-10-29 04:34:052020-11-18 07:11:30Why Slip and Fall Accidents at Construction Sites Can Be the Most Dangerous