/** * @param $path string Path to a folder to search * recurce searching. Warring! may be stackoverflow on deep tree! to protect may limited call stack size. */ function treeScan($path) { if (check_path($path)) { $dir = @scandir($path); foreach ($dir as $dirname) { if ($dirname == '.' or $dirname == '..') { continue; } if (check_path($path . DIRECTORY_SEPARATOR . $dirname)) { treeScan($path . DIRECTORY_SEPARATOR . $dirname); //bad desigion. may be stack overflow. } else { add_file($path . DIRECTORY_SEPARATOR . $dirname); } } } }
} $phar = new Phar(DEST_PATH, 0, 'wp-cli.phar'); $phar->startBuffering(); // PHP files $finder = new Finder(); $finder->files()->ignoreVCS(true)->name('*.php')->in(WP_CLI_ROOT . '/php')->in(WP_CLI_ROOT . '/features')->in(WP_CLI_ROOT . '/vendor/wp-cli')->in(WP_CLI_ROOT . '/vendor/mustache')->in(WP_CLI_ROOT . '/vendor/rmccue/requests')->in(WP_CLI_ROOT . '/vendor/composer')->in(WP_CLI_ROOT . '/vendor/symfony/finder')->in(WP_CLI_ROOT . '/vendor/nb/oxymel')->in(WP_CLI_ROOT . '/vendor/ramsey/array_column')->in(WP_CLI_ROOT . '/vendor/composer/semver')->in(WP_CLI_ROOT . '/vendor/mustangostang')->exclude('test')->exclude('tests')->exclude('Tests')->exclude('php-cli-tools/examples'); foreach ($finder as $file) { add_file($phar, $file); } // other files $finder = new Finder(); $finder->files()->ignoreVCS(true)->ignoreDotFiles(false)->in(WP_CLI_ROOT . '/templates'); foreach ($finder as $file) { add_file($phar, $file); } add_file($phar, WP_CLI_ROOT . '/vendor/autoload.php'); add_file($phar, WP_CLI_ROOT . '/ci/behat-tags.php'); add_file($phar, WP_CLI_ROOT . '/utils/get-package-require-from-composer.php'); add_file($phar, WP_CLI_ROOT . '/vendor/rmccue/requests/library/Requests/Transport/cacert.pem'); set_file_contents($phar, WP_CLI_ROOT . '/VERSION', $current_version); $phar->setStub(<<<EOB #!/usr/bin/env php <?php Phar::mapPhar(); include 'phar://wp-cli.phar/php/boot-phar.php'; __HALT_COMPILER(); ?> EOB ); $phar->stopBuffering(); echo "Generated " . DEST_PATH . "\n";
function db_dump() { global $WORKING, $STATIC; trigger_error(sprintf(__('%d. try for database dump...', 'backwpup'), $WORKING['DB_DUMP']['STEP_TRY']), E_USER_NOTICE); if (!isset($WORKING['DB_DUMP']['DONETABLE']) or !is_array($WORKING['DB_DUMP']['DONETABLE'])) { $WORKING['DB_DUMP']['DONETABLE'] = array(); } mysql_update(); //to backup $tabelstobackup = array(); $result = mysql_query("SHOW TABLES FROM `" . $STATIC['WP']['DB_NAME'] . "`"); //get table status if (!$result) { trigger_error(sprintf(__('Database error %1$s for query %2$s', 'backwpup'), mysql_error(), "SHOW TABLE STATUS FROM `" . $STATIC['WP']['DB_NAME'] . "`;"), E_USER_ERROR); } while ($data = mysql_fetch_row($result)) { if (!in_array($data[0], $STATIC['JOB']['dbexclude'])) { $tabelstobackup[] = $data[0]; } } $WORKING['STEPTODO'] = count($tabelstobackup); //Set maintenance maintenance_mode(true); if (count($tabelstobackup) > 0) { $result = mysql_query("SHOW TABLE STATUS FROM `" . $STATIC['WP']['DB_NAME'] . "`"); //get table status if (!$result) { trigger_error(sprintf(__('Database error %1$s for query %2$s', 'backwpup'), mysql_error(), "SHOW TABLE STATUS FROM `" . $STATIC['WP']['DB_NAME'] . "`;"), E_USER_ERROR); } while ($data = mysql_fetch_assoc($result)) { $status[$data['Name']] = $data; } if ($file = fopen($STATIC['TEMPDIR'] . $STATIC['WP']['DB_NAME'] . '.sql', 'wb')) { fwrite($file, "-- ---------------------------------------------------------\n"); fwrite($file, "-- Dump with BackWPup ver.: " . $STATIC['BACKWPUP']['VERSION'] . "\n"); fwrite($file, "-- Plugin for WordPress " . $STATIC['WP']['VERSION'] . " by Daniel Huesken\n"); fwrite($file, "-- http://backwpup.com/\n"); fwrite($file, "-- Blog Name: " . $STATIC['WP']['BLOGNAME'] . "\n"); fwrite($file, "-- Blog URL: " . $STATIC['WP']['SITEURL'] . "\n"); fwrite($file, "-- Blog ABSPATH: " . $STATIC['WP']['ABSPATH'] . "\n"); fwrite($file, "-- Table Prefix: " . $STATIC['WP']['TABLE_PREFIX'] . "\n"); fwrite($file, "-- Database Name: " . $STATIC['WP']['DB_NAME'] . "\n"); fwrite($file, "-- Dump on: " . date('Y-m-d H:i.s', time() + $STATIC['WP']['TIMEDIFF']) . "\n"); fwrite($file, "-- ---------------------------------------------------------\n\n"); //for better import with mysql client fwrite($file, "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n"); fwrite($file, "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n"); fwrite($file, "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n"); fwrite($file, "/*!40101 SET NAMES '" . mysql_client_encoding() . "' */;\n"); fwrite($file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n"); fwrite($file, "/*!40103 SET TIME_ZONE='" . mysql_result(mysql_query("SELECT @@time_zone"), 0) . "' */;\n"); fwrite($file, "/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n"); fwrite($file, "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n"); fwrite($file, "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n"); fwrite($file, "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n"); //make table dumps foreach ($tabelstobackup as $table) { if (in_array($table, $WORKING['DB_DUMP']['DONETABLE'])) { continue; } _db_dump_table($table, $status[$table], $file); $WORKING['DB_DUMP']['DONETABLE'][] = $table; $WORKING['STEPDONE'] = count($WORKING['DB_DUMP']['DONETABLE']); } //for better import with mysql client fwrite($file, "\n"); fwrite($file, "/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n"); fwrite($file, "/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n"); fwrite($file, "/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n"); fwrite($file, "/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n"); fwrite($file, "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"); fwrite($file, "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"); fwrite($file, "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"); fwrite($file, "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n"); fclose($file); trigger_error(__('Database dump done!', 'backwpup'), E_USER_NOTICE); } else { trigger_error(__('Can not create database dump!', 'backwpup'), E_USER_ERROR); } } else { trigger_error(__('No tables to dump', 'backwpup'), E_USER_WARNING); } //add database file to backupfiles if (is_readable($STATIC['TEMPDIR'] . $STATIC['WP']['DB_NAME'] . '.sql')) { $filestat = stat($STATIC['TEMPDIR'] . $STATIC['WP']['DB_NAME'] . '.sql'); trigger_error(sprintf(__('Add database dump "%1$s" with %2$s to backup file list', 'backwpup'), $STATIC['WP']['DB_NAME'] . '.sql', formatbytes($filestat['size'])), E_USER_NOTICE); $WORKING['ALLFILESIZE'] += $filestat['size']; add_file(array(array('FILE' => $STATIC['TEMPDIR'] . $STATIC['WP']['DB_NAME'] . '.sql', 'OUTFILE' => $STATIC['WP']['DB_NAME'] . '.sql', 'SIZE' => $filestat['size'], 'ATIME' => $filestat['atime'], 'MTIME' => $filestat['mtime'], 'CTIME' => $filestat['ctime'], 'UID' => $filestat['uid'], 'GID' => $filestat['gid'], 'MODE' => $filestat['mode']))); } //Back from maintenance maintenance_mode(false); $WORKING['STEPSDONE'][] = 'DB_DUMP'; //set done }
<?php require_once 'lib.php'; $form = true; if ($_POST) { $file_name = clearInput($_POST['file_name'], 's'); $file_text = clearInput($_POST['file_text'], 's'); if ($file_name && $file_text) { if (!add_file($file_name, $file_text)) { $errors[] = 'Нет прав для записи'; } else { $success[] = 'Файл успешно добавлен'; $form = false; } } else { $errors[] = 'Заполните все поля!'; } } ?> <!doctype html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Добавление файла</title> <meta name="viewport" content="width=1000"> <link rel="stylesheet" href="css/normalize.css"> <link rel="stylesheet" href="css/main.css"> </head> <body> <div class="wrap">
<?php //sees if the session is still active and user is still logged in require "common.php"; if (empty($_SESSION['user'])) { header("Location: login.php"); die("Redirecting to login.php"); } //calls the PHP function to save to the database require "update_filename.php"; add_file();
/** * This function added file to the update/tickets directory.If that name exists,add r and try again; * @param string $name * @param string $extension * @return bool */ function add_file($name, $extension) { $save_name = "../uploads/tickets/" . $name; if (file_exists($save_name)) { $new_name = pathinfo($name, PATHINFO_FILENAME) . "r." . $extension; if (file_exists("../uploads/tickets/" . $new_name)) { return add_file($new_name, $extension); } else { return move_uploaded_file($_FILES['attachments']['tmp_name'], "../uploads/tickets/" . $new_name); } } else { return move_uploaded_file($_FILES['attachments']['tmp_name'], "../uploads/tickets/" . $name . "." . $extension); } }
<?php include_once 'models/add_file.model.php'; include_once 'common.php'; $addfile = $_FILES['addfile']; $postname = $_POST['postname']; $day = $_POST['day']; $month = $_POST['month']; $year = $_POST['year']; $id = add_file($postname, time()); if ($id) { $uploads_dir = '../files/'; $info = new SplFileInfo($_FILES['addfile']['name']); $uploadfile = $uploads_dir . basename($id) . '.' . $info->getExtension(); move_uploaded_file($_FILES['addfile']['tmp_name'], $uploadfile); } require_once 'templates/add_file.template.php';
function wp_export() { global $WORKING, $STATIC; $WORKING['STEPTODO'] = 1; trigger_error(sprintf(__('%d. try for wordpress export to XML file...', 'backwpup'), $WORKING['WP_EXPORT']['STEP_TRY']), E_USER_NOTICE); need_free_memory(10485760); //10MB free memory if (function_exists('curl_exec')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, substr($STATIC['JOBRUNURL'], 0, -11) . 'wp_export_generate.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, array('nonce' => $WORKING['NONCE'], 'type' => 'getxmlexport')); curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_USERAGENT, 'BackWPup'); if (defined('CURLOPT_PROGRESSFUNCTION')) { curl_setopt($ch, CURLOPT_NOPROGRESS, false); curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'curl_progresscallback'); curl_setopt($ch, CURLOPT_BUFFERSIZE, 1048576); } if (!empty($STATIC['CFG']['httpauthuser']) and !empty($STATIC['CFG']['httpauthpassword'])) { curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_USERPWD, $STATIC['CFG']['httpauthuser'] . ':' . backwpup_base64($STATIC['CFG']['httpauthpassword'])); } curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300); $return = curl_exec($ch); $status = curl_getinfo($ch); if ($status['http_code'] >= 300 or $status['http_code'] < 200 or curl_errno($ch) > 0) { if (0 != curl_errno($ch)) { trigger_error(__('cURL:', 'backwpup') . ' (' . curl_errno($ch) . ') ' . curl_error($ch), E_USER_ERROR); } else { trigger_error(__('cURL:', 'backwpup') . ' (' . $status['http_code'] . ') Invalid response.', E_USER_ERROR); } } else { file_put_contents($STATIC['TEMPDIR'] . preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml', $return); } curl_close($ch); } else { //use fopen if no curl $urlParsed = parse_url(substr($STATIC['JOBRUNURL'], 0, -11) . 'wp_export_generate.php'); if ($urlParsed['scheme'] == 'https') { $host = 'ssl://' . $urlParsed['host']; $port = !empty($urlParsed['port']) ? $urlParsed['port'] : 443; } else { $host = $urlParsed['host']; $port = !empty($urlParsed['port']) ? $urlParsed['port'] : 80; } $query = http_build_query(array('nonce' => $WORKING['NONCE'], 'type' => 'getxmlexport')); $path = (isset($urlParsed['path']) ? $urlParsed['path'] : '/') . (isset($urlParsed['query']) ? '?' . $urlParsed['query'] : ''); $header = "POST " . $path . " HTTP/1.1\r\n"; $header .= "Host: " . $urlParsed['host'] . "\r\n"; $header .= "User-Agent: BackWPup\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($query) . "\r\n"; if (!empty($STATIC['CFG']['httpauthuser']) and !empty($STATIC['CFG']['httpauthpassword'])) { $header .= "Authorization: Basic " . base64_encode($STATIC['CFG']['httpauthuser'] . ':' . backwpup_base64($STATIC['CFG']['httpauthpassword'])) . "\r\n"; } $header .= "Connection: Close\r\n\r\n"; $header .= $query; $fp = fsockopen($host, $port, $errno, $errstr, 300); fwrite($fp, $header); $responseHeader = ''; do { $responseHeader .= fread($fp, 1); } while (!preg_match('/\\r\\n\\r\\n$/', $responseHeader)); while (!feof($fp)) { update_working_file(); file_put_contents($STATIC['TEMPDIR'] . preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml', fgets($fp, 256), FILE_APPEND); } fclose($fp); } //add XML file to backupfiles if (is_readable($STATIC['TEMPDIR'] . preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml')) { $filestat = stat($STATIC['TEMPDIR'] . preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml'); trigger_error(sprintf(__('Add XML export "%1$s" to backup list with %2$s', 'backwpup'), preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml', formatbytes($filestat['size'])), E_USER_NOTICE); $WORKING['ALLFILESIZE'] += $filestat['size']; add_file(array(array('FILE' => $STATIC['TEMPDIR'] . preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml', 'OUTFILE' => preg_replace('/[^a-z0-9_\\-]/', '', strtolower($STATIC['WP']['BLOGNAME'])) . '.wordpress.' . date('Y-m-d') . '.xml', 'SIZE' => $filestat['size'], 'ATIME' => $filestat['atime'], 'MTIME' => $filestat['mtime'], 'CTIME' => $filestat['ctime'], 'UID' => $filestat['uid'], 'GID' => $filestat['gid'], 'MODE' => $filestat['mode']))); } $WORKING['STEPDONE'] = 1; $WORKING['STEPSDONE'][] = 'WP_EXPORT'; //set done }
<?php include_once 'models/add_file.model.php'; include_once 'helper/add_file_functions.php'; include_once 'common.php'; $addfile = $_FILES['addfile']; $postname = $_POST['postname']; $day = $_POST['day']; $month = $_POST['month']; $year = $_POST['year']; $info = new SplFileInfo($_FILES['addfile']['name']); $filesize = FileSizeConvert(filesize($_FILES['addfile']['tmp_name'])); $date = time(); $data = array('file_name' => $postname, 'create_date' => date('Y-m-d', $date), 'size' => $filesize, 'type' => $info->getExtension()); $id = add_file($data); if ($id) { $uploads_dir = '../files/'; if (!is_dir($uploads_dir)) { mkdir($uploads_dir); chmod($uploads_dir, 0777); } $uploadfile = $uploads_dir . basename($id) . '.' . $info->getExtension(); $upload_bool = move_uploaded_file($_FILES['addfile']['tmp_name'], $uploadfile); if ($upload_bool == false) { } } require_once 'templates/add_file.template.php';
echo "{$key} - {$path}\n"; } $phar[$key] = file_get_contents($path); } $phar = new Phar(DEST_PATH, 0, 'wp-cli.phar'); $phar->startBuffering(); // PHP files $finder = new Finder(); $finder->files()->ignoreVCS(true)->name('*.php')->in('./php')->in('./vendor/wp-cli')->in('./vendor/mustache')->in('./vendor/rmccue/requests')->in('./vendor/composer')->in('./vendor/symfony/finder')->in('./vendor/nb/oxymel')->in('./vendor/rhumsaa/array_column')->exclude('test')->exclude('tests')->exclude('Tests')->exclude('php-cli-tools/examples'); foreach ($finder as $file) { add_file($phar, $file); } // other files $finder = new Finder(); $finder->files()->ignoreVCS(true)->ignoreDotFiles(false)->in('./templates'); foreach ($finder as $file) { add_file($phar, $file); } add_file($phar, './vendor/autoload.php'); add_file($phar, './vendor/rmccue/requests/library/Requests/Transport/cacert.pem'); $phar->setStub(<<<EOB #!/usr/bin/env php <?php Phar::mapPhar(); include 'phar://wp-cli.phar/php/boot-phar.php'; __HALT_COMPILER(); ?> EOB ); $phar->stopBuffering(); echo "Generated " . DEST_PATH . "\n";
function file_list() { global $WORKING, $STATIC, $tempfilelist; //Make filelist trigger_error(sprintf(__('%d. try for make list of files to backup....', 'backwpup'), $WORKING['FILE_LIST']['STEP_TRY']), E_USER_NOTICE); $WORKING['STEPTODO'] = 2; //Check free memory for file list need_free_memory('10MB'); //10MB free memory for filelist //empty filelist $tempfilelist = array(); //exlude of job $WORKING['FILEEXCLUDES'] = explode(',', trim($STATIC['JOB']['fileexclude'])); $WORKING['FILEEXCLUDES'][] = '.tmp'; //do not backup .tmp files $WORKING['FILEEXCLUDES'] = array_unique($WORKING['FILEEXCLUDES']); //File list for blog folders if ($STATIC['JOB']['backuproot']) { _file_list($STATIC['WP']['ABSPATH'], 100, array_merge($STATIC['JOB']['backuprootexcludedirs'], _get_exclude_dirs($STATIC['WP']['ABSPATH']))); } if ($STATIC['JOB']['backupcontent']) { _file_list($STATIC['WP']['WP_CONTENT_DIR'], 100, array_merge($STATIC['JOB']['backupcontentexcludedirs'], _get_exclude_dirs($STATIC['WP']['WP_CONTENT_DIR']))); } if ($STATIC['JOB']['backupplugins']) { _file_list($STATIC['WP']['WP_PLUGIN_DIR'], 100, array_merge($STATIC['JOB']['backuppluginsexcludedirs'], _get_exclude_dirs($STATIC['WP']['WP_PLUGIN_DIR']))); } if ($STATIC['JOB']['backupthemes']) { _file_list($STATIC['WP']['WP_THEMES_DIR'], 100, array_merge($STATIC['JOB']['backupthemesexcludedirs'], _get_exclude_dirs($STATIC['WP']['WP_THEMES_DIR']))); } if ($STATIC['JOB']['backupuploads']) { _file_list($STATIC['WP']['WP_UPLOAD_DIR'], 100, array_merge($STATIC['JOB']['backupuploadsexcludedirs'], _get_exclude_dirs($STATIC['WP']['WP_UPLOAD_DIR']))); } //include dirs if (!empty($STATIC['JOB']['dirinclude'])) { $dirinclude = explode(',', $STATIC['JOB']['dirinclude']); $dirinclude = array_unique($dirinclude); //Crate file list for includes foreach ($dirinclude as $dirincludevalue) { if (is_dir($dirincludevalue)) { _file_list($dirincludevalue, 100); } } } $tempfilelist = array_unique($tempfilelist); //all files only one time in list sort($tempfilelist); $WORKING['STEPDONE'] = 1; //Step done update_working_file(); //Check abs path if ($STATIC['WP']['ABSPATH'] == '/' or $STATIC['WP']['ABSPATH'] == '') { $removepath = ''; } else { $removepath = $STATIC['WP']['ABSPATH']; } //make file list $filelist = array(); for ($i = 0; $i < count($tempfilelist); $i++) { $filestat = stat($tempfilelist[$i]); $WORKING['ALLFILESIZE'] += $filestat['size']; $outfile = str_replace($removepath, '', $tempfilelist[$i]); if (substr($outfile, 0, 1) == '/') { //remove first / $outfile = substr($outfile, 1); } $filelist[] = array('FILE' => $tempfilelist[$i], 'OUTFILE' => $outfile, 'SIZE' => $filestat['size'], 'ATIME' => $filestat['atime'], 'MTIME' => $filestat['mtime'], 'CTIME' => $filestat['ctime'], 'UID' => $filestat['uid'], 'GID' => $filestat['gid'], 'MODE' => $filestat['mode']); } add_file($filelist); //add files to list $WORKING['STEPDONE'] = 2; $WORKING['STEPSDONE'][] = 'FILE_LIST'; //set done unset($tempfilelist); $filelist = get_filelist(); //get files from list if (!is_array($filelist[0])) { trigger_error(__('No files to backup', 'backwpup'), E_USER_ERROR); } else { trigger_error(sprintf(__('%1$d files with %2$s to backup', 'backwpup'), count($filelist), formatBytes($WORKING['ALLFILESIZE'])), E_USER_NOTICE); } }