From 77985e1ab485d66b18e9e29e81a7e555983c1180 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sat, 18 Apr 2015 18:26:52 +0000 Subject: [PATCH] User registrations are almost a thing --- _sakura/components/Main.php | 102 +++- _sakura/components/Templates.php | 4 +- _sakura/components/Users.php | 218 +++++++- _sakura/components/Whois.php | 210 ++++++++ _sakura/config/config.example.php | 6 +- _sakura/config/whois.json | 609 ++++++++++++++++++++++ _sakura/sakura.php | 1 + _sakura/templates/htmlEmail.tpl | 60 +++ _sakura/templates/yuuno/global/header.tpl | 5 + main/authenticate.php | 14 +- 10 files changed, 1214 insertions(+), 15 deletions(-) create mode 100644 _sakura/components/Whois.php create mode 100644 _sakura/config/whois.json create mode 100644 _sakura/templates/htmlEmail.tpl diff --git a/_sakura/components/Main.php b/_sakura/components/Main.php index 7b087b0..70abfec 100644 --- a/_sakura/components/Main.php +++ b/_sakura/components/Main.php @@ -31,7 +31,10 @@ class Main { Session::init(); // Templating engine - Templates::init(Configuration::getLocalConfig('etc', 'design')); + Templates::init(Configuration::getConfig('site_style')); + + // Assign servers file to whois class + Whois::setServers(Configuration::getLocalConfig('etc', 'whoisservers')); // Markdown Parser self::initMD(); @@ -74,9 +77,9 @@ class Main { public static function ErrorHandler($errno, $errstr, $errfile, $errline) { // Set some variables to work with including A HUGE fallback hackjob for the templates folder - $errstr = str_replace(Configuration::getLocalConfig('etc', 'localPath'), '', $errstr); - $errfile = str_replace(Configuration::getLocalConfig('etc', 'localPath'), '', $errfile); - $templates = (Configuration::getLocalConfig('etc', 'templatesPath') !== null && !empty(Configuration::getLocalConfig('etc', 'templatesPath'))) ? Configuration::getLocalConfig('etc', 'templatesPath') : '/var/www/flashii.net/_sakuya/templates/'; + $errstr = str_replace(ROOT, '', $errstr); + $errfile = str_replace(ROOT, '', $errfile); + $templates = ROOT .'_sakura/templates/'; switch ($errno) { @@ -114,6 +117,80 @@ class Main { } + // Send emails + public static function sendMail($to, $subject, $body) { + + // Initialise PHPMailer + $mail = new \PHPMailer(); + + // Set to SMTP + $mail->IsSMTP(); + + // Set the SMTP server host + $mail->Host = Configuration::getConfig('smtp_server'); + + // Do we require authentication? + $mail->SMTPAuth = Configuration::getConfig('smtp_auth'); + + // Do we encrypt as well? + $mail->SMTPSecure = Configuration::getConfig('smtp_secure'); + + // Set the port to the SMTP server + $mail->Port = Configuration::getConfig('smtp_port'); + + // If authentication is required log in as well + if(Configuration::getConfig('smtp_auth')) { + + $mail->Username = Configuration::getConfig('smtp_username'); + $mail->Password = base64_decode(Configuration::getConfig('smtp_password')); + + } + + // Add a reply-to header + $mail->AddReplyTo(Configuration::getConfig('smtp_replyto_mail'), Configuration::getConfig('smtp_replyto_name')); + + // Set a from address as well + $mail->SetFrom(Configuration::getConfig('smtp_from_email'), Configuration::getConfig('smtp_from_name')); + + // Set the addressee + foreach($to as $email => $name) + $mail->AddBCC($email, $name); + + // Subject line + $mail->Subject = $subject; + + // Set the mail type to HTML + $mail->isHTML(true); + + // Set email contents + $htmlMail = file_get_contents(ROOT .'_sakura/templates/htmlEmail.tpl'); + + // Replace template tags + $htmlMail = str_replace('{{ sitename }}', Configuration::getConfig('sitename'), $htmlMail); + $htmlMail = str_replace('{{ siteurl }}', '//'. Configuration::getLocalConfig('urls', 'main'), $htmlMail); + $htmlMail = str_replace('{{ contents }}', self::mdParse($body), $htmlMail); + + // Set HTML body + $mail->Body = $htmlMail; + + // Set fallback body + $mail->AltBody = $body; + + // Send the message + $send = $mail->Send(); + + // Clear the addressee list + $mail->ClearAddresses(); + + // If we got an error return the error + if(!$send) + return $mail->ErrorInfo; + + // Else just return whatever + return $send; + + } + // Legacy password hashing to be able to validate passwords from users on the old backend. public static function legacyPasswordHash($data) { @@ -313,4 +390,21 @@ class Main { } + // Get country code from CloudFlare header (which just returns EU if not found) + public static function getCountryCode() { + + // Check if remote IP is a CloudFlare IP + if(self::checkCFIP($_SERVER['REMOTE_ADDR'])) { + + // Check if the required header is set and return it + if(isset($_SERVER['HTTP_CF_IPCOUNTRY'])) + return $_SERVER['HTTP_CF_IPCOUNTRY']; + + } + + // Return EU as a fallback + return 'EU'; + + } + } diff --git a/_sakura/components/Templates.php b/_sakura/components/Templates.php index 54dfcff..874e8d9 100644 --- a/_sakura/components/Templates.php +++ b/_sakura/components/Templates.php @@ -19,7 +19,7 @@ class Templates { self::$_TPL = $template; // Assign config path to a variable so we don't have to type it out twice - $confPath = Configuration::getLocalConfig('etc', 'templatesPath') .'/'. self::$_TPL .'/template.cfg'; + $confPath = ROOT .'_sakura/templates/'. self::$_TPL .'/template.cfg'; // Check if the configuration file exists if(!file_exists($confPath)) @@ -41,7 +41,7 @@ class Templates { private static function twigLoader() { // Initialise Twig Filesystem Loader - $twigLoader = new \Twig_Loader_Filesystem(Configuration::getLocalConfig('etc', 'templatesPath') .'/'. Configuration::getLocalConfig('etc', 'design')); + $twigLoader = new \Twig_Loader_Filesystem(ROOT .'_sakura/templates/'. self::$_TPL); // And now actually initialise the templating engine self::$_ENG = new \Twig_Environment($twigLoader, array( diff --git a/_sakura/components/Users.php b/_sakura/components/Users.php index d6df503..c9b1a66 100644 --- a/_sakura/components/Users.php +++ b/_sakura/components/Users.php @@ -14,7 +14,7 @@ class Users { 'username_clean' => 'deleted user', 'password_hash' => '', 'password_salt' => '', - 'password_algo' => 'sha256', + 'password_algo' => 'nologin', 'password_iter' => 1000, 'password_chan' => 0, 'password_new' => '', @@ -38,7 +38,7 @@ class Users { // Empty rank template public static $emptyRank = [ 'id' => 0, - 'rankname' => 'Non-existent Rank', + 'rankname' => 'Non-existent Rank', 'multi' => 0, 'colour' => '#444', 'description' => 'A hardcoded dummy rank for fallback.' @@ -85,7 +85,11 @@ class Users { $userData = self::getUser($uid); // Validate password - if($userData['password_algo'] == 'legacy') { // Shitty legacy method of sha512(strrev(sha512())) + if($userData['password_algo'] == 'nologin') { // Disable logging in to an account + + return [0, 'NO_LOGIN']; + + } elseif($userData['password_algo'] == 'legacy') { // Shitty legacy method of sha512(strrev(sha512())) if(Main::legacyPasswordHash($password) != $userData['password_hash']) return [0, 'INCORRECT_PASSWORD']; @@ -138,6 +142,214 @@ class Users { } + // Register user + public static function register($username, $password, $confirmpass, $email, $tos, $captcha = null, $regkey = null) { + + // Check if registration is even enabled + if(Configuration::getConfig('disable_registration')) + return [0, 'DISABLED']; + + // Check if registration codes are required + if(Configuration::getConfig('require_registration_code')) { + + // Check if the code is valid + if(!self::checkRegistrationCode($regkey)) + return [0, 'INVALID_REG_KEY']; + + } + + // Check if the user agreed to the ToS + if(!$tos) + return [0, 'TOS']; + + // Verify the captcha if it's enabled + if(Configuration::getConfig('recaptcha')) { + + if(!Main::verifyCaptcha($captcha)['success']) + return [0, 'CAPTCHA_FAIL']; + + } + + // Check if the username already exists + if(self::userExists($username, false)) + return [0, 'USER_EXISTS']; + + // Username too short + if(strlen($username) < 3) + return [0, 'NAME_TOO_SHORT']; + + // Username too long + if(strlen($username) > 16) + return [0, 'NAME_TOO_LONG']; + + // Password too short + if(strlen($password) < 8) + return [0, 'PASS_TOO_SHORT']; + + // Password too long + if(strlen($password) > 256) + return [0, 'PASS_TOO_LONG']; + + // Passwords do not match + if($password != $confirmpassword) + return [0, 'PASS_NOT_MATCH']; + + // Check if the given email address is formatted properly + if(!filter_var($email, FILTER_VALIDATE_EMAIL)) + return [0, 'INVALID_EMAIL']; + + // Check the MX record of the email + if(!Main::checkMXRecord($email)) + return [0, 'INVALID_MX']; + + // Set a few variables + $usernameClean = Main::cleanString($username); + $password = Hashing::create_hash($password); + $requireActive = Configuration::getConfig('require_activation'); + $userRank = $requireActive ? [0] : [1]; + $userRankJson = json_encode($userRank); + + // Insert the user into the database + Database::insert('users', [ + 'username' => $username, + 'username_clean' => $usernameClean, + 'password_hash' => $password[3], + 'password_salt' => $password[2], + 'password_algo' => $password[0], + 'password_iter' => $password[1], + 'email' => $email, + 'rank_main' => $userRank[0], + 'ranks' => $userRankJson, + 'register_ip' => Main::getRemoteIP(), + 'last_ip' => Main::getRemoteIP(), + 'regdate' => time(), + 'lastdate' => 0, + 'lastunamechange' => time(), + 'country' => Main::getCountryCode(), + 'profile_data' => '[]' + ]); + + // Get userid of the new user + $uid = Database::fetch('users', false, ['username_clean' => [$usernameClean, '=']])['id']; + + // Check if we require e-mail activation + if($requireActive) { + + // Send activation e-mail to user + self::sendActivationMail($uid); + + } + + // Check if registration codes are required + if(Configuration::getConfig('require_registration_code')) { + + // If we do mark the registration code that was used as used + self::markRegistrationCodeUsed($regkey, $uid); + + } + + // Return true with a specific message if needed + return [1, ($requireActive ? 'EMAILSENT' : 'SUCCESS')]; + + } + + // Send the activation e-mail and do other required stuff + public static function sendActivationMail($uid) { + + // Get the user data + $user = Database::fetch('users', false, ['id' => [$uid, '=']]); + + // User is already activated or doesn't even exist + if(!count($user) > 1 || $user['rank_main']) + return false; + + // Generate activation key + // $activate = ; + $activate = 'null'; + + // Build the e-mail + $message = "Welcome to ". Configuration::getConfig('sitename') ."!\r\n\r\n"; + $message .= "Please keep this e-mail for your records. Your account intormation is as follows:\r\n\r\n"; + $message .= "----------------------------\r\n\r\n"; + $message .= "Username: ". $user['username'] ."\r\n"; + $message .= "Your profile: http://". Configuration::getLocalConfig('urls', 'main') ."/u/". $user['id'] ."\r\n\r\n"; + $message .= "----------------------------\r\n\r\n"; + $message .= "Please visit the following link in order to activate your account:\r\n\r\n"; + $message .= "http://". Configuration::getLocalConfig('urls', 'main') ."/activate?mode=activate&u=". $user['id'] ."&k=". $activate ."\r\n\r\n"; + $message .= "Your password has been securely stored in our database and cannot be retrieved. "; + $message .= "In the event that it is forgotten, you will be able to reset it using the email address associated with your account.\r\n\r\n"; + $message .= "Thank you for registering.\r\n\r\n"; + $message .= "--\r\n\r\nSincerely\r\n\r\n". Configuration::getConfig('mail_signature'); + + // Send the message + Main::sendMail([$user['email'] => $user['username']], Configuration::getConfig('sitename') .' Activation Mail', $message); + + // Return true indicating that the things have been sent + return true; + + } + + // Check if registration code is valid + public static function checkRegistrationCode($code) { + + // Get registration key + $keyRow = Database::fetch('regcodes', true, ['code' => [$code, '='], 'key_used' => [0, '=']]); + + // Check if it exists and return it + return count($keyRow) ? $keyRow[0]['id'] : false; + + } + + // Mark registration code as used + public static function markRegistrationCodeUsed($code, $uid = 0) { + + // Check if the code exists + if(!$id = self::checkRegistrationCode($code)) + return false; + + // Mark it as used + Database::update('regcodes', [ + [ + 'used_by' => $uid, + 'key_used' => 1 + ], + [ + 'id' => [$id, '='] + ] + ]); + + // Return true because yeah + return true; + + } + + // Create new registration code + public static function createRegistrationCode() { + + // Check if we're logged in + if(!self::checkLogin()) + return false; + + // Check if the user is not exceeding the maximum registration key amount + if(count(Database::fetch('regcodes', true, ['uid' => [Session::$userId, '=']])) >= Configuration::getConfig('max_reg_keys')) + return false; + + // Generate a code by MD5'ing some random bullshit + $code = md5('SAKURA'. rand(0, 99999999) . Session::$userId .'NOOKLSISGOD'); + + // Insert the key into the database + Database::insert('regcodes', [ + 'code' => $code, + 'created_by' => Session::$userId, + 'used_by' => 0, + 'key_used' => 0 + ]); + + // Return the code + return $code; + + } + // Check if a user exists public static function userExists($user, $id = true) { diff --git a/_sakura/components/Whois.php b/_sakura/components/Whois.php new file mode 100644 index 0000000..57fc480 --- /dev/null +++ b/_sakura/components/Whois.php @@ -0,0 +1,210 @@ + + * Released under the MIT-License + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Flashwave + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace Sakura; + +class Whois { + + // Variables + public static $servers; + + // Set the whois servers list + public static function setServers($serversFile) { + + // Check if the file exists and if it does get contents. + if(file_exists($serversFile)) + $servers = file_get_contents($serversFile); + else + trigger_error('Failed to load whois servers file', E_USER_ERROR); + + // Parse json + if(($servers = json_decode($servers, true)) != true) + trigger_error('Error while parsing whois servers file JSON', E_USER_ERROR); + + // Check for neccesary keys + if(!array_key_exists('tld', $servers) || !array_key_exists('ip', $servers)) + trigger_error('One or more of the required whois lists isn\'t set, please check your whois servers file', E_USER_ERROR); + + // If everything is gucci set self::$servers + self::$servers = $servers; + + } + + // Query the whois servers + public static function query($address) { + + // Call validate to use the right whois type + switch(self::validateAddress($address)) { + + case 1: // validateAddress returns 1 for a domain... + return self::lookupDomain($address); + + case 2: // ...and 2 for both IPv4 and IPv6 (should be fine)... + return self::lookupIP($address); + + case 0: // ...and 0 in case the type is invalid in which case... + default: // ...a false is returned by this function + return false; + + } + + } + + // Validates an address + private static function validateAddress($address) { + + // Check if the given address is an IP address + if(filter_var($address, FILTER_VALIDATE_IP)) + return 2; + + // Check if given address is a domain name + if(preg_match("/^([-a-z0-9]{2,100})\.([a-z\.]{2,8})$/i", $address)) + return 1; + + // If unsuccessful return 0 + return 0; + + } + + // Look up a domain + private static function lookupDomain($address) { + + // Get list of servers + $servers = self::$servers['tld']; + + // Break domain up in parts + $addressParts = explode(".", $address); + + // Get TLD + $tld = strtolower(array_pop($addressParts)); + + // Get proper whois server address + if(!$server = $servers[$tld]) + return 'Error: No appropriate whois server found for the TLD '. $tld .', check if the given address is correct.'; + + // Get results from whois server + if(!$result = self::queryWhois($server, $address)) { + + // Return an error if there's no results were retrieved. + return 'Error: No results retrieved from '. $server .' for '. $address .'.'; + + } else { + + // Assign result with heading text to return variable + $return = $address ." domain lookup results from ". $server .":\r\n\r\n". $result; + + // Check if there's a secondary whois server + while(strpos($result, "Whois Server:") !== FALSE) { + + preg_match("/Whois Server: (.*)/", $return, $matches); + + // If there is call it... + if(isset($matches[1])) { + + $result = self::queryWhois(($server = $matches[1]), $address); + + // ...and append the retrieved values to the return variable + $return .= "\r\n-------------\r\n\r\n". $address ." domain lookup results from ". $server .":\r\n". $result; + + } + + } + + } + + // If all is good return the return variable + return $return; + + } + + // Look up an IP + private static function lookupIP($address) { + + // Get list of servers + $servers = self::$servers['ip']; + + // Set variable to keep results in + $results = array(); + + // Query servers + foreach($servers as $server) { + + // Get results + $result = self::queryWhois($server, $address); + + // Assign result to results array if not in it yet + if($result && !in_array($result, $results)) + $results[$server] = $result; + + } + + // Create variable to keep return value + $return = "RESULTS FOUND: ". count($results); + + // Append results + foreach($results as $server => $result) { + + $return .= "\r\n\r\n-------------" + . "\r\nLookup results for " + . $address + . " from " + . $server + . " server:\r\n\r\n" + . $result; + + } + + // Return results + return $return; + + } + + // Query whois server + private static function queryWhois($server, $address, $port = 43, $timeout = 10) { + + // Open socket + $query = @fsockopen($server, $port, $errno, $errstr, $timeout) or trigger_error('Failed to open socket: '. $errno .' - '. $errstr, E_USER_ERROR); + + // Send address + fputs($query, $address ."\r\n"); + + // Await output + $out = null; + while(!feof($query)) + $out .= fgets($query); + + // Close socket + fclose($query); + + // Return results + return $out; + + } + +} diff --git a/_sakura/config/config.example.php b/_sakura/config/config.example.php index de78f8c..8afc384 100644 --- a/_sakura/config/config.example.php +++ b/_sakura/config/config.example.php @@ -21,7 +21,5 @@ $sakuraConf['urls']['chat'] = 'chat.flashii.net'; // Chat url $sakuraConf['urls']['manage'] = 'manage.flashii.net'; // Moderator panel url // Errata -$sakuraConf['etc']['localPath'] = '/var/www/flashii.net/'; // Local path -$sakuraConf['etc']['templatesPath'] = $sakuraConf['etc']['localPath'] .'_sakura/templates/'; // Path to templates directory -$sakuraConf['etc']['design'] = 'yuuno'; // Style name -$sakuraConf['etc']['cfhosts'] = $sakuraConf['etc']['localPath'] .'_sakura/config/cloudflare.hosts'; // Cloudflare IP subnets file +$sakuraConf['etc']['cfhosts'] = ROOT .'_sakura/config/cloudflare.hosts'; // Cloudflare IP subnets file +$sakuraConf['etc']['whoisservers'] = ROOT .'_sakura/config/whois.json'; // JSON with Whois servers diff --git a/_sakura/config/whois.json b/_sakura/config/whois.json new file mode 100644 index 0000000..6c24461 --- /dev/null +++ b/_sakura/config/whois.json @@ -0,0 +1,609 @@ +{ + + "tld": { + + "abogado": "whois.nic.ac", + "ac": "whois.nic.ac", + "academy": "whois.donuts.co", + "accountants": "whois.donuts.co", + "active": "whois.afilias-srs.net", + "actor": "whois.unitedtld.com", + "actor": "whois.unitedtld.com", + "ad": "whois.ripe.net", + "ae": "whois.nic.ae", + "aero": "whois.aero", + "af": "whois.nic.af", + "ag": "whois.nic.ag", + "agency": "whois.donuts.co", + "ai": "whois.ai", + "airforce": "whois.unitedtld.com", + "al": "whois.ripe.net", + "allfinanz": "whois.ksregistry.net", + "alsace": "whois-alsace.nic.fr", + "am": "whois.amnic.net", + "army": "whois.rightside.co", + "arpa": "whois.iana.org", + "as": "whois.nic.as", + "asia": "whois.nic.asia", + "associates": "whois.donuts.co", + "at": "whois.nic.at", + "attorney": "whois.rightside.co", + "au": "whois.audns.net.au", + "auction": "whois.unitedtld.com", + "audio": "whois.uniregistry.net", + "autos": "whois.afilias-srs.net", + "aw": "whois.nic.aw", + "ax": "whois.ax", + "az": "whois.ripe.net", + "band": "whois.rightside.co", + "bar": "whois.nic.bar", + "bargains": "whois.donuts.co", + "bayern": "whois-dub.mm-registry.com", + "be": "whois.dns.be", + "beer": "whois-dub.mm-registry.com", + "berlin": "whois.nic.berlin", + "best": "whois.nic.best", + "bg": "whois.register.bg", + "bi": "whois.nic.bi", + "bike": "whois.donuts.co", + "bio": "whois.ksregistry.net", + "biz": "whois.biz", + "bj": "whois.nic.bj", + "black": "whois.afilias.net", + "blackfriday": "whois.uniregistry.net", + "blue": "whois.afilias.net", + "bmw": "whois.ksregistry.net", + "bn": "whois.bn", + "bnpparibas": "whois.afilias-srs.net", + "bo": "whois.nic.bo", + "boo": "domain-registry-whois.l.google.com", + "boutique": "whois.donuts.co", + "br": "whois.nic.br", + "brussels": "whois.nic.brussels", + "bt": "whois.netnames.net", + "budapest": "whois-dub.mm-registry.com", + "build": "whois.nic.build", + "builders": "whois.donuts.co", + "business": "whois.donuts.co", + "business": "whois.donuts.co", + "bw": "whois.nic.net.bw", + "by": "whois.cctld.by", + "bz": "whois.belizenic.bz", + "bzh": "whois-bzh.nic.fr", + "ca": "whois.cira.ca", + "cab": "whois.donuts.co", + "cal": "domain-registry-whois.l.google.com", + "camera": "whois.donuts.co", + "camp": "whois.donuts.co", + "cancerresearch": "whois.nic.cancerresearch", + "capetown": "capetown-whois.registry.net.za", + "capital": "whois.donuts.co", + "cards": "whois.donuts.co", + "care": "whois.donuts.co", + "career": "whois.nic.career", + "careers": "whois.donuts.co", + "casa": "whois-dub.mm-registry.com", + "cash": "whois.donuts.co", + "cat": "whois.cat", + "catering": "whois.donuts.co", + "cc": "ccwhois.verisign-grs.com", + "cd": "whois.nic.cd", + "center": "whois.donuts.co", + "ceo": "whois.nic.ceo", + "cern": "whois.afilias-srs.net", + "cf": "whois.dot.cf", + "ch": "whois.nic.ch", + "channel": "domain-registry-whois.l.google.com", + "cheap": "whois.donuts.co", + "christmas": "whois.uniregistry.net", + "chrome": "domain-registry-whois.l.google.com", + "church": "whois.donuts.co", + "ci": "whois.nic.ci", + "city": "whois.donuts.co", + "ck": "whois.nic.ck", + "cl": "whois.nic.cl", + "claims": "whois.donuts.co", + "cleaning": "whois.donuts.co", + "click": "whois.uniregistry.net", + "clinic": "whois.donuts.co", + "clothing": "whois.donuts.co", + "club": "whois.nic.club", + "cn": "whois.cnnic.net.cn", + "co": "whois.co", + "codes": "whois.donuts.co", + "coffee": "whois.donuts.co", + "college": "whois.centralnic.com", + "cologne": "whois-fe1.pdt.cologne.tango.knipp.de", + "com": "whois.verisign-grs.com", + "community": "whois.donuts.co", + "company": "whois.donuts.co", + "computer": "whois.donuts.co", + "condos": "whois.donuts.co", + "construction": "whois.donuts.co", + "consulting": "whois.unitedtld.com", + "contractors": "whois.donuts.co", + "cooking": "whois-dub.mm-registry.com", + "cool": "whois.donuts.co", + "coop": "whois.nic.coop", + "country": "whois-dub.mm-registry.com", + "credit": "whois.donuts.co", + "creditcard": "whois.donuts.co", + "cruises": "whois.donuts.co", + "cuisinella": "whois.nic.cuisinella", + "cx": "whois.nic.cx", + "cymru": "whois.nic.cymru", + "cz": "whois.nic.cz", + "dad": "domain-registry-whois.l.google.com", + "dance": "whois.unitedtld.com", + "dating": "whois.donuts.co", + "day": "domain-registry-whois.l.google.com", + "de": "whois.denic.de", + "deals": "whois.donuts.co", + "democrat": "whois.rightside.co", + "degree": "whois.unitedtld.com", + "dental": "whois.donuts.co", + "dentist": "whois.rightside.co", + "desi": "whois.ksregistry.net", + "diamonds": "whois.donuts.co", + "diet": "whois.uniregistry.net", + "digital": "whois.donuts.co", + "direct": "whois.donuts.co", + "directory": "whois.donuts.co", + "discount": "whois.donuts.co", + "dk": "whois.dk-hostmaster.dk", + "dm": "whois.nic.dm", + "domains": "whois.donuts.co", + "durban": "durban-whois.registry.net.za", + "dvag": "whois.ksregistry.net", + "dz": "whois.nic.dz", + "eat": "domain-registry-whois.l.google.com", + "ec": "whois.nic.ec", + "edu": "whois.educause.edu", + "education": "whois.donuts.co", + "ee": "whois.eenet.ee", + "eg": "whois.ripe.net", + "email": "whois.donuts.co", + "engineer": "whois.rightside.co", + "engineering": "whois.donuts.co", + "enterprises": "whois.donuts.co", + "equipment": "whois.donuts.co", + "es": "whois.nic.es", + "esq": "domain-registry-whois.l.google.com", + "estate": "whois.donuts.co", + "eu": "whois.eu", + "eus": "whois.eus.coreregistry.net", + "events": "whois.donuts.co", + "exchange": "whois.donuts.co", + "expert": "whois.donuts.co", + "exposed": "whois.donuts.co", + "fail": "whois.donuts.co", + "farm": "whois.donuts.co", + "feedback": "whois.centralnic.com", + "fi": "whois.ficora.fi", + "finance": "whois.donuts.co", + "financial": "whois.donuts.co", + "fish": "whois.donuts.co", + "fishing": "whois-dub.mm-registry.com", + "fitness": "whois.donuts.co", + "flights": "whois.donuts.co", + "florist": "whois.donuts.co", + "flsmidth": "whois.ksregistry.net", + "fly": "domain-registry-whois.l.google.com", + "fo": "whois.nic.fo", + "foo": "domain-registry-whois.l.google.com", + "forsale": "whois.unitedtld.com", + "foundation": "whois.donuts.co", + "fr": "whois.nic.fr", + "frl": "whois.nic.frl", + "frogans": "whois-frogans.nic.fr", + "fund": "whois.donuts.co", + "furniture": "whois.donuts.co", + "futbol": "whois.unitedtld.com", + "gal": "whois.gal.coreregistry.net", + "gallery": "whois.donuts.co", + "gbiz": "domain-registry-whois.l.google.com", + "gd": "whois.nic.gd", + "gent": "whois.nic.gent", + "gg": "whois.channelisles.net", + "gi": "whois2.afilias-grs.net", + "gift": "whois.uniregistry.net", + "gifts": "whois.donuts.co", + "gives": "whois.rightside.co", + "gl": "whois.nic.gl", + "glass": "whois.donuts.co", + "gle": "domain-registry-whois.l.google.com", + "global": "whois.afilias-srs.net", + "globo": "whois.gtlds.nic.br", + "gmail": "domain-registry-whois.l.google.com", + "gmx": "whois-fe1.gmx.tango.knipp.de", + "google": "domain-registry-whois.l.google.com", + "gop": "whois-cl01.mm-registry.com", + "gov": "whois.nic.gov", + "gq": "whois.dominio.gq", + "gr": "whois.ripe.net", + "gratis": "whois.donuts.co", + "green": "whois.afilias.net", + "gripe": "whois.donuts.co", + "gs": "whois.nic.gs", + "guide": "whois.donuts.co", + "guitars": "whois.uniregistry.net", + "guru": "whois.donuts.co", + "gy": "whois.registry.gy", + "hamburg": "whois.nic.hamburg", + "haus": "whois.unitedtld.com", + "healthcare": "whois.donuts.co", + "help": "whois.uniregistry.net", + "here": "domain-registry-whois.l.google.com", + "hiphop": "whois.uniregistry.net", + "hiv": "whois.afilias-srs.net", + "hk": "whois.hkirc.hk", + "hn": "whois.nic.hn", + "holdings": "whois.donuts.co", + "holiday": "whois.donuts.co", + "homes": "whois.afilias-srs.net", + "horse": "whois-dub.mm-registry.com", + "host": "whois.nic.host", + "hosting": "whois.uniregistry.net", + "house": "whois.donuts.co", + "how": "domain-registry-whois.l.google.com", + "hr": "whois.dns.hr", + "ht": "whois.nic.ht", + "hu": "whois.nic.hu", + "ibm": "whois.nic.ibm", + "id": "whois.pandi.or.id", + "ie": "whois.domainregistry.ie", + "il": "whois.isoc.org.il", + "im": "whois.nic.im", + "immo": "whois.donuts.co", + "immobilien": "whois.unitedtld.com", + "in": "whois.inregistry.net", + "industries": "whois.donuts.co", + "info": "whois.afilias.net", + "ing": "domain-registry-whois.l.google.com", + "ink": "whois.centralnic.com", + "institute": "whois.donuts.co", + "insure": "whois.donuts.co", + "int": "whois.iana.org", + "international": "whois.donuts.co", + "investments": "whois.donuts.co", + "io": "whois.nic.io", + "iq": "whois.cmc.iq", + "ir": "whois.nic.ir", + "is": "whois.isnic.is", + "it": "whois.nic.it", + "je": "whois.channelisles.net", + "jobs": "jobswhois.verisign-grs.com", + "joburg": "joburg-whois.registry.net.za", + "jp": "whois.jprs.jp", + "juegos": "whois.uniregistry.net", + "kaufen": "whois.unitedtld.com", + "ke": "whois.kenic.or.ke", + "kg": "www.domain.kg", + "ki": "whois.nic.ki", + "kim": "whois.afilias.net", + "kitchen": "whois.donuts.co", + "kiwi": "whois.nic.kiwi", + "koeln": "whois-fe1.pdt.koeln.tango.knipp.de", + "kr": "whois.kr", + "krd": "whois.aridnrs.net.au", + "kz": "whois.nic.kz", + "la": "whois.nic.la", + "lacaixa": "whois.nic.lacaixa", + "land": "whois.donuts.co", + "lawyer": "whois.rightside.co", + "lease": "whois.donuts.co", + "lgbt": "whois.afilias.net", + "li": "whois.nic.li", + "life": "whois.donuts.co", + "lighting": "whois.donuts.co", + "limited": "whois.donuts.co", + "limo": "whois.donuts.co", + "link": "whois.uniregistry.net", + "loans": "whois.donuts.co", + "london": "whois-lon.mm-registry.com", + "lotto": "whois.afilias.net", + "lt": "whois.domreg.lt", + "ltda": "whois.afilias-srs.net", + "lu": "whois.dns.lu", + "luxe": "whois-dub.mm-registry.com", + "luxury": "whois.nic.luxury", + "lv": "whois.nic.lv", + "ly": "whois.nic.ly", + "ma": "whois.iam.net.ma", + "maison": "whois.donuts.co", + "management": "whois.donuts.co", + "mango": "whois.mango.coreregistry.net", + "market": "whois.rightside.co", + "marketing": "whois.donuts.co", + "md": "whois.nic.md", + "me": "whois.nic.me", + "media": "whois.donuts.co", + "meet": "whois.afilias.net", + "melbourne": "whois.aridnrs.net.au", + "meme": "domain-registry-whois.l.google.com", + "menu": "whois.nic.menu", + "mg": "whois.nic.mg", + "miami": "whois-dub.mm-registry.com", + "mil": "whois.internic.net", + "mini": "whois.ksregistry.net", + "mk": "whois.marnet.mk", + "ml": "whois.dot.ml", + "mn": "whois.nic.mn", + "mo": "whois.monic.mo", + "mobi": "whois.dotmobiregistry.net", + "moda": "whois.unitedtld.com", + "moe": "whois.nic.moe", + "monash": "whois.nic.monash", + "mortgage": "whois.rightside.co", + "moscow": "whois.nic.moscow", + "motorcycles": "whois.afilias-srs.net", + "mov": "domain-registry-whois.l.google.com", + "mp": "whois.nic.mp", + "ms": "whois.nic.ms", + "mu": "whois.nic.mu", + "museum": "whois.museum", + "mx": "whois.mx", + "my": "whois.mynic.my", + "mz": "whois.nic.mz", + "na": "whois.na-nic.com.na", + "name": "whois.nic.name", + "navy": "whois.rightside.co", + "nc": "whois.nc", + "net": "whois.verisign-grs.net", + "network": "whois.donuts.co", + "new": "domain-registry-whois.l.google.com", + "nexus": "domain-registry-whois.l.google.com", + "nf": "whois.nic.nf", + "ng": "whois.nic.net.ng", + "ngo": "whois.publicinterestregistry.net", + "ninja": "whois.unitedtld.com", + "nl": "whois.domain-registry.nl", + "no": "whois.norid.no", + "nra": "whois.afilias-srs.net", + "nrw": "whois.nic.nrw", + "nu": "whois.nic.nu", + "nz": "whois.srs.net.nz", + "om": "whois.registry.om", + "ong": "whois.publicinterestregistry.net", + "onl": "whois.afilias-srs.net", + "ooo": "whois.nic.ooo", + "org": "whois.pir.org", + "organic": "whois.afilias.net", + "ovh": "whois-ovh.nic.fr", + "paris": "whois-paris.nic.fr", + "partners": "whois.donuts.co", + "parts": "whois.donuts.co", + "pe": "kero.yachay.pe", + "pf": "whois.registry.pf", + "photo": "whois.uniregistry.net", + "photography": "whois.donuts.co", + "photos": "whois.donuts.co", + "physio": "whois.nic.physio", + "pics": "whois.uniregistry.net", + "pictures": "whois.donuts.co", + "pink": "whois.afilias.net", + "pizza": "whois.donuts.co", + "pl": "whois.dns.pl", + "place": "whois.donuts.co", + "plumbing": "whois.donuts.co", + "pm": "whois.nic.pm", + "pohl": "whois.ksregistry.net", + "poker": "whois.afilias.net", + "post": "whois.dotpostregistry.net", + "pr": "whois.nic.pr", + "press": "whois.nic.press", + "pro": "whois.dotproregistry.net", + "prod": "domain-registry-whois.l.google.com", + "productions": "whois.donuts.co", + "prof": "domain-registry-whois.l.google.com", + "properties": "whois.donuts.co", + "property": "whois.uniregistry.net", + "pt": "whois.dns.pt", + "pub": "whois.unitedtld.com", + "pw": "whois.nic.pw", + "qa": "whois.registry.qa", + "quebec": "whois.quebec.rs.corenic.net", + "re": "whois.nic.re", + "recipes": "whois.donuts.co", + "red": "whois.afilias.net", + "rehab": "whois.rightside.co", + "reise": "whois.nic.reise", + "reisen": "whois.donuts.co", + "rentals": "whois.donuts.co", + "repair": "whois.donuts.co", + "report": "whois.donuts.co", + "republican": "whois.rightside.co", + "rest": "whois.centralnic.com", + "restaurant": "whois.donuts.co", + "reviews": "whois.unitedtld.com", + "rich": "whois.afilias-srs.net", + "rio": "whois.gtlds.nic.br", + "rip": "whois.rightside.co", + "ro": "whois.rotld.ro", + "rocks": "whois.unitedtld.com", + "rodeo": "whois-dub.mm-registry.com", + "rs": "whois.rnids.rs", + "rsvp": "domain-registry-whois.l.google.com", + "ru": "whois.ripn.net", + "ruhr": "whois.nic.ruhr", + "sa": "whois.nic.net.sa", + "saarland": "whois.ksregistry.net", + "sarl": "whois.donuts.co", + "sb": "whois.nic.net.sb", + "sc": "whois2.afilias-grs.net", + "sca": "whois.nic.scb", + "schmidt": "whois.nic.schmidt", + "schule": "whois.donuts.co", + "scot": "whois.scot.coreregistry.net", + "se": "whois.iis.se", + "services": "whois.donuts.co", + "sexy": "whois.uniregistry.net", + "sg": "whois.nic.net.sg", + "sh": "whois.nic.sh", + "shiksha": "whois.afilias.net", + "shoes": "whois.donuts.co", + "si": "whois.arnes.si", + "singles": "whois.donuts.co", + "sk": "whois.sk-nic.sk", + "sm": "whois.nic.sm", + "sn": "whois.nic.sn", + "so": "whois.nic.so", + "social": "whois.unitedtld.com", + "software": "whois.rightside.co", + "solar": "whois.donuts.co", + "solutions": "whois.donuts.co", + "soy": "domain-registry-whois.l.google.com", + "space": "whois.nic.space", + "spiegel": "whois.ksregistry.net", + "st": "whois.nic.st", + "su": "whois.tcinet.ru", + "supplies": "whois.donuts.co", + "supply": "whois.donuts.co", + "support": "whois.donuts.co", + "surf": "whois-dub.mm-registry.com", + "surgery": "whois.donuts.co", + "sx": "whois.sx", + "sy": "whois.tld.sy", + "systems": "whois.donuts.co", + "tatar": "whois.nic.tatar", + "tattoo": "whois.uniregistry.net", + "tax": "whois.donuts.co", + "tc": "whois.meridiantld.net", + "technology": "whois.donuts.co", + "tel": "whois.nic.tel", + "tf": "whois.nic.tf", + "th": "whois.thnic.co.th", + "tienda": "whois.donuts.co", + "tips": "whois.donuts.co", + "tirol": "whois.nic.tirol", + "tj": "whois.nic.tj", + "tk": "whois.dot.tk", + "tl": "whois.nic.tl", + "tm": "whois.nic.tm", + "tn": "whois.ati.tn", + "to": "whois.tonic.to", + "today": "whois.donuts.co", + "tools": "whois.donuts.co", + "top": "whois.nic.top", + "town": "whois.donuts.co", + "toys": "whois.donuts.co", + "tp": "whois.nic.tl", + "tr": "whois.nic.tr", + "training": "whois.donuts.co", + "travel": "whois.nic.travel", + "tui": "whois.ksregistry.net", + "tv": "tvwhois.verisign-grs.com", + "tw": "whois.twnic.net.tw", + "tz": "whois.tznic.or.tz", + "ua": "whois.ua", + "ug": "whois.co.ug", + "uk": "whois.nic.uk", + "university": "whois.donuts.co", + "uol": "whois.gtlds.nic.br", + "us": "whois.nic.us", + "uy": "whois.nic.org.uy", + "uz": "whois.cctld.uz", + "vacations": "whois.donuts.co", + "vc": "whois2.afilias-grs.net", + "ve": "whois.nic.ve", + "vegas": "whois.afilias-srs.net", + "ventures": "whois.donuts.co", + "vermögensberater": "whois.ksregistry.net", + "vermögensberatung": "whois.ksregistry.net", + "versicherung": "whois.nic.versicherung", + "vet": "whois.rightside.co", + "vg": "ccwhois.ksregistry.net", + "viajes": "whois.donuts.co", + "villas": "whois.donuts.co", + "vision": "whois.donuts.co", + "vlaanderen": "whois.nic.vlaanderen", + "vodka": "whois-dub.mm-registry.com", + "vote": "whois.afilias.net", + "voting": "whois.voting.tld-box.at", + "voto": "whois.afilias.net", + "voyage": "whois.donuts.co", + "vu": "vunic.vu", + "wf": "whois.nic.wf", + "wales": "whois.nic.wales", + "wang": "whois.gtld.knet.cn", + "watch": "whois.donuts.co", + "website": "whois.nic.website", + "wed": "whois.nic.wed", + "wedding": "whois-dub.mm-registry.com", + "wf": "whois.nic.wf", + "wien": "whois.nic.wien", + "wiki": "whois.nic.wiki", + "wme": "whois.centralnic.com", + "work": "whois-dub.mm-registry.com", + "works": "whois.donuts.co", + "world": "whois.donuts.co", + "ws": "whois.website.ws", + "wtc": "whois.nic.wtc", + "wtf": "whois.donuts.co", + "xxx": "whois.nic.xxx", + "xyz": "whois.nic.xyz", + "yachts": "whois.afilias-srs.net", + "yoga": "whois-dub.mm-registry.com", + "youtube": "domain-registry-whois.l.google.com", + "yt": "whois.nic.yt", + "zip": "domain-registry-whois.l.google.com", + "zm": "whois.nic.zm", + "zone": "whois.donuts.co", + "дети": "whois.nic.xn--d1acj3b", + "москва": "whois.nic.xn--80adxhks", + "онлайн": "whois.online.rs.corenic.net", + "орг": "whois.publicinterestregistry.net", + "рус": "whois.nic.xn--p1acf", + "рф": "whois.tcinet.ru", + "сайт": "whois.site.rs.corenic.net", + "укр": "whois.dotukr.com", + "қаз": "whois.nic.kz", + "الجزائر": "whois.nic.dz", + "السعودية": "whois.nic.net.sa", + "امارات": "whois.aeda.net.ae", + "ایران": "whois.nic.ir", + "بازار": "whois.bazaar.coreregistry.net", + "سورية": "whois.tld.sy", + "شبكة": "whois.nic.xn--ngbc5azd", + "عمان": "whois.registry.om", + "قطر": "whois.registry.qa", + "مليسيا": "whois.mynic.my", + "موقع": "whois.afilias-srs.net", + "சிங்கப்பூர்": "whois.sgnic.sg", + "ไทย": "whois.thnic.co.th", + "みんな": "domain-registry-whois.l.google.com", + "中信": "whois.gtld.knet.cn", + "中国": "cwhois.cnnic.cn", + "中國": "cwhois.cnnic.cn", + "中文网": "whois.afilias-srs.net", + "企业": "whois.donuts.co", + "佛山": "whois.ngtld.cn", + "公司": "whois.ngtld.cn", + "公益": "whois.conac.cn", + "台湾": "whois.twnic.net.tw", + "台灣": "whois.twnic.net.tw", + "商城": "whois.gtld.knet.cn", + "在线": "whois.afilias-srs.net", + "广东": "whois.ngtld.cn", + "我爱你": "whois.gtld.knet.cn", + "手机": "whois.afilias-srs.net", + "政务": "whois.conac.cn", + "新加坡": "whois.sgnic.sg", + "新加坡": "whois.sgnic.sg", + "游戏": "whois.donuts.co", + "移动": "whois.afilias.net", + "组织机构": "whois.publicinterestregistry.net", + "网络": "whois.ngtld.cn", + "集团": "whois.gtld.knet.cn", + "香港": "whois.hkirc.hk" + + }, + + "ip": [ + "whois.lacnic.net", + "whois.apnic.net", + "whois.arin.net", + "whois.ripe.net" + ] + +} diff --git a/_sakura/sakura.php b/_sakura/sakura.php index 993e8ec..503584e 100644 --- a/_sakura/sakura.php +++ b/_sakura/sakura.php @@ -32,6 +32,7 @@ require_once ROOT .'_sakura/components/Configuration.php'; require_once ROOT .'_sakura/components/Templates.php'; require_once ROOT .'_sakura/components/Sessions.php'; require_once ROOT .'_sakura/components/Users.php'; +require_once ROOT .'_sakura/components/Whois.php'; // Generate path to database driver $_DBNGNPATH = ROOT .'_sakura/components/database/'. $sakuraConf['db']['driver'] .'.php'; diff --git a/_sakura/templates/htmlEmail.tpl b/_sakura/templates/htmlEmail.tpl new file mode 100644 index 0000000..134d0fe --- /dev/null +++ b/_sakura/templates/htmlEmail.tpl @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + +
+ {{ sitename }} +
+ {{ contents }} +
+ This message has been sent to the email address associated with your {{ sitename }} account. +
+ + diff --git a/_sakura/templates/yuuno/global/header.tpl b/_sakura/templates/yuuno/global/header.tpl index 86105aa..d60d04d 100644 --- a/_sakura/templates/yuuno/global/header.tpl +++ b/_sakura/templates/yuuno/global/header.tpl @@ -52,6 +52,11 @@ Home News + Chat + {% if user.checklogin %} + Members + Donate + {% endif %}