"._SETTINGS."
"._MAINSETTINGS." | "._SUBMISSIONSETTINGS." | "._SITESETTINGS." | "._DISPLAYSETTINGS." | "._REVIEWSETTINGS." | "._USERSETTINGS." | "._EMAILSETTINGS." | "._CENSOR."
"._WELCOME." | "._COPYRIGHT." | "._PRINTERCOPYRIGHT." | "._TINYMCE." | "._NOTHANKYOU." | "._THANKYOU."
"; $settingsquery = dbquery("SELECT * FROM ".TABLEPREFIX."fanfiction_panels WHERE panel_type = 'AS' ORDER BY panel_title"); while($os = dbassoc($settingsquery)) { if($os['panel_url']) $othersettings[] = "".$os['panel_title'].""; } if(isset($othersettings)) $output .= implode(" | ", $othersettings); $output .= "
"; } $sects = array("main", "submissions", "sitesettings", "display", "reviews", "useropts", "email"); //if(!isset($_GET['sect'])) $sect = "main"; //else $sect = $_GET['sect']; $sect = isset($_GET['sect']) ? $_GET['sect'] : "main"; if(isset($_POST['testsmtp']) && $sect == "email") { // SMTP connection test. Runs only on POST (the Test button), never via a GET // parameter. It verifies the SAVED settings loaded from fanfiction_settings // (via header.php) -- NOT the unsaved form values -- by opening a real SMTP // connection and reporting each step. It never sends an email and never writes // to the database, so it must not touch $result or advance $sects. $output .= "

"._TESTSMTP_HEADER."

"; if(empty($smtp_host)) { $output .= write_error(_TESTSMTP_NOHOST); } else { // Effective values MUST mirror the real sending behaviour of sendemail(): // PHPMailer's default port is 25, and 'ssl' uses an ssl:// transport prefix. $port = !empty($smtp_port) ? (int) $smtp_port : 25; $secure = !empty($smtp_secure) ? $smtp_secure : ''; $host = ($secure === 'ssl') ? 'ssl://'.$smtp_host : $smtp_host; $output .= write_message(sprintf(_TESTSMTP_PORTNOTE, htmlspecialchars((string) $port), htmlspecialchars($secure !== '' ? $secure : '(none)'))); // If encryption is requested but no port is saved, warn about the usual port // -- but still run the test on the effective values, since that is what real // sending will do. if(empty($smtp_port) && $secure === 'ssl') $output .= write_message(_TESTSMTP_SSLPORTWARN); if(empty($smtp_port) && $secure === 'tls') $output .= write_message(_TESTSMTP_TLSPORTWARN); // Load the SMTP class the same way emailer.php loads PHPMailer, via the // autoloader -- NOT by requiring class.smtp.php directly. After the planned // PHPMailer 6.x upgrade the autoload file becomes a shim and this must keep // working (that upgrade must alias the SMTP class name; see issue #2). require_once(_BASEDIR."includes/PHPMailerAutoload.php"); $steps = ""; ob_start(); $smtp = new SMTP; $smtp->do_debug = 2; try { if(!$smtp->connect($host, $port, 10)) { $steps .= write_error(sprintf(_TESTSMTP_CONNECTFAIL, htmlspecialchars($host), htmlspecialchars((string) $port))); } else { $steps .= write_message(sprintf(_TESTSMTP_CONNECTOK, htmlspecialchars($host), htmlspecialchars((string) $port))); if(!$smtp->hello(gethostname())) { $err = $smtp->getError(); $steps .= write_error(sprintf(_TESTSMTP_HELOFAIL, htmlspecialchars(!empty($err['error']) ? $err['error'] : ''))); } else { $steps .= write_message(_TESTSMTP_HELOOK); $ext = $smtp->getServerExtList(); $hasStartTls = is_array($ext) && array_key_exists('STARTTLS', $ext); if($hasStartTls) { $steps .= write_message(_TESTSMTP_STARTTLSOK); if($secure === 'tls') { if(!$smtp->startTLS()) { $err = $smtp->getError(); $steps .= write_error(sprintf(_TESTSMTP_STARTTLSFAIL, htmlspecialchars(!empty($err['error']) ? $err['error'] : ''))); } else { // Re-issue EHLO over the now-encrypted channel and refresh caps. $smtp->hello(gethostname()); $ext = $smtp->getServerExtList(); } } } else if($secure === 'tls') { $steps .= write_error(_TESTSMTP_STARTTLSMISSING); } $hasAuth = is_array($ext) && array_key_exists('AUTH', $ext); if($hasAuth) { if(!empty($smtp_username)) { if(!$smtp->authenticate($smtp_username, $smtp_password)) { // NOTE: never include the password in this message. $err = $smtp->getError(); $steps .= write_error(sprintf(_TESTSMTP_AUTHFAIL, htmlspecialchars(!empty($err['error']) ? $err['error'] : ''))); } else { $steps .= write_message(_TESTSMTP_AUTHOK); } } else { $steps .= write_message(_TESTSMTP_AUTHSKIP); } } else { $steps .= write_message(_TESTSMTP_NOAUTH); } } } } catch (Exception $e) { $steps .= write_error(htmlspecialchars($e->getMessage())); } // Always close the connection, even if we stopped early above. $smtp->quit(true); $debug = ob_get_clean(); // SECURITY: the debug transcript at level 2 echoes client commands, which // during AUTH include the base64-encoded credentials. Redact every form of // the password before it is ever shown so it is never printed anywhere. if(!empty($smtp_password)) { $secrets = array( $smtp_password, base64_encode($smtp_password), base64_encode("\0".$smtp_username."\0".$smtp_password), // AUTH PLAIN ); $debug = str_replace($secrets, "***REDACTED***", $debug); } $output .= $steps; // Server banners are untrusted input -> escape the whole transcript (XSS). $output .= "

"._TESTSMTP_TRANSCRIPT."

".htmlspecialchars($debug)."
"; } } else if(isset($_POST['submit'])) { if($sect == "main") { if(!preg_match("!^[a-z0-9_]{3,30}$!i", $_POST['newsitekey'])) $output .= write_error(_BADSITEKEY); else { $oldsitekey = $sitekey; $sitekey = descript($_POST['newsitekey']); $sitename = escapestring(descript(strip_tags($_POST['newsitename']))); $slogan = escapestring(descript(strip_tags($_POST['newslogan']))); $url = escapestring(descript(strip_tags($_POST['newsiteurl']))); // if the https:// is missing add it. if(substr($url, 0, 8) != "https://" && substr($url, 0, 7) != "http://") $url = "https://".$url; // we also want to check for a trailing slash. if(substr($url, -1, 1) == "/") $url = substr($url, 0, strlen($url) - 1); $tableprefix = escapestring(descript(strip_tags($_POST['newtableprefix']))); $siteemail = escapestring(descript(strip_tags($_POST['newsiteemail']))); $skin = escapestring(descript(strip_tags($_POST['newskin']))); $language = escapestring(descript(strip_tags($_POST['newlanguage']))); if(empty($sitekey)) $output .= write_message(_SITEKEYREQUIRED); else { if($sitekey != $oldsitekey) $output .= write_message(_SITEKEYCHANGED); $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET sitekey = '$sitekey', sitename = '$sitename', slogan = '$slogan', url = '$url', tableprefix = '$tableprefix', siteemail = '$siteemail', skin = '$skin', language = '$language' WHERE sitekey = '$oldsitekey'"); } } } else if($sect == "submissions") { $submissionsoff = $_POST['newsubmissionsoff'] == 1 ? 1 : 0; $autovalidate = $_POST['newautovalidate'] == 1 ? 1 : 0; $coauthallowed = $_POST['newcoauthallowed'] == 1 ? 1 : 0; $store = !empty($_POST['newstore']) ? ($_POST['newstore'] == "files" ? "files" : "mysql" ) : $store; $storiespath = descript($_POST['newstoriespath']); $minwords = isNumber($_POST['newminwords']) ? $_POST['newminwords'] : 0; $maxwords = isNumber($_POST['newmaxwords']) ? $_POST['newmaxwords'] : 0; $roundrobins = $_POST['newroundrobins'] == 1 ? 1 : 0; $allowseries = $_POST['newallowseries'] && isNumber($_POST['newallowseries']) ? $_POST['newallowseries'] : 0; $imageupload = $_POST['newimageupload'] == 1 ? 1 : 0; $imageheight = isNumber($_POST['newimageheight']) ? $_POST['newimageheight'] : 0; $imagewidth = isNumber($_POST['newimagewidth']) ? $_POST['newimagewidth'] : 0; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET submissionsoff = '$submissionsoff', autovalidate = '$autovalidate', coauthallowed = '$coauthallowed', store = '$store', storiespath = '$storiespath', minwords = '$minwords', maxwords = '$maxwords', imageupload = '$imageupload', imageheight = '$imageheight', imagewidth = '$imagewidth', roundrobins = '$roundrobins', allowseries = '$allowseries' WHERE sitekey ='".SITEKEY."'"); if($action == "settings") { dbquery("UPDATE ".TABLEPREFIX."fanfiction_panels SET panel_hidden = '".($imageupload ? "0" : "1")."' WHERE panel_name LIKE 'manageimages'"); dbquery("UPDATE ".TABLEPREFIX."fanfiction_panels SET panel_hidden = '".($allowseries ? "0" : "1")."' WHERE (panel_name LIKE '%series%' OR panel_title LIKE '%series%') AND panel_type != 'A' AND panel_type != 'B'"); updatePanelOrder( ); } } else if($sect == "sitesettings") { $tinyMCE = ($_POST['newtinyMCE'] == 1 OR $_POST['newtinyMCE'] == 2 OR $_POST['newtinyMCE'] == 3 OR $_POST['newtinyMCE'] == 4 OR $_POST['newtinyMCE'] == 5) ? $_POST['newtinyMCE'] : 0; $allowed_tags = $_POST['newallowed_tags']; $favorites = $_POST['newfavorites'] == 1 ? 1 : 0; $multiplecats = $_POST['newmultiplecats'] == 1 ? 1 : 0; $setreg = $_POST['newsetreg'] == 1 ? 1 : 0; $newscomments = $_POST['newnewscomments'] == 1 ? 1 : 0; $logging = $_POST['newlogging'] == 1 ? 1 : 0; $maintenance = $_POST['newmaint'] == 1 ? 1 : 0; $debug = $_POST['newdebug'] == 1 ? 1 : 0; $captcha = $_POST['newcaptcha'] == 1 ? 1 : 0; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET tinyMCE = '$tinyMCE', favorites = '$favorites', multiplecats = '$multiplecats', setreg = '$setreg', allowed_tags = '$allowed_tags', newscomments = '$newscomments', logging = '$logging', maintenance = '$maintenance', debug = '$debug', captcha = '$captcha' WHERE sitekey ='".SITEKEY."'"); } else if($sect == "display") { $dateformat = $_POST['newdateformat'] ? descript(strip_tags($_POST['newdateformat'])) : descript(strip_tags($_POST['customdateformat'])); $timeformat = $_POST['newtimeformat'] ? descript(strip_tags($_POST['newtimeformat'])) : descript(strip_tags($_POST['customtimeformat'])); $extendcats = $_POST['newextendcats'] == 1 ? 1 : 0; if(isset($_POST['newdisplaycolumns']) && isNumber($_POST['newdisplaycolumns'])) $displaycolumns = $_POST['newdisplaycolumns']; if(isset($_POST['newitemsperpage']) && isNumber($_POST['newitemsperpage'])) $itemsperpage = $_POST['newitemsperpage']; if(isset($_POST['newlinkstyle']) && isNumber($_POST['newlinkstyle'])) $linkstyle = $_POST['newlinkstyle']; if(isset($_POST['newlinkrange']) && isNumber($_POST['newlinkrange'])) $linkrange = $_POST['newlinkrange']; $displayindex = $_POST['newstoryindex'] == 1 ? 1 : 0; $displayprofile = $_POST['newdisplayprofile'] == 1 ? 1 : 0; $defaultsort = $_POST['newdefaultsort'] == 1 ? 1 : 0; if(isNumber($_POST['newrecentdays'])) $recentdays = $_POST['newrecentdays']; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET dateformat = '$dateformat', timeformat = '$timeformat', extendcats = '$extendcats', displaycolumns = '$displaycolumns', itemsperpage = '$itemsperpage', displayindex = '$displayindex', defaultsort = '$defaultsort', recentdays = '$recentdays', displayprofile = '$displayprofile', linkstyle = '$linkstyle', linkrange = '$linkrange' WHERE sitekey ='".SITEKEY."'"); } else if($sect == "reviews") { $reviewsallowed = $_POST['newreviewsallowed'] == 1 ? 1 : 0; $anonreviews = $_POST['newanonreviews'] == 1 ? 1 : 0; $rateonly = $_POST['newrateonly'] == 1 ? 1 : 0; $ratings = isset($_POST['newratings']) && isNumber($_POST['newratings']) ? $_POST['newratings'] : 0; $revdelete = isset($_POST['newrevdelete']) && isNumber($_POST['newrevdelete']) ? $_POST['newrevdelete'] : 0; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET reviewsallowed = '$reviewsallowed', anonreviews = '$anonreviews', rateonly = '$rateonly', ratings = '$ratings', revdelete = '$revdelete' WHERE sitekey ='".SITEKEY."'"); } else if($sect == "useropts") { $alertson = $_POST['newalertson'] == 1 ? 1 : 0; $disablepopups = $_POST['newdisablepops'] == 1 ? 1 : 0; $agestatement = $_POST['newagestatement'] == 1 ? 1 : 0; $pwdsetting = $_POST['newpwdsetting'] == 1 ? 1 : 0; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET alertson = '$alertson', disablepopups = '$disablepopups', agestatement = '$agestatement', pwdsetting = '$pwdsetting' WHERE sitekey ='".SITEKEY."'"); } else if($sect == "email") { $smtp_host = escapestring(descript(strip_tags($_POST['newsmtp_host']))); $smtp_username = escapestring(descript(strip_tags($_POST['newsmtp_username']))); $smtp_password = escapestring(descript(strip_tags($_POST['newsmtp_password']))); $smtp_port = !empty($_POST['newsmtp_port']) ? (int) $_POST['newsmtp_port'] : ''; $smtp_secure = in_array($_POST['newsmtp_secure'], array('', 'tls', 'ssl'), true) ? $_POST['newsmtp_secure'] : ''; $result = dbquery("UPDATE ".$settingsprefix."fanfiction_settings SET smtp_host = '$smtp_host', smtp_username = '$smtp_username', smtp_password = '$smtp_password', smtp_port = '$smtp_port', smtp_secure = '$smtp_secure' WHERE sitekey ='".SITEKEY."'"); } if ($result) { $output .= write_message(_ACTIONSUCCESSFUL); // The section-advance wizard is for the INSTALLER only (install/install.php // includes this file and steps through sections). In admin, "email" is the // last entry in $sects, so advancing would wrap to 0 and jump back to the // first tab while the URL still says sect=email. $action is undefined in the // installer include context, so guard with isset() to avoid a PHP 8 warning. if (!isset($action) || $action != "settings") { $idx = array_search($sect, $sects); if ($idx !== false) { $next_idx = $idx + 1; if ($next_idx >= count($sects)) { $next_idx = 0; } $sect = $sects[$next_idx]; } } } else { $output .= write_error(_ERROR); } } $settingsresults = dbquery("SELECT * FROM ".$settingsprefix."fanfiction_settings WHERE sitekey ='".SITEKEY."'"); $settings = dbassoc($settingsresults); foreach($settings as $var => $val) { if(is_NULL($val)) $val = ''; $$var = stripslashes($val ); } $output .= "
"; if($sect == "main") { $output .= "
"._SITEINFO."
"; } else if($sect == "submissions") { $output .= "
"._SUBMISSIONSETTINGS."
[?]"._HELP_SITEKEY."
[?]"._HELP_SITENAME."
[?]"._HELP_SLOGAN."
[?]"._HELP_URL."
[?]"._HELP_TABLEPREFIX."
[?]"._HELP_SITEEMAIL."
[?]"._HELP_SITESKIN."
[?]"._HELP_LANGUAGE."
"; } else if($sect == "sitesettings") { $output .= "
"._SITESETTINGS."
[?]"._HELP_SUBSOFF."
[?]"._HELP_AUTOVALIDATE."
[?]"._HELP_COAUTHORS."
[?]"._HELP_ROUNDROBINS."
[?]"._HELP_ALLOWSERIES."
[?]"._HELP_IMAGEUPLOAD."
"._IMAGESIZE." [?]"._HELP_IMAGESIZE."
[?]"._HELP_STORE."
[?]"._HELP_STORIESPATH."
"._MAXMINWORDS." [?]"._HELP_MINMAXWORDS."
"; } else if($sect == "display") { $settings = dbquery("SELECT defaultsort, displayindex FROM ".$settingsprefix."fanfiction_settings WHERE sitekey ='".SITEKEY."'"); list($sitedefaultsort, $sitedisplayindex) = dbrow($settings); $defaultdates = array("m/d/y", "m/d/Y", "m/d/Y", "d/m/Y", "d/m/y", "d M Y", "d.m.y", "Y.m.d", "m.d.Y", "d-m-y", "m-d-y", "M d Y", "M d, Y", "F d Y", "F d, Y"); $defaulttimes = array("h:i a", "h:i A", "H:i", "g:i a", "g:i A", "G:i", "h:i:s a", "H:i:s", "g:i:s a", "g:i:s A", "G:i:s"); $output .= "
"._DISPLAYSETTINGS."
[?]"._HELP_TINYMCE." "._TINYMCENOTE."
[?]"._HELP_ALLOWEDTAGS." "._TINYMCENOTE."
[?]"._HELP_FAVORITES."
[?]"._HELP_NUMCATS."
[?]"._HELP_SETREG."
[?]"._HELP_NEWSCOMMENTS."
[?]"._HELP_LOGGING."
[?]"._HELP_MAINTENANCE."
[?]"._HELP_DEBUG."
[?]"._HELP_CAPTCHA."
"; } else if($sect == "reviews") { $output .= "
"._REVIEWSETTINGS."
"._OR." [?]"._HELP_DATEFORMAT."
"._OR." [?]"._HELP_TIMEFORMAT."
[?]"._HELP_EXTENDCATS."
[?]"._HELP_COLUMNS."
[?]"._HELP_ITEMSPERPAGE."
[?]"._HELP_RECENTDAYS."
[?]"._HELP_DEFAULTSORT."
[?]"._HELP_DISPLAYINDEX."
[?]"._HELP_DISPLAYPROFILE."
[?]"._HELP_LINKSTYLE."
[?]"._HELP_LINKRANGE."
"; } else if($sect == "useropts") { $output .= "
"._USERSETTINGS."
[?]"._HELP_REVIEWSON."
[?]"._HELP_ANONREVIEWS."
[?]"._HELP_REVDELETE."
[?]"._HELP_RATINGS."
[?]"._HELP_RATEONLY."
"; } else if($sect == "email") { $output .= "
"._EMAILSETTINGS."
[?]"._HELP_ALERTSON."
[?]"._HELP_POPUPS."
[?]"._HELP_AGECONSENT."
[?]"._HELP_PWD."
"; $output .= write_message(_SMTPOFF); } $output .= "
[?]"._HELP_SMTPHOST."
[?]"._HELP_SMTPUSER."
[?]"._HELP_SMTPPWD."
[?]"._HELP_SMTPPORT."
[?]"._HELP_SMTPSECURE."

"; // The SMTP test button lives OUTSIDE the main settings form (nested forms are // invalid HTML). It is its own POST mini-form -- a submit button, not a GET // link -- so the outbound SMTP connection can't be triggered by a plain link // or a browser prefetch. The existing testsmtp handler posts to the same URL. if($sect == "email") { $output .= "
"._TESTSMTP_HEADER."

[?]"._HELP_TESTSMTP."

"; } ?>