/** * save log * @param * @return boolean */ function log($arr) { //indexes: //author_id = given author id, if not given, check data array for author id, if not given, check login, if not given, set to 0=system //action = text = new/edit/delete //object = contact/ticket/contact_group/object/contact_type etc //data = array with data, e.g. from $contact array addContact Method etc. $Return = false; //check values //set log date $this->LOG['date'] = date("Y-m-d H:i:s"); //chekc for author id $this->LOG['author_id'] = 0; //default is 0=system if (isset($arr['author_id']) && check_dbid($arr['author_id'])) { //if valid author_id in arr $this->LOG['author_id'] = $arr['author_id']; } else { //else check for author_id in data array if (isset($arr['data']['author_id']) && check_dbid($arr['data']['author_id'])) { $this->LOG['author_id'] = $arr['data']['author_id']; } else { // else, if not set at all get author id from logged in user global $LOGIN; if (isset($LOGIN->USER['id']) && check_dbid($LOGIN->USER['id'])) { $this->LOG['author_id'] = $LOGIN->USER['id']; } } } //action //action should always be set, default is -- $this->LOG['action'] = "--"; if (isset($arr['action']) && !empty($arr['action'])) { //wenn aktion definiert $this->LOG['action'] = $arr['action']; } //object //object should always be set, default is -- $this->LOG['object'] = "--"; if (isset($arr['object']) && !empty($arr['object'])) { //wenn aktion definiert $this->LOG['object'] = $arr['object']; } //edit_id, die id des geaenderten datensatzes! oder neuen datensatzes, defakto muss log() erst am ende einer add methode aufgerufen werden wenn die id bekannt ist! //edit_id should always be set, default is 0 $this->LOG['edit_id'] = 0; if (isset($arr['data']['id']) && !empty($arr['data']['id'])) { //wenn id $this->LOG['edit_id'] = $arr['data']['id']; } $this->LOG['memo'] = ""; if (isset($arr['memo'])) { $this->LOG['memo'] = $arr['memo']; } $this->LOG['s_data'] = serialize($arr['data']); //hmmm, falls loeschung, daten aus altem datensatz anhand id ermitteln.... hmmmm if ($this->LOG['action'] == "delete" && check_dbid($this->LOG['edit_id'])) { switch ($this->LOG['object']) { //default: #no default, default : require_once (TM_INCLUDEPATH."/Welcome.inc.php"); break; case 'usr': $LINK = new tm_CFG(); $DATA = $LINK->getUser("", $this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA); break; case 'adr': $LINK = new tm_ADR(); $DATA = $LINK->getAdr($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'adr_grp': $LINK = new tm_ADR(); $DATA = $LINK->getGroup($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'nl': $LINK = new tm_NL(); $DATA = $LINK->getNL($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'nl_grp': $LINK = new tm_NL(); $DATA = $LINK->getGroup($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'bl': $LINK = new tm_BLACKLIST(); $DATA = $LINK->getBL($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'frm': $LINK = new tm_FRM(); $DATA = $LINK->getForm($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'host': $LINK = new tm_HOST(); $DATA = $LINK->getHost($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'q': $LINK = new tm_Q(); $DATA = $LINK->getQ($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'lnk': $LINK = new tm_LNK(); $DATA = $LINK->get($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; case 'lnk_grp': $LINK = new tm_LNK(); $DATA = $LINK->getGroup($this->LOG['edit_id']); $this->LOG['s_data'] = serialize($DATA[0]); break; } //switch } //if action=delete //serialisierte werte speichern, ein eintrag in die db pro aktion! $Query = "INSERT INTO " . TM_TABLE_LOG . " (\n\t\t\t\t\t\tdate,\n\t\t\t\t\t\tauthor_id,\n\t\t\t\t\t\taction,\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\tx_value,\n\t\t\t\t\t\tedit_id,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tmemo,\n\t\t\t\t\t\tsiteid\n\t\t\t\t\t\t)\n\t\t\t\t\t\tVALUES (\n\t\t\t\t\t\t'" . dbesc($this->LOG["date"]) . "',\n\t\t\t\t\t\t" . checkset_int($this->LOG["author_id"]) . ",\n\t\t\t\t\t\t'" . dbesc($this->LOG["action"]) . "',\n\t\t\t\t\t\t'" . dbesc($this->LOG["object"]) . "',\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t" . checkset_int($this->LOG["edit_id"]) . ",\n\t\t\t\t\t\t'" . dbesc($this->LOG['s_data']) . "',\n\t\t\t\t\t\t'" . dbesc($this->LOG['memo']) . "',\n\t\t\t\t\t\t'" . TM_SITEID . "')"; if ($this->DB->Query($Query)) { $Return = true; } else { $Return = FALSE; return $Return; } /* //jeden wert einzeln speichern, ist aber unsinnn!!!! //iterate data array, fetch all indexes and values and save...... yes, it becomes a very very big table!!!!! anders gehts halt nicht! foreach ($arr['data'] as $data_key => $data_val) { if (DEBUG) $_MAIN_MESSAGE.= "$data_key => $data_val\n, "; $Query ="INSERT INTO ".TM_TABLE_LOG." ( date, author_id, action, object, property, x_value, edit_id, siteid ) VALUES ( '".dbesc($this->LOG["date"])."', '".checkset_int($this->LOG["author_id"])."', '".dbesc($this->LOG["action"])."', '".dbesc($this->LOG["object"])."', '".dbesc($data_key)."', '".dbesc($data_val)."', '".checkset_int($this->LOG["edit_id"])."', '".TM_SITEID."')"; if (DEBUG_SQL) $_MAIN_MESSAGE.="\n".$Query."<br>"; if ($this->DB->Query($Query)) { $Return=true; } else { $Return=FALSE; return $Return; } }//foreach */ return $Return; }
$nl_id = getVar("nl_id"); $a_id = getVar("a_id"); $code = getVar("code"); if (DEBUG) { $FMESSAGE .= tm_debugmessage("DEBUG enabled"); } if (!isset($_CONTENT)) { $_CONTENT = ""; } if (!isset($called_via_url)) { if (DEBUG) { $FMESSAGE .= tm_debugmessage("valled_via_url = true"); } $called_via_url = true; } $HOSTS = new tm_HOST(); #$HOST=$HOSTS->getStdSMTPHost(); if (DEBUG) { $FMESSAGE .= tm_debugmessage("select smtp host with id " . $C[0]['unsubscribe_host']); } $HOST = $HOSTS->getHost($C[0]['unsubscribe_host']); $check = true; $InputName_Name = "email"; //email ${$InputName_Name} = getVar($InputName_Name); $InputName_Captcha = "fcpt"; //einbgegebener Captcha Code ${$InputName_Captcha} = getVar($InputName_Captcha); $cpt = getVar("cpt"); //zu pruefender captchacode, hidden field, $captcha_code //if isset $a_id and adr exists and adr code=c, then prefill email!
/********************************************************************************/ /* this file is part of: / diese Datei ist ein Teil von: */ /* tellmatic, the newslettermachine */ /* tellmatic, die Newslettermaschine */ /* 2006/7 by Volker Augustin, multi.art.studio Hanau */ /* Contact/Kontakt: info@tellmatic.org */ /* Homepage: www.tellmatic.org */ /* leave this header in file! */ /* diesen Header nicht loeschen! */ /* check Homepage for Updates and more Infos */ /* Besuchen Sie die Homepage fuer Updates und weitere Infos */ /********************************************************************************/ $_MAIN_OUTPUT .= "\n\n<!-- bounce.inc -->\n\n"; $_MAIN_DESCR = ___("Bounce Management"); $_MAIN_MESSAGE .= ""; $HOSTS = new tm_HOST(); $set = getVar("set"); $InputName_Limit = "limit"; ${$InputName_Limit} = getVar($InputName_Limit); if (${$InputName_Limit} < 1 || empty(${$InputName_Limit})) { ${$InputName_Limit} = 10; } $InputName_Offset = "offset"; ${$InputName_Offset} = getVar($InputName_Offset); if (${$InputName_Offset} < 0 || empty(${$InputName_Offset})) { ${$InputName_Offset} = 0; } //export $InputName_Export = "export"; // ${$InputName_Export} = getVar($InputName_Export);
/***********************************************************/ if (!DEMO) { $pass_hash = md5(TM_SITEID . $name . $pass); $CONFIG = new tm_CFG(); $CONFIG->addUSER(array("siteid" => TM_SITEID, "name" => $name, "passwd" => $pass_hash, "crypt" => crypt($pass, CRYPT_EXT_DES), "email" => $email, "aktiv" => 1, "admin" => 1, "manager" => 1, "style" => "default", "lang" => $lang, "startpage" => "Welcome", "expert" => 0)); } //demo $MESSAGE .= "<br>" . sprintf(___("Benutzer '%s' wurde angelegt."), $name); /***********************************************************/ //add config /***********************************************************/ if (!DEMO) { //insert config $CONFIG->addCFG(array("siteid" => TM_SITEID, "name" => "Tellmatic_0", "lang" => $lang, "style" => "default", "notify_mail" => $email, "notify_subscribe" => 0, "notify_unsubscribe" => 0, "max_mails_retry" => 5, "emailcheck_intern" => 2, "emailcheck_subscribe" => 2, "emailcheck_sendit" => 1, "emailcheck_checkit" => 3, "check_version" => 1, "rcpt_name" => "Newsletter", "track_image" => '_blank', "unsubscribe_use_captcha" => 0, "unsubscribe_digits_captcha" => 4, "unsubscribe_sendmail" => 1, "unsubscribe_action" => "unsubscribe", "unsubscribe_host" => 1, "checkit_limit" => 25, "checkit_from_email" => '', "checkit_adr_reset_error" => 1, "checkit_adr_reset_status" => 1, "bounceit_limit" => 10, "bounceit_host" => 0, "bounceit_action" => 'auto', "bounceit_search" => 'header', "bounceit_filter_to" => 0, "bounceit_filter_to_email" => '', "proof" => 1, "proof_url" => 'http://proof.tellmatic.org', "proof_trigger" => 10, "proof_pc" => 10)); //add mailservers, use default settings for config and create smtp/pop3 host entries... $HOSTS = new tm_HOST(); //add smtp host $Add_Host = $HOSTS->addHost(array("siteid" => TM_SITEID, "name" => "default smtp", "aktiv" => 1, "host" => $smtp_host, "port" => $smtp_port, "options" => "novalidate-cert", "smtp_auth" => $smtp_auth, "smtp_domain" => $smtp_domain, "smtp_ssl" => 0, "smtp_max_piped_rcpt" => 1, "type" => "smtp", "user" => $smtp_user, "pass" => $smtp_pass, "max_mails_atonce" => 25, "max_mails_bcc" => 1, "sender_name" => "Tellmatic", "sender_email" => $email, "return_mail" => $email, "reply_to" => $email, "delay" => 100000)); //make default smtp host! $HOSTS->setHostStd($Add_Host[1]); //add pop3 host $HOSTS->addHost(array("siteid" => TM_SITEID, "name" => "default pop3", "aktiv" => 1, "host" => $smtp_host, "port" => 110, "options" => "novalidate-cert", "smtp_auth" => "", "smtp_domain" => "", "smtp_ssl" => 0, "smtp_max_piped_rcpt" => 1, "type" => "pop3", "user" => $smtp_user, "pass" => $smtp_pass, "max_mails_atonce" => 25, "max_mails_bcc" => 1, "sender_name" => "Tellmatic", "sender_email" => $email, "return_mail" => $email, "reply_to" => $email, "delay" => 100000)); } $MESSAGE .= "<br>" . ___("Einstellungen wurden gespeichert."); /***********************************************************/ //create configfile /***********************************************************/ $tm_config = '<?php' . "\n" . '//domain' . "\n" . 'if (isset($_SERVER[\'HTTPS\'])) {' . "\n" . '$protocol = $_SERVER[\'HTTPS\'] ? "https://" : "http://";' . "\n" . '} else {' . "\n" . '$protocol = "http://";' . "\n" . '}' . "\n" . 'define("TM_DOMAIN",$protocol.\'' . TM_DOMAINNAME . '\');' . "\n" . '//absoluter pfad , docroot' . "\n" . 'define("TM_DOCROOT",\'' . TM_DOCROOT . '\');' . "\n" . '//script verzeichnis' . "\n" . 'define("TM_DIR",\'' . TM_DIR . '\');' . "\n" . '//table prefix' . "\n" . '$tm_tablePrefix=\'' . $tm_tablePrefix_cfg . '\';' . "\n" . '//database' . "\n" . '$tm["DB"]["Name"]=\'' . $db_name . '\';' . "\n" . '$tm["DB"]["Host"]=\'' . $db_host . '\';' . "\n" . '$tm["DB"]["Port"]=\'' . $db_port . '\';' . "\n" . '$tm["DB"]["Socket"]=\'' . $db_socket . '\';' . "\n" . '$tm["DB"]["User"]=\'' . $db_user . '\';' . "\n" . '$tm["DB"]["Pass"]=\'' . $db_pass . '\';' . "\n" . '/////////////////////////////////' . "\n" . 'include (TM_DOCROOT."/".TM_DIR."/include/tm_lib.inc.php");' . "\n" . '/////////////////////////////////' . "\n" . '?>'; /***********************************************************/ //create htaccess files /***********************************************************/
/********************************************************************************/ /* this file is part of: / diese Datei ist ein Teil von: */ /* tellmatic, the newslettermachine */ /* tellmatic, die Newslettermaschine */ /* 2006/7 by Volker Augustin, multi.art.studio Hanau */ /* Contact/Kontakt: info@tellmatic.org */ /* Homepage: www.tellmatic.org */ /* leave this header in file! */ /* diesen Header nicht loeschen! */ /* check Homepage for Updates and more Infos */ /* Besuchen Sie die Homepage fuer Updates und weitere Infos */ /********************************************************************************/ $_MAIN_DESCR = ___("Newsletter Warteschlange (Q)"); $_MAIN_MESSAGE .= ""; $QUEUE = new tm_Q(); $HOSTS = new tm_HOST(); $ADDRESS = new tm_ADR(); $NEWSLETTER = new tm_NL(); $set = getVar("set"); $val = getVar("val"); $q_id = getVar("q_id"); $nl_id = getVar("nl_id"); $grp_id = getVar("grp_id"); $doit = getVar("doit"); //wird per js an url angefuegt!!! confirm() //logfile if (check_dbid($q_id)) { $Q = $QUEUE->getQ($q_id); $logfilename = "q_.log.html"; if (isset($Q[0]['id'])) { $logfilename = "q_" . $Q[0]['id'] . "_" . $Q[0]['grp_id'] . "_" . date_convert_to_string($Q[0]['created']) . ".log.html";
if adr not exists, update adr record fetch adr record again if adr not exists and double optin is used, send double optin mail to user/admin if adr not exists and no double optin is used, send notify mail to user/admin if adr already exists, send update mail to user/admin (optional) if adr not exists, count/add subscription to form show successmessage $Form_Filename if we have a valid form and set is not set to 'save' yet, no double optin confirmation or form input not ok: show form */ if (!isset($_CONTENT)) { $_CONTENT = ""; } if (!isset($called_via_url)) { $called_via_url = true; } $HOSTS = new tm_HOST(); $NEWSLETTER = new tm_NL(); $FORMULAR = new tm_FRM(); $ADDRESS = new tm_ADR(); $_Tpl_FRM = new tm_Template(); $MESSAGE = ""; $OUTPUT = ""; if (DEBUG && $called_via_url) { $OUTPUT .= tm_debugmessage("called via url"); } if (DEBUG && !$called_via_url) { $OUTPUT .= tm_debugmessage("included"); } $date_sub = date(TM_NL_DATEFORMAT); //used in template and email, formatted if (!isset($frm_id) || empty($frm_id)) {
$check = false; $_MAIN_MESSAGE .= "<br>" . ___("Die Antwort-E-Mail-Adresse ist nicht gültig.") . " " . $check_mail[1]; } if (empty($return_mail)) { $check = false; $_MAIN_MESSAGE .= "<br>" . ___("Die E-Mail-Adresse für Fehlermeldungen darf nicht leer sein") . "."; } $check_mail = checkEmailAdr($return_mail, $EMailcheck_Intern); if (!$check_mail[0]) { $check = false; $_MAIN_MESSAGE .= "<br>" . ___("Die E-Mail-Adresse für Fehlermeldungen ist nicht gültig.") . " " . $check_mail[1]; } } if ($check) { if (!DEMO) { $HOSTS = new tm_HOST(); $HOSTS->addHost(array("siteid" => TM_SITEID, "name" => $name, "aktiv" => $aktiv, "host" => $host, "port" => $port, "options" => $options, "smtp_auth" => $smtp_auth, "smtp_domain" => $smtp_domain, "smtp_ssl" => $smtp_ssl, "smtp_max_piped_rcpt" => $smtp_max_piped_rcpt, "type" => $type, "user" => $user, "pass" => $pass, "max_mails_atonce" => $max_mails_atonce, "max_mails_bcc" => $max_mails_bcc, "sender_name" => $sender_name, "sender_email" => $sender_email, "return_mail" => $return_mail, "reply_to" => $reply_to, "delay" => $delay)); } //demo $_MAIN_MESSAGE .= "<br>" . sprintf(___("Neuer Mailserver %s wurde angelegt."), "'<b>" . display($name) . "</b>'"); $action = "host_list"; require_once TM_INCLUDEPATH . "/host_list.inc.php"; } else { //check require_once TM_INCLUDEPATH . "/host_form.inc.php"; require_once TM_INCLUDEPATH . "/host_form_show.inc.php"; } //check } else { //set==save require_once TM_INCLUDEPATH . "/host_form.inc.php";
#require_once (TM_INCLUDEPATH."/phphtmlparser/html2text.inc"); $called_via_url = FALSE; if (isset($_SERVER['REMOTE_ADDR'])) { $called_via_url = TRUE; } //a http refresh may work $reload_intervall = 300; if ($called_via_url) { echo "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . $encoding . "\">\n"; echo "<html>\n<body bgcolor=\"#ffffff\">\n"; echo "<pre>\n"; } $QUEUE = new tm_Q(); $NEWSLETTER = new tm_NL(); $ADDRESS = new tm_ADR(); $HOSTS = new tm_HOST(); $BLACKLIST = new tm_BLACKLIST(); $T = new Timer(); //zeitmessung $skip_send = FALSE; //if true, skip sending routine// is true after new q has been prepared $log_proc_id = rand(111111, 999999); $log_q_id = "0"; $log_nl_id = "0"; $log_grp_id = "0"; $log_adr_id = "0"; $log_msg = ""; function send_log($text) { #update log on the fly global $tm_logpath;
/* 2006/7 by Volker Augustin, multi.art.studio Hanau */ /* Contact/Kontakt: info@tellmatic.org */ /* Homepage: www.tellmatic.org */ /* leave this header in file! */ /* diesen Header nicht loeschen! */ /* check Homepage for Updates and more Infos */ /* Besuchen Sie die Homepage fuer Updates und weitere Infos */ /********************************************************************************/ exit; #include config file: edit line if you run this script via cronjob, add full path to tellmatic config file require_once "./tm_config.inc.php"; /********************************************************************************/ if (DEMO) { exit; } $HOSTS = new tm_HOST(); $Mailer = new tm_Mail(); $Bounce = new tm_Bounce(); $ADDRESS = new tm_ADR(); #POP3/IMAP HostID frm global config $HOST = $HOSTS->getHost($C[0]['bounceit_host']); if (!isset($HOST[0])) { exit; } $Mail = array(); $BMail = array(); $Bounces = array(); $bcmatch = 0; $offset = 0; $search_mail = array(); if ($C[0]['bounceit_filter_to'] == 1) {
function validate_email($email, $from = "") { $protocol = ""; $HOSTS = new tm_HOST(); $HOST = $HOSTS->getStdSMTPHost(); if (empty($from)) { $from = $HOST[0]['sender_email']; } $Return = array(0 => true, 1 => "OK"); list($userName, $mailDomain) = explode("@", $email, 2); //use explode instead of split, php5.3 $protocol .= "from: " . $from . " \n"; $protocol .= "to: " . $email . " \n"; $mx = getmxrr($mailDomain, $mxhosts); $hc = count($mxhosts); if ($hc > 0) { //wir preuefen nur mal den ersten mx $host = $mxhosts[0]; $protocol .= $host . " \n"; //added @ to suppress possible error messages, thx to tms-schmidt //fixed bug id: 3114571 //https://sourceforge.net/tracker/?func=detail&aid=3114571&group_id=190396&atid=933192 $Connect = @fsockopen($host, 25, $errno, $errstr, 0.5); //timeout 0,5 sec usleep(100000); if ($Connect) { //aol hack /* //schwachsinnig! gibt schleife bis 220... ohoh do { $Out = fgets ( $Connect, 1024 ); } while (ereg("^220",$Out)); */ if (ereg("^220", $Out = fgets($Connect, 1024))) { //aol: if (ereg("^220", $Out)) { usleep(100000); fputs($Connect, "HELO " . $HOST[0]['smtp_domain'] . "\r\n"); $Out = fgets($Connect, 1024); $protocol .= $Out . " \n"; usleep(100000); fputs($Connect, "MAIL FROM: {$from}\r\n"); $From = fgets($Connect, 1024); $protocol .= $From . " \n"; usleep(100000); fputs($Connect, "RCPT TO: {$email}\r\n"); $To = fgets($Connect, 1024); $protocol .= $To . " \n"; usleep(100000); fputs($Connect, "QUIT\r\n"); fclose($Connect); //http://www.faqs.org/rfcs/rfc821.html if (!ereg("^250", $From) || !ereg("^250", $To)) { if (ereg("^4", $From) || ereg("^4", $To)) { $Return[1] = ___("Server lehnt Mail ab, temporaerer Fehler, Greylisting etc."); #."\n".$protocol."\n"; } else { $Return[0] = false; $Return[1] = ___("Server meldet Fehler, Adresse abgelehnt"); #."\n".$protocol."\n"; } } } else { $Return[0] = false; $Return[1] = ___("Keine Antwort vom Server."); #."\n".$protocol."\n"; } } else { $Return[0] = false; $Return[1] = ___("Kann Verbindung zum Server nicht herstellen.") . " (" . $errno . " " . $errstr . ")"; #."\n".$protocol."\n"; } } else { //kein mx host gefunden $hc=0 $Return[0] = false; $Return[1] = ___("Kein MX Eintrag (Validate)"); #."\n".$protocol."\n"; } $Return[1] .= "\n" . $protocol . "\n"; return $Return; }
/********************************************************************************/ /* this file is part of: / diese Datei ist ein Teil von: */ /* tellmatic, the newslettermachine */ /* tellmatic, die Newslettermaschine */ /* 2006/7 by Volker Augustin, multi.art.studio Hanau */ /* Contact/Kontakt: info@tellmatic.org */ /* Homepage: www.tellmatic.org */ /* leave this header in file! */ /* diesen Header nicht loeschen! */ /* check Homepage for Updates and more Infos */ /* Besuchen Sie die Homepage fuer Updates und weitere Infos */ /********************************************************************************/ $_MAIN_DESCR = ___("Mailserver verwalten"); $_MAIN_MESSAGE .= ""; $HOSTS = new tm_HOST(); $h_id = getVar("h_id"); $set = getVar("set"); $val = getVar("val"); $doit = getVar("doit"); //wird per js an url angefuegt!!! confirm() if ($set == "aktiv") { if (!DEMO) { $HOSTS->setAktiv($h_id, $val); } if ($val == 1) { $_MAIN_MESSAGE .= "<br>" . ___("Server wurde aktiviert."); } else { $_MAIN_MESSAGE .= "<br>" . ___("Server wurde de-aktiviert."); } }