Modernized php

This commit is contained in:
Daniel Winzen
2020-10-16 18:03:06 +02:00
parent addb6b24d8
commit d42e1db5e5
9 changed files with 69 additions and 119 deletions

View File

@ -8,32 +8,30 @@ Installation instructions:
You'll need to have php with pdo_mysql, pcre, json and date extension, a web-server and a MySQL server installed.
When you have everything installed, you'll have to create a database and a user for the script.
Then edit the configuration in common_config.php to reflect the appropriate database settings and to modify the settings the way you like them.
Then edit the configuration in `common_config.php` to reflect the appropriate database settings and to modify the settings the way you like them.
Then copy the scripts to your web-server directory and run the `setup.php` script from cli, if possible.
Note: If you updated the script, please run `setup.php` again, to make sure, that any database changes are applied and no errors occur.
At last, set up cron jobs for the scripts in the `cron` directory.
Recommended schedule:
update.php - every 24 hours
`update.php` - every 24 hours
phishing_tests.php - every 24 hours, shortly after update.php
`phishing_tests.php` - every 24 hours, shortly after `update.php`
scam_tests.php - every 24 hours
tests.php - every 15 minutes
`tests.php` - every 15 minutes
Translating:
------------
Copy lang_en.php and rename it to lang_YOUR_LANGCODE.php
Copy `lang_en.php` and rename it to `lang_YOUR_LANGCODE.php`
Then edit the file and translate the messages into your language and change $I to $T at the top.
If you ever use a ' character, you have to escape it by using \' instead, or the script will fail.
When you are done, you have to edit common_config.php, to include your translation. Simply add a line with
When you are done, you have to edit `common_config.php`, to include your translation. Simply add a line with
`'lang_code' => 'Language name',`
to the $L array below the settings, similar to what I did for the German translation.
Please share your translation with me, so I can add it to the official version.
To update your translation, you can copy each new string to your translation file or edit the automated lang_update.php script to reflect you language and run it.
To update your translation, you can copy each new string to your translation file or edit the automated `lang_update.php` script to reflect you language and run it.
Live Demo:
----------

View File

@ -19,44 +19,42 @@
*/
// Configuration
define('DBHOST', 'localhost'); // Database host
define('DBUSER', 'www-data'); // Database user
define('DBPASS', 'YOUR_DB_PASS'); // Database password
define('DBNAME', 'links'); // Database
define('PREFIX', ''); // Table Prefix - useful if other programs use the same names for tables - use only alpha-numeric values (A-Z, a-z, 0-9, or _)
define('PERSISTENT', true); // Use persistent database conection true/false
define('ADMINPASS', 'YOUR_ADMIN_PASS'); // Password for the admin interface
define('PROXY', '127.0.0.1:9050'); // Socks5 Proxy to connect to (Tor)
define('USERAGENT', 'Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'); // User-Agent to use when testing a site
define('LANG', 'en'); // Default language
define('PROMOTEPRICE', 0.025); // Price to promote a site for PROMOTETIME long
define('PROMOTETIME', 2592000); // Time (in seconds) to promote a site payed with PROMOTEPRICE - 864000 equals 10 days
define('PER_PAGE', 50); // Sites listed per page
define('VERSION', '1'); // Script version
define('DBVERSION', 6); // Database layout version
define('REQUIRE_APPROVAL', false); // require admin approval of new sites? true/false
const DBHOST = 'localhost'; // Database host
const DBUSER = 'www-data'; // Database user
const DBPASS = 'YOUR_DB_PASS'; // Database password
const DBNAME = 'links'; // Database
const PREFIX = ''; // Table Prefix - useful if other programs use the same names for tables - use only alpha-numeric values (A-Z, a-z, 0-9, or _)
const PERSISTENT = true; // Use persistent database conection true/false
const ADMINPASS = 'YOUR_ADMIN_PASS'; // Password for the admin interface
const PROXY = '127.0.0.1:9050'; // Socks5 Proxy to connect to (Tor)
const USERAGENT = 'Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'; // User-Agent to use when testing a site
const LANG = 'en'; // Default language
const PROMOTEPRICE = 0.025; // Price to promote a site for PROMOTETIME long
const PROMOTETIME = 2592000; // Time (in seconds) to promote a site payed with PROMOTEPRICE - 864000 equals 10 days
const PER_PAGE = 50; // Sites listed per page
const VERSION = '1'; // Script version
const DBVERSION = 6; // Database layout version
const REQUIRE_APPROVAL = false; // require admin approval of new sites? true/false
//Categories - new links will always be put into the first one, leave it to Unsorted
//once configured, only add new categories at the end or you have to manually adjust the database.
$categories=['Unsorted', 'Adult/Porn', 'Communication/Social', 'Forums', 'Hacking/Programming/Software', 'Hosting', 'Libraries/Wikis', 'Link Lists', 'Market/Shop/Store', 'Other', 'Personal Sites/Blogs', 'Security/Privacy/Encryption', 'Whistleblowing', 'Empty/Error/Unknown', 'Cryptocurrencies', 'Scams', 'Fun/Games/Joke', 'Search', 'Autodetected scam (unchecked)'];
// Language selection
$I = [];
$I = $T = [];
$language = LANG;
$L=[
'de' => 'Deutsch',
'en' => 'English',
'ja' => '日本語',
'tr' => 'Türkçe',
];
if(isSet($_REQUEST['lang']) && isSet($L[$_REQUEST['lang']])){
if(isset($_REQUEST['lang']) && isset($L[$_REQUEST['lang']])){
$language=$_REQUEST['lang'];
if(!isSet($_COOKIE['language']) || $_COOKIE['language']!==$language){
if(!isset($_COOKIE['language']) || $_COOKIE['language']!==$language){
set_secure_cookie('language', $language);
}
}elseif(isSet($_COOKIE['language']) && isSet($L[$_COOKIE['language']])){
}elseif(isset($_COOKIE['language']) && isset($L[$_COOKIE['language']])){
$language=$_COOKIE['language'];
}else{
$language=LANG;
}
require_once(__DIR__.'/lang_en.php'); //always include English
if($language!=='en'){
@ -81,7 +79,7 @@ function print_langs(){
echo '</small>';
}
function blacklist_scams($address, $content){
function blacklist_scams(string $address, string $content){
global $db;
$scams = ['Black&White Cards :: Index', 'Shadow guide | The ultimate guide of dark web ', 'ONIONLIST - SAFE .ONION LINKS LISTING', 'Dir ', 'netAuth', 'POPBUY MARKET', 'Digital Goods - Verified by GoDark Search, Hidden Links, Wiki, Escrow', 'Delta - Secure Black Market', 'DeDope', 'Unlocker - iCloud Activation Services', '222LOTTO!', 'STREAMING SERVICES ACCOUNTS', 'Red Room', 'Digital Cash'];
$cp_scams = ['Wonderful shop', '~ DROP BY TARYAXX ~', 'Magic CP', 'Lolita Club', 'Daft Tadjikskiy Sex Video _ Inductively Fiberless Porno Qom Along With Post Porn Com Numb _ Porn Zdarma', 'xPlay - hosting service for porn videos', 'DARK PRIVATE PACK', 'Good Porn'];
@ -132,7 +130,7 @@ function send_headers(array $styles = []){
}
}
function set_secure_cookie($name, $value){
function set_secure_cookie(string $name, string $value){
if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
setcookie($name, $value, ['expires' => 0, 'path' => '/', 'domain' => '', 'secure' => is_definitely_ssl(), 'httponly' => true, 'samesite' => 'Strict']);
}else{
@ -140,7 +138,7 @@ function set_secure_cookie($name, $value){
}
}
function is_definitely_ssl() {
function is_definitely_ssl() : bool {
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
return true;
}

View File

@ -1,5 +1,5 @@
<?php
// Executed every 25 hours via cron - checks for phishing clones on known phishing sites.
// Executed daily via cronjob - checks for phishing clones on known phishing sites.
date_default_timezone_set('UTC');
require_once(__DIR__.'/../common_config.php');
try{
@ -14,10 +14,11 @@ curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 25);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
check('http://tt3j2x4k5ycaa5zt.onion/onions.php?cat=15&pg=0', 'http://tt3j277rncfaqmj7.onion/onions.php?cat=15&pg=0');
check('http://skunksworkedp2cg.onion/sites.html', 'http://skunkrdunsylcfqd.onion/sites.html');
//check('http://tt3j2x4k5ycaa5zt.onion/onions.php?cat=15&pg=0', 'http://tt3j277rncfaqmj7.onion/onions.php?cat=15&pg=0');
//check('http://skunksworkedp2cg.onion/sites.html', 'http://skunkrdunsylcfqd.onion/sites.html');
check('http://dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion/list.php', 'http://dhostingwwafxyuaxhs6bkhzo5e2mueztbmhqe6wsng547ucvzfuh2ad.onion/list.php');
function check($link, $phishing_link){
function check(string $link, string $phishing_link){
global $ch, $db;
curl_setopt($ch, CURLOPT_URL, $link);
$links=curl_exec($ch);
@ -27,8 +28,9 @@ function check($link, $phishing_link){
$phishings=$db->prepare('INSERT IGNORE INTO ' . PREFIX . 'phishing (onion_id, original) VALUES ((SELECT id FROM onions WHERE md5sum=?), ?);');
$select=$db->prepare('SELECT id FROM ' . PREFIX . 'onions WHERE md5sum=?;');
$insert=$db->prepare('INSERT INTO ' . PREFIX . 'onions (address, md5sum, timeadded) VALUES (?, ?, ?);');
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}).onion(/[^\s><"]*)?~i', $links, $addr);
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}).onion(/[^\s><"]*)?~i', $phishing_links, $phishing_addr);
$update=$db->prepare('UPDATE ' . PREFIX . 'onions SET locked=1 WHERE md5sum=?;');
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}|[a-z2-7]{56}).onion(/[^\s><"]*)?~i', $links, $addr);
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}|[a-z2-7]{56}).onion(/[^\s><"]*)?~i', $phishing_links, $phishing_addr);
$count=count($addr[3]);
if($count===count($phishing_addr[3])){ //only run with same data set
for($i=0; $i<$count; ++$i){
@ -41,6 +43,7 @@ function check($link, $phishing_link){
$insert->execute([$phishing_address, $md5, time()]);
}
$phishings->execute([$md5, $address]);
$update->execute([$md5]);
}
}
}

View File

@ -1,52 +0,0 @@
<?php
// Executed daily via cronjob - checks for phishing clones on known phishing sites.
date_default_timezone_set('UTC');
require_once(__DIR__.'/../common_config.php');
try{
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
die($I['nodb']);
}
$ch=curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, PROXY);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 25);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
//check('http://onionsnjajzkhm5g.onion/onions.php?cat=15&pg=0', 'http://onionsbnvrzmxsoe.onion/onions.php?cat=15&pg=0');
//check('http://7cbqhjnlkivmigxf.onion', 'http://7cbqhjnpcgixggts.onion');
check('http://dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion/list.php', 'http://dhostingwwafxyuaxhs6bkhzo5e2mueztbmhqe6wsng547ucvzfuh2ad.onion/list.php');
function check($link, $phishing_link){
global $ch, $db;
curl_setopt($ch, CURLOPT_URL, $link);
$links=curl_exec($ch);
curl_setopt($ch, CURLOPT_URL, $phishing_link);
$phishing_links=curl_exec($ch);
if(!empty($links) && !empty($phishing_links)){
$phishings=$db->prepare('INSERT IGNORE INTO ' . PREFIX . 'phishing (onion_id, original) VALUES ((SELECT id FROM onions WHERE md5sum=?), ?);');
$select=$db->prepare('SELECT id FROM ' . PREFIX . 'onions WHERE md5sum=?;');
$insert=$db->prepare('INSERT INTO ' . PREFIX . 'onions (address, md5sum, timeadded) VALUES (?, ?, ?);');
$update=$db->prepare('UPDATE ' . PREFIX . 'onions SET locked=1 WHERE md5sum=?;');
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}|[a-z2-7]{56}).onion(/[^\s><"]*)?~i', $links, $addr);
preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}|[a-z2-7]{56}).onion(/[^\s><"]*)?~i', $phishing_links, $phishing_addr);
$count=count($addr[3]);
if($count===count($phishing_addr[3])){ //only run with same data set
for($i=0; $i<$count; ++$i){
if($addr[3][$i]!==$phishing_addr[3][$i]){
$address=strtolower($addr[3][$i]);
$phishing_address=strtolower($phishing_addr[3][$i]);
$md5=md5($phishing_address, true);
$select->execute([$md5]);
if(!$select->fetch(PDO::FETCH_NUM)){
$insert->execute([$phishing_address, $md5, time()]);
}
$phishings->execute([$md5, $address]);
$update->execute([$md5]);
}
}
}
}
}

View File

@ -37,13 +37,14 @@ add_onions($onions, $db);
//delete links that were not seen within a month
$db->exec('DELETE FROM ' . PREFIX . "onions WHERE address!='' AND timediff>2419200 AND lasttest-timeadded>2419200;");
function check_links(&$onions, &$ch, $link_to_check, $scan_children = false, &$scanned_onoins = []){
function check_links(array &$onions, CurlHandle &$ch, string $link_to_check, bool $scan_children = false, array &$scanned_onoins = []){
curl_setopt($ch, CURLOPT_URL, $link_to_check);
$links=curl_exec($ch);
if(preg_match_all('~(https?://)?([a-z0-9]*\.)?([a-z2-7]{16}|[a-z2-7]{56}).onion(/[^\s><"]*)?~i', $links, $addr)){
$mh = null;
$curl_handles = [];
if($scan_children){
$mh = curl_multi_init();
$curl_handles = [];
}
foreach($addr[3] as $link){
$link=strtolower($link);
@ -96,7 +97,7 @@ function add_onions(&$onions, $db){
// $update=$db->prepare('UPDATE ' . PREFIX . "onions SET address = '', locked=1, description=CONCAT(description, ' - SCAM'), category=15 WHERE md5sum=? AND address!='';");
$stmt=$db->query('SELECT md5sum FROM ' . PREFIX . 'onions;');
while($tmp=$stmt->fetch(PDO::FETCH_NUM)){
if(isSet($onions[$tmp[0]])){
if(isset($onions[$tmp[0]])){
unset($onions[$tmp[0]]);
// $update->execute($tmp);
}

View File

@ -2,7 +2,8 @@
$native = 'Deutsch'; // Native lanugae name
$english = 'German'; // English language name
$code = 'de'; // Language code
$I=[];
$T=[];
ob_start();
echo "<?php
/*
@ -32,7 +33,7 @@ if(file_exists("lang_$code.php")){
}
include('lang_en.php');
foreach($T as $id=>$value){
if(isSet($I[$id])){
if(isset($I[$id])){
$I[$id]=$value;
}
}

View File

@ -18,13 +18,13 @@ echo "<h1>$I[admintitle]</h1>";
print_langs();
//check password
if(!isSet($_POST['pass']) || $_POST['pass']!==ADMINPASS){
if(!isset($_POST['pass']) || $_POST['pass']!==ADMINPASS){
echo "<form action=\"$_SERVER[SCRIPT_NAME]\" method=\"POST\">";
echo "<input type=\"hidden\" name=\"lang\" value=\"$language\">";
echo "<p>$I[password]: <input type=\"password\" name=\"pass\" size=\"30\" required></p>";
echo "<input type=\"submit\" name=\"action\" value=\"$I[login]\">";
echo '</form>';
if(isSet($_POST['pass'])){
if(isset($_POST['pass'])){
echo "<p class=\"red\">$I[wrongpass]</p>";
}
}else{
@ -57,12 +57,12 @@ if(!isSet($_POST['pass']) || $_POST['pass']!==ADMINPASS){
echo '</table>';
}
echo "<p>$I[cloneof]: <input type=\"text\" name=\"original\" size=\"30\"";
if(isSet($_REQUEST['original'])){
if(isset($_REQUEST['original'])){
echo ' value="'.htmlspecialchars($_REQUEST['original']).'"';
}
echo '></p>';
echo "<p>$I[bitcoins]: <input type=\"text\" name=\"btc\" size=\"30\"";
if(isSet($_REQUEST['btc'])){
if(isset($_REQUEST['btc'])){
echo ' value="'.htmlspecialchars($_REQUEST['btc']).'"';
}
echo '></p>';
@ -82,10 +82,10 @@ if(!isSet($_POST['pass']) || $_POST['pass']!==ADMINPASS){
}
}
echo '</textarea></p>';
if(isSet($_REQUEST['cat']) && $_REQUEST['cat']<count($categories) && $_REQUEST['cat']>=0){
if(isset($_REQUEST['cat']) && $_REQUEST['cat']<count($categories) && $_REQUEST['cat']>=0){
$category=$_REQUEST['cat'];
}
if(!isSet($category)){
if(!isset($category)){
$category=count($categories);
}
echo "<p>$I[category]: <select name=\"cat\">";

View File

@ -53,7 +53,7 @@ function send_html(){
$I['lastadded']=>"address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing)',
$I['offline']=>"address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff>604800'
];
if(!isSet($_REQUEST['pg'])){
if(!isset($_REQUEST['pg'])){
$_REQUEST['pg']=1;
}else{
settype($_REQUEST['pg'], 'int');
@ -74,7 +74,7 @@ function send_html(){
echo "<h1>$I[title]</h1>";
print_langs();
echo "<br><small>$I[format]: <a href=\"?format=text\" target=\"_self\">Text</a> <a href=\"?format=json\" target=\"_self\">JSON</a></small>";
if(!isSet($db)){
if(!isset($db)){
echo "<p><b class=\"red\">$I[error]:</b> $I[nodb]</p>";
echo '</body></html>';
exit;
@ -85,7 +85,7 @@ function send_html(){
echo "<input type=\"hidden\" name=\"pg\" value=\"$_REQUEST[newpg]\">";
echo "<input type=\"hidden\" name=\"lang\" value=\"$language\">";
echo "<p><label>$I[addonion]: <br><input name=\"addr\" size=\"30\" placeholder=\"http://$_SERVER[HTTP_HOST]\" value=\"";
if(isSet($_REQUEST['addr'])){
if(isset($_REQUEST['addr'])){
echo htmlspecialchars($_REQUEST['addr']);
}
echo '" required></label></p>';
@ -105,11 +105,11 @@ function send_html(){
}
}
echo '</textarea></label></p>';
if(isSet($_REQUEST['cat']) && $_REQUEST['cat']<(count($categories)+count($special)+1) && $_REQUEST['cat']>=0){
if(isset($_REQUEST['cat']) && $_REQUEST['cat']<(count($categories)+count($special)+1) && $_REQUEST['cat']>=0){
settype($_REQUEST['cat'], 'int');
$category=$_REQUEST['cat'];
}
if(!isSet($category)){
if(!isset($category)){
$category=count($categories);
}
echo "<p><label>$I[category]: <select name=\"cat\">";
@ -128,7 +128,7 @@ function send_html(){
echo "<input type=\"hidden\" name=\"pg\" value=\"$_REQUEST[newpg]\">";
echo "<input type=\"hidden\" name=\"lang\" value=\"$language\">";
echo "<p><label>$I[search]: <br><input name=\"q\" size=\"30\" placeholder=\"$I[searchterm]\" value=\"";
if(isSet($_REQUEST['q'])){
if(isset($_REQUEST['q'])){
echo htmlspecialchars($_REQUEST['q']);
}
echo '"></label></p>';
@ -234,7 +234,7 @@ function send_html(){
if($category==count($categories)){
$category=0;
}
if(!isSet($_POST['desc'])){
if(!isset($_POST['desc'])){
$desc='';
}else{
$desc=trim($_POST['desc']);
@ -288,6 +288,7 @@ function send_html(){
print_phishing_table();
}elseif($category>=count($categories)){//show special categories
$tmp=$category-count($categories);
$query = '';
foreach($special as $name=>$query){
if($tmp===0) break;
--$tmp;
@ -320,7 +321,7 @@ function send_html(){
echo '</body></html>';
}
function get_table(PDOStatement $stmt, &$numrows=0, $promoted=false){
function get_table(PDOStatement $stmt, int &$numrows = 0, bool $promoted = false) : string {
global $I, $db, $language;
$time=time();
$admin_approval = '';
@ -417,7 +418,7 @@ function print_phishing_table(){
function send_text(){
global $I, $db;
if(!isSet($db)){
if(!isset($db)){
die("$I[error]: $I[nodb]");
}
header('Content-Type: text/plain; charset=UTF-8');
@ -433,7 +434,7 @@ function send_text(){
function send_json(){
global $I, $db, $categories;
if(!isSet($db)){
if(!isset($db)){
die("$I[error]: $I[nodb]");
}
header('Content-Type: application/json;');
@ -453,7 +454,7 @@ function send_json(){
echo json_encode($data);
}
function get_pagination($category, $pages){
function get_pagination(int $category, int $pages) : string {
global $I, $language;
ob_start();
echo "<ul class=\"list\"><li>$I[pages]:</li>";
@ -520,6 +521,6 @@ function send_captcha(){
echo "<input type=\"hidden\" name=\"challenge\" value=\"$randid\"><input type=\"text\" name=\"captcha\" size=\"15\" autocomplete=\"off\"></label></p>";
}
function send_error($msg){
function send_error(string $msg){
die("<p class=\"red\">$msg</p></div></body></html>");
}

View File

@ -15,7 +15,7 @@ echo "<p>$I[testdesc]</p>";
echo "<form action=\"$_SERVER[SCRIPT_NAME]\" method=\"POST\">";
echo "<input type=\"hidden\" name=\"lang\" value=\"$language\">";
echo "<p>$I[link]: <br><input name=\"addr\" size=\"30\" value=\"";
if(isSet($_REQUEST['addr'])){
if(isset($_REQUEST['addr'])){
echo htmlspecialchars($_REQUEST['addr']);
}else{
echo "http://$_SERVER[HTTP_HOST]";
@ -67,7 +67,7 @@ if(!empty($_REQUEST['addr'])){
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($content, 0, $header_size);
$content = substr($content, $header_size);
if(isSet($db)){
if(isset($db)){
//update entry in database
$stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'onions WHERE md5sum=?;');
$stmt->execute([$md5]);
@ -99,7 +99,7 @@ if(!empty($_REQUEST['addr'])){
}
echo "<p class=\"green\">$I[testonline]</p>";
}else{
if(isSet($db)){
if(isset($db)){
$time=time();
$db->prepare('UPDATE ' . PREFIX . 'onions SET lasttest=?, timediff=lasttest-lastup WHERE md5sum=? AND lasttest<?;')->execute([$time, $md5, $time]);
}