Java tutorial
/* * This file is part of SPFBL. * * SPFBL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SPFBL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SPFBL. If not, see <http://www.gnu.org/licenses/>. */ package net.spfbl.core; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.sun.mail.smtp.SMTPTransport; import com.sun.mail.util.MailConnectException; import it.sauronsoftware.junique.AlreadyLockedException; import it.sauronsoftware.junique.JUnique; import it.sauronsoftware.junique.MessageHandler; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.BindException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.NetworkInterface; import java.net.SocketException; import java.net.URL; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.security.SecureRandom; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Locale; import net.spfbl.whois.QueryTCP; import net.spfbl.spf.QuerySPF; import java.util.Properties; import java.util.StringTokenizer; import java.util.Timer; import java.util.TimerTask; import java.util.TreeMap; import java.util.TreeSet; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.imageio.ImageIO; import javax.mail.Address; import javax.mail.AuthenticationFailedException; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.SendFailedException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import net.spfbl.data.Block; import net.spfbl.dns.QueryDNS; import net.spfbl.http.ServerHTTP; import net.spfbl.spf.SPF; import net.spfbl.whois.Domain; import net.spfbl.whois.Subnet; import net.spfbl.whois.SubnetIPv4; import net.spfbl.whois.SubnetIPv6; import org.apache.commons.codec.binary.Base32; import org.apache.commons.codec.binary.Base64; /** * Classe principal de inicilizao do servio. * * @author Leandro Carlos Rodrigues <leandro@spfbl.net> */ public class Core { private static final byte VERSION = 2; private static final byte SUBVERSION = 7; private static final byte RELEASE = 5; private static final boolean TESTING = false; public static String getAplication() { return "SPFBL-" + getVersion() + (TESTING ? "-TESTING" : ""); } public static String getVersion() { return VERSION + "." + SUBVERSION + "." + RELEASE; } /** * O nvel do LOG. */ public static Level LOG_LEVEL = Level.INFO; public enum Level { ERROR, WARN, INFO, DEBUG, TRACE } public static String sendCommandToPeer(String command, String address, int port) { if (peerUDP == null) { return "DISABLED"; } else { return peerUDP.send(command, address, port); } } public static boolean hasPeerConnection() { if (peerUDP == null) { return false; } else { return peerUDP.hasConnection(); } } public static String getPeerConnection() { if (peerUDP == null) { return null; } else { return peerUDP.getConnection(); } } private static ServerHTTP complainHTTP = null; public static final Huffman HUFFMAN = Huffman.load(); public static final Base64 BASE64 = new Base64(0, new byte[0], true); public static String getReleaseURL(String id) throws ProcessException { if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { Defer defer = Defer.getDefer(id); String url = complainHTTP.getURL(); if (defer == null) { return null; } else if (url == null) { return null; } else { try { long time = System.currentTimeMillis(); String ticket = "release " + id; byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getDNSBLURL(Locale locale, String token) { if (complainHTTP == null) { return null; } else if (token == null) { return null; } else { String url = complainHTTP.getDNSBLURL(locale); if (url == null) { return null; } else { return url + token; } } } public static String getURL(Locale locale, String token) { if (complainHTTP == null) { return null; } else if (token == null) { return null; } else { String url = complainHTTP.getURL(locale); if (url == null) { return null; } else { return url + token; } } } public static String getUnblockURL(Client client, User user, String ip, String sender, String hostname, String recipient) throws ProcessException { // Definio do e-mail do usurio. String userEmail = null; if (user != null) { userEmail = user.getEmail(); } else if (client != null) { userEmail = client.getEmail(); } return getUnblockURL(userEmail, ip, sender, hostname, recipient); } public static String getUnblockURL(String userEmail, String ip, String sender, String hostname, String recipient) throws ProcessException { if (userEmail == null) { return null; } else if (ip == null) { return null; } else if (sender == null) { return null; } else if (!Domain.isValidEmail(sender)) { return null; } else if (recipient == null) { return null; } else if (!Domain.isValidEmail(recipient)) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { try { long time = System.currentTimeMillis(); String ticket = "unblock"; ticket += ' ' + userEmail; ticket += ' ' + ip; ticket += ' ' + sender; ticket += ' ' + recipient; ticket += hostname == null ? "" : ' ' + hostname; byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getUnblockURL(String client, String ip) throws ProcessException { if (client == null) { return null; } else if (!Domain.isValidEmail(client)) { return null; } else if (ip == null) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { long time = System.currentTimeMillis(); String ticket = "unblock"; ticket += ' ' + client; ticket += ' ' + ip; try { byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { Server.logError("compress fail: " + ticket); throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getHoldingURL(User user, long time) throws ProcessException { if (user == null) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { try { String ticket = "holding"; ticket += ' ' + user.getEmail(); byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getUnholdURL(User user, long time) throws ProcessException { if (user == null) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { try { String ticket = "unhold"; ticket += ' ' + user.getEmail(); byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getBlockURL(User user, long time) throws ProcessException { if (user == null) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { try { String ticket = "block"; ticket += ' ' + user.getEmail(); byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getWhiteURL(String white, String client, String ip, String sender, String hostname, String recipient) throws ProcessException { if (white == null) { return null; } else if (client == null) { return null; } else if (ip == null) { return null; } else if (sender == null) { return null; } else if (recipient == null) { return null; } else if (complainHTTP == null) { return null; } else if (Core.hasRecaptchaKeys()) { String url = complainHTTP.getURL(); if (url == null) { return null; } else { try { long time = System.currentTimeMillis(); String ticket = "white"; ticket += ' ' + white; ticket += ' ' + client; ticket += ' ' + ip; ticket += ' ' + sender; ticket += ' ' + recipient; ticket += hostname == null ? "" : ' ' + hostname; byte[] byteArray = Core.HUFFMAN.encodeByteArray(ticket, 8); byteArray[0] = (byte) (time & 0xFF); byteArray[1] = (byte) ((time = time >>> 8) & 0xFF); byteArray[2] = (byte) ((time = time >>> 8) & 0xFF); byteArray[3] = (byte) ((time = time >>> 8) & 0xFF); byteArray[4] = (byte) ((time = time >>> 8) & 0xFF); byteArray[5] = (byte) ((time = time >>> 8) & 0xFF); byteArray[6] = (byte) ((time = time >>> 8) & 0xFF); byteArray[7] = (byte) ((time >>> 8) & 0xFF); return url + Server.encryptURLSafe(byteArray); } catch (Exception ex) { throw new ProcessException("FATAL", ex); } } } else { return null; } } public static String getURL() { if (complainHTTP == null) { return null; } else { return complainHTTP.getURL(); } } public static String dropURL(String domain) { if (complainHTTP == null) { return null; } else { return complainHTTP.drop(domain); } } public static boolean addURL(String domain, String url) { if (complainHTTP == null) { return false; } else { return complainHTTP.put(domain, url); } } public static void loadURL() { if (complainHTTP != null) { complainHTTP.load(); } } public static void storeURL() { if (complainHTTP != null) { complainHTTP.store(); } } public static HashMap<String, String> getMapURL() { if (complainHTTP == null) { return new HashMap<String, String>(); } else { return complainHTTP.getMap(); } } private static AdministrationTCP administrationTCP = null; private static QuerySPF querySPF = null; private static QueryDNS queryDNSBL = null; private static PeerUDP peerUDP = null; public static void interruptTimeout() { // if (administrationTCP != null) { // administrationTCP.interruptTimeout(); // } if (querySPF != null) { querySPF.interruptTimeout(); } } public static boolean loadConfiguration() { File confFile = new File("spfbl.conf"); if (confFile.exists()) { try { Properties properties = new Properties(); FileInputStream confIS = new FileInputStream(confFile); try { properties.load(confIS); Server.setLogFolder(properties.getProperty("log_folder")); Server.setLogExpires(properties.getProperty("log_expires")); Server.setProviderDNS(properties.getProperty("dns_provider")); Core.setHostname(properties.getProperty("hostname")); Core.setInterface(properties.getProperty("interface")); Core.setAdminEmail(properties.getProperty("admin_email")); Core.setAbuseEmail(properties.getProperty("abuse_email")); Core.setIsAuthSMTP(properties.getProperty("smtp_auth")); Core.setStartTLSSMTP(properties.getProperty("smtp_starttls")); Core.setHostSMTP(properties.getProperty("smtp_host")); Core.setPortSMTP(properties.getProperty("smpt_port")); // Version: 2.4 Core.setPortSMTP(properties.getProperty("smtp_port")); Core.setUserSMTP(properties.getProperty("smtp_user")); Core.setPasswordSMTP(properties.getProperty("smtp_password")); Core.setPortAdmin(properties.getProperty("admin_port")); Core.setPortWHOIS(properties.getProperty("whois_port")); Core.setPortSPFBL(properties.getProperty("spfbl_port")); Core.setPortDNSBL(properties.getProperty("dnsbl_port")); Core.setPortHTTP(properties.getProperty("http_port")); Core.setMaxUDP(properties.getProperty("udp_max")); Core.setFloodTimeIP(properties.getProperty("flood_time_ip")); Core.setFloodTimeHELO(properties.getProperty("flood_time_helo")); Core.setFloodTimeSender(properties.getProperty("flood_time_sender")); Core.setFloodMaxRetry(properties.getProperty("flood_max_retry")); Core.setDeferTimeFLOOD(properties.getProperty("defer_time_flood")); Core.setDeferTimeSOFTFAIL(properties.getProperty("defer_time_softfail")); Core.setDeferTimeYELLOW(properties.getProperty("defer_time_gray")); // Obsolete. Core.setDeferTimeYELLOW(properties.getProperty("defer_time_yellow")); Core.setDeferTimeRED(properties.getProperty("defer_time_black")); // Obsolete. Core.setDeferTimeRED(properties.getProperty("defer_time_red")); Core.setDeferTimeHOLD(properties.getProperty("defer_time_hold")); Core.setReverseRequired(properties.getProperty("reverse_required")); Core.setLevelLOG(properties.getProperty("log_level")); Core.setRecaptchaKeySite(properties.getProperty("recaptcha_key_site")); Core.setRecaptchaKeySecret(properties.getProperty("recaptcha_key_secret")); Core.setCacheTimeStore(properties.getProperty("cache_time_store")); Core.setHostnameMySQL(properties.getProperty("mysql_hostname")); Core.setPortMySQL(properties.getProperty("mysql_port")); Core.setSchemaMySQL(properties.getProperty("mysql_schema")); Core.setUserMySQL(properties.getProperty("mysql_user")); Core.setPasswordMySQL(properties.getProperty("mysql_password")); Core.setSSLMySQL(properties.getProperty("mysql_ssl")); PeerUDP.setConnectionLimit(properties.getProperty("peer_limit")); QueryDNS.setConnectionLimit(properties.getProperty("dnsbl_limit")); QuerySPF.setConnectionLimit(properties.getProperty("spfbl_limit")); Analise.setAnaliseExpires(properties.getProperty("analise_expires")); Analise.setAnaliseIP(properties.getProperty("analise_ip")); Analise.setAnaliseMX(properties.getProperty("analise_mx")); return true; } finally { confIS.close(); } } catch (IOException ex) { Server.logError(ex); return false; } } else { return false; } } private static String MYSQL_HOSTNAME = null; private static short MYSQL_PORT = 3306; private static String MYSQL_SCHEMA = "spfbl"; private static String MYSQL_USER = null; private static String MYSQL_PASSWORD = null; private static boolean MYSQL_SSL = false; public static synchronized void setHostnameMySQL(String hostame) { if (hostame != null && hostame.length() > 0) { if (Domain.isHostname(hostame)) { Core.MYSQL_HOSTNAME = Domain.extractHost(hostame, false); } else if (Subnet.isValidIP(hostame)) { Core.MYSQL_HOSTNAME = Subnet.normalizeIP(hostame); } else { Server.logError("invalid MySQL address '" + hostame + "'."); } } } public static void setPortMySQL(String port) { if (port != null && port.length() > 0) { try { setPortMySQL(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid MySQL port '" + port + "'."); } } } public static synchronized void setPortMySQL(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid MySQL port '" + port + "'."); } else { Core.MYSQL_PORT = (short) port; } } public static synchronized void setSchemaMySQL(String schema) { if (schema != null && schema.trim().length() > 0) { Core.MYSQL_SCHEMA = schema.trim(); } } public static synchronized void setUserMySQL(String user) { if (user != null && user.trim().length() > 0) { Core.MYSQL_USER = user.trim(); } } public static synchronized void setPasswordMySQL(String password) { if (password != null && password.trim().length() > 0) { Core.MYSQL_PASSWORD = password.trim(); } } public static void setSSLMySQL(String ssl) { if (ssl != null && ssl.length() > 0) { try { setSSLMySQL(Boolean.parseBoolean(ssl)); } catch (Exception ex) { Server.logError("invalid MySQL SSL '" + ssl + "'."); } } } public static synchronized void setSSLMySQL(boolean ssl) { Core.MYSQL_SSL = ssl; } public static boolean hasMySQL() { if (MYSQL_HOSTNAME == null) { return false; } else if (MYSQL_USER == null) { return false; } else if (MYSQL_PASSWORD == null) { return false; } else { return true; } } private static ConnectionPooler CONNECTION_POOLER = null; private static synchronized ConnectionPooler getConnectionPooler() { if (MYSQL_HOSTNAME == null) { return null; } else if (MYSQL_USER == null) { return null; } else if (MYSQL_PASSWORD == null) { return null; } else if (CONNECTION_POOLER == null) { return CONNECTION_POOLER = new ConnectionPooler(MYSQL_HOSTNAME, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, MYSQL_SCHEMA, MYSQL_SSL); } else { return CONNECTION_POOLER; } } public static synchronized boolean closeConnectionPooler() { if (CONNECTION_POOLER == null) { return false; } else { try { CONNECTION_POOLER.close(); return true; } catch (Exception ex) { Server.logError(ex); return false; } } } public static Connection poolConnectionMySQL() { ConnectionPooler pooler = getConnectionPooler(); if (pooler == null) { return null; } else { try { return pooler.pollConnection(); } catch (Exception ex) { Server.logError(ex); return null; } } } public static boolean offerConnectionMySQL(Connection connection) { if (connection == null) { return false; } else { ConnectionPooler pooler = getConnectionPooler(); if (pooler == null) { return false; } else { try { return pooler.offerConnection(connection); } catch (Exception ex) { Server.logError(ex); return false; } } } } public static Connection getConnectionMySQL() { if (MYSQL_HOSTNAME == null) { return null; } else if (MYSQL_USER == null) { return null; } else if (MYSQL_PASSWORD == null) { return null; } else { try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://" + MYSQL_HOSTNAME + ":" + "" + MYSQL_PORT + "/" + MYSQL_SCHEMA + "" + "?autoReconnect=true" + "&useUnicode=true&characterEncoding=UTF-8" + (MYSQL_SSL ? "&verifyServerCertificate=false" + "&useSSL=true&requireSSL=true" : ""); DriverManager.setLoginTimeout(3); Connection connection = DriverManager.getConnection(url, MYSQL_USER, MYSQL_PASSWORD); Statement statement = connection.createStatement(); try { statement.executeUpdate("SET NAMES 'utf8mb4'"); } finally { statement.close(); } Server.logMySQL("connection created."); return connection; } catch (Exception ex) { Server.logError(ex); return null; } } } private static String HOSTNAME = null; private static String INTERFACE = null; private static String ADMIN_EMAIL = null; private static String ABUSE_EMAIL = null; private static short PORT_ADMIN = 9875; private static short PORT_WHOIS = 0; private static short PORT_SPFBL = 9877; private static short PORT_DNSBL = 0; private static short PORT_HTTP = 0; private static short UDP_MAX = 512; // UDP max size packet. public static boolean isAdminEmail(String email) { if (email == null) { return false; } else { return email.equals(ADMIN_EMAIL); } } public static boolean hasAdminEmail() { return ADMIN_EMAIL != null; } public static boolean isAbuseEmail(String email) { if (email == null) { return false; } else { return email.equals(ABUSE_EMAIL); } } public static boolean hasAbuseEmail() { return ABUSE_EMAIL != null; } public static InternetAddress getAdminInternetAddress() { if (ADMIN_EMAIL == null) { return null; } else { User user = User.get(ADMIN_EMAIL); if (user == null) { try { return new InternetAddress(ADMIN_EMAIL, "SPFBL Admin"); } catch (UnsupportedEncodingException ex) { return null; } } else { try { return user.getInternetAddress(); } catch (UnsupportedEncodingException ex) { return null; } } } } public static String getAdminEmail() { return ADMIN_EMAIL; } public static String getAbuseEmail() { return ABUSE_EMAIL; } public static short getPortAdmin() { return PORT_ADMIN; } public static short getPortWHOIS() { return PORT_WHOIS; } public static boolean hasPortWHOIS() { return PORT_WHOIS > 0; } public static short getPortSPFBL() { return PORT_SPFBL; } public static short getPortDNSBL() { return PORT_DNSBL; } public static boolean hasPortDNSBL() { return PORT_DNSBL > 0; } public static short getPortHTTP() { return PORT_HTTP; } public static boolean hasPortHTTP() { return PORT_HTTP > 0; } public static boolean hasInterface() { return INTERFACE != null; } public static String getInterface() { return INTERFACE; } public static String getHostname() { return HOSTNAME; } public static boolean hasHostname() { return HOSTNAME != null; } private static boolean isRouteable(String hostame) { try { Attributes attributesA = Server.getAttributesDNS(hostame, new String[] { "A" }); Attribute attributeA = attributesA.get("A"); if (attributeA == null) { Attributes attributesAAAA = Server.getAttributesDNS(hostame, new String[] { "AAAA" }); Attribute attributeAAAA = attributesAAAA.get("AAAA"); if (attributeAAAA != null) { for (int i = 0; i < attributeAAAA.size(); i++) { String host6Address = (String) attributeAAAA.get(i); if (SubnetIPv6.isValidIPv6(host6Address)) { try { InetAddress address = InetAddress.getByName(host6Address); if (address.isLinkLocalAddress()) { return false; } else if (address.isLoopbackAddress()) { return false; } } catch (UnknownHostException ex) { } } else { return false; } } } } else { for (int i = 0; i < attributeA.size(); i++) { String host4Address = (String) attributeA.get(i); host4Address = host4Address.trim(); if (SubnetIPv4.isValidIPv4(host4Address)) { try { InetAddress address = InetAddress.getByName(host4Address); if (address.isLinkLocalAddress()) { return false; } else if (address.isLoopbackAddress()) { return false; } } catch (UnknownHostException ex) { } } else { return false; } } } return true; } catch (NamingException ex) { return false; } } public static synchronized void setHostname(String hostame) { if (hostame != null && hostame.length() > 0) { if (!Domain.isHostname(hostame)) { Server.logError("invalid hostname '" + hostame + "'."); } else if (!Core.TESTING && !hostame.equals("localhost") && !isRouteable(hostame)) { Server.logError("unrouteable hostname '" + hostame + "'."); } else { Core.HOSTNAME = Domain.extractHost(hostame, false); } } } private static boolean hasInterface(String netInterface) { try { Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface netint : Collections.list(nets)) { if (netInterface.equals(netint.getName())) { return true; } } return false; } catch (SocketException ex) { return false; } } public static synchronized void setInterface(String netInterface) { if (netInterface != null && netInterface.length() > 0) { if (hasInterface(netInterface)) { Core.INTERFACE = netInterface; } else { Server.logError("network interface '" + netInterface + "' not found."); } } } public static synchronized void setAdminEmail(String email) { if (email != null && email.length() > 0) { if (Domain.isEmail(email)) { Core.ADMIN_EMAIL = email.toLowerCase(); } else { Server.logError("invalid admin e-mail '" + email + "'."); } } } public static synchronized void setAbuseEmail(String email) { if (email != null && email.length() > 0) { if (Domain.isEmail(email)) { Core.ABUSE_EMAIL = email.toLowerCase(); } else { Server.logError("invalid abuse e-mail '" + email + "'."); } } } public static void setPortAdmin(String port) { if (port != null && port.length() > 0) { try { setPortAdmin(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid administration port '" + port + "'."); } } } public static synchronized void setPortAdmin(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid administration port '" + port + "'."); } else { Core.PORT_ADMIN = (short) port; } } public static void setPortWHOIS(String port) { if (port != null && port.length() > 0) { try { setPortWHOIS(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid WHOIS port '" + port + "'."); } } } public static synchronized void setPortWHOIS(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid WHOIS port '" + port + "'."); } else { Core.PORT_WHOIS = (short) port; } } public static void setPortSPFBL(String port) { if (port != null && port.length() > 0) { try { setPortSPFBL(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid SPFBL port '" + port + "'."); } } } public static synchronized void setPortSPFBL(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid SPFBL port '" + port + "'."); } else { Core.PORT_SPFBL = (short) port; } } public static void setPortDNSBL(String port) { if (port != null && port.length() > 0) { try { setPortDNSBL(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid DNSBL port '" + port + "'."); } } } public static synchronized void setPortDNSBL(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid DNSBL port '" + port + "'."); } else { Core.PORT_DNSBL = (short) port; } } public static void setPortHTTP(String port) { if (port != null && port.length() > 0) { try { setPortHTTP(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid HTTP port '" + port + "'."); } } } public static synchronized void setPortHTTP(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid HTTP port '" + port + "'."); } else { Core.PORT_HTTP = (short) port; } } public static void setMaxUDP(String max) { if (max != null && max.length() > 0) { try { setMaxUDP(Integer.parseInt(max)); } catch (Exception ex) { Server.logError("invalid UDP max size '" + max + "'."); } } } public static synchronized void setMaxUDP(int max) { if (max < 128 || max > Short.MAX_VALUE) { Server.logError("invalid UDP max size '" + max + "'."); } else { Core.UDP_MAX = (short) max; } } public static void setLevelLOG(String level) { if (level != null && level.length() > 0) { try { Core.LOG_LEVEL = Core.Level.valueOf(level); } catch (Exception ex) { Server.logError("invalid LOG level '" + level + "'."); } } } public static boolean setLevelLOG(Level level) { if (level == null) { return false; } else if (level == Core.LOG_LEVEL) { return false; } else { Core.LOG_LEVEL = level; return true; } } private static float FLOOD_TIME_IP = 1.0f; public static float getFloodTimeIP() { return FLOOD_TIME_IP; } public static void setFloodTimeIP(String time) { if (time != null && time.length() > 0) { try { setFloodTimeIP(Float.parseFloat(time)); } catch (Exception ex) { Server.logError("invalid FLOOD IP time '" + time + "'."); } } } public static synchronized void setFloodTimeIP(float time) { if (time < 0.0f || time > Byte.MAX_VALUE) { Server.logError("invalid FLOOD IP time '" + time + "s'."); } else { Core.FLOOD_TIME_IP = time; } } private static float FLOOD_TIME_HELO = 10.0f; public static float getFloodTimeHELO() { return FLOOD_TIME_HELO; } public static void setFloodTimeHELO(String time) { if (time != null && time.length() > 0) { try { setFloodTimeHELO(Float.parseFloat(time)); } catch (Exception ex) { Server.logError("invalid FLOOD HELO time '" + time + "'."); } } } public static synchronized void setFloodTimeHELO(float time) { if (time < 0.0f || time > Byte.MAX_VALUE) { Server.logError("invalid FLOOD HELO time '" + time + "s'."); } else { Core.FLOOD_TIME_HELO = time; } } private static float FLOOD_TIME_SENDER = 30.0f; public static float getFloodTimeSender() { return FLOOD_TIME_SENDER; } public static void setFloodTimeSender(String time) { if (time != null && time.length() > 0) { try { setFloodTimeSender(Float.parseFloat(time)); } catch (Exception ex) { Server.logError("invalid FLOOD SENDER time '" + time + "'."); } } } public static synchronized void setFloodTimeSender(float time) { if (time < 0.0f || time > Byte.MAX_VALUE) { Server.logError("invalid FLOOD SENDER time '" + time + "s'."); } else { Core.FLOOD_TIME_SENDER = time; } } private static byte FLOOD_MAX_RETRY = 32; public static float getFloodMaxRetry() { return FLOOD_MAX_RETRY; } public static void setFloodMaxRetry(String max) { if (max != null && max.length() > 0) { try { setFloodMaxRetry(Integer.parseInt(max)); } catch (Exception ex) { Server.logError("invalid FLOOD max retry '" + max + "'."); } } } public static synchronized void setFloodMaxRetry(int max) { if (max < 0 || max > Byte.MAX_VALUE) { Server.logError("invalid FLOOD max retry '" + max + "'."); } else { Core.FLOOD_MAX_RETRY = (byte) max; } } private static class ApplicationMessageHandler implements MessageHandler { @Override public synchronized String handle(String message) { if (message.equals("register")) { Server.logDebug("another instance of this application tried to start."); } return null; } } private static byte DEFER_TIME_FLOOD = 1; public static byte getDeferTimeFLOOD() { return DEFER_TIME_FLOOD; } public static void setDeferTimeFLOOD(String time) { if (time != null && time.length() > 0) { try { setDeferTimeFLOOD(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid DEFER time for FLOOD '" + time + "'."); } } } public static synchronized void setDeferTimeFLOOD(int time) { if (time < 0 || time > Byte.MAX_VALUE) { Server.logError("invalid DEFER time for FLOOD '" + time + "'."); } else { Core.DEFER_TIME_FLOOD = (byte) time; } } private static byte DEFER_TIME_SOFTFAIL = 1; public static byte getDeferTimeSOFTFAIL() { return DEFER_TIME_SOFTFAIL; } public static void setDeferTimeSOFTFAIL(String time) { if (time != null && time.length() > 0) { try { setDeferTimeSOFTFAIL(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid DEFER time for SOFTFAIL '" + time + "'."); } } } public static synchronized void setDeferTimeSOFTFAIL(int time) { if (time < 0 || time > Byte.MAX_VALUE) { Server.logError("invalid DEFER time for SOFTFAIL '" + time + "'."); } else { Core.DEFER_TIME_SOFTFAIL = (byte) time; } } private static byte DEFER_TIME_YELLOW = 25; public static byte getDeferTimeYELLOW() { return DEFER_TIME_YELLOW; } public static void setDeferTimeYELLOW(String time) { if (time != null && time.length() > 0) { try { setDeferTimeYELLOW(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid DEFER time for YELLOW '" + time + "'."); } } } public static synchronized void setDeferTimeYELLOW(int time) { if (time < 0 || time > Byte.MAX_VALUE) { Server.logError("invalid DEFER time for YELLOW '" + time + "'."); } else { Core.DEFER_TIME_YELLOW = (byte) time; } } private static short DEFER_TIME_RED = 1435; public static short getDeferTimeRED() { return DEFER_TIME_RED; } public static void setDeferTimeRED(String time) { if (time != null && time.length() > 0) { try { setDeferTimeRED(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid DEFER time for RED '" + time + "'."); } } } public static synchronized void setDeferTimeRED(int time) { if (time < 0 || time > Short.MAX_VALUE) { Server.logError("invalid DEFER time for RED '" + time + "'."); } else { Core.DEFER_TIME_RED = (short) time; } } private static short DEFER_TIME_HOLD = 7175; public static short getDeferTimeHOLD() { return DEFER_TIME_HOLD; } public static void setDeferTimeHOLD(String time) { if (time != null && time.length() > 0) { try { setDeferTimeHOLD(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid DEFER time for HOLD '" + time + "'."); } } } public static synchronized void setDeferTimeHOLD(int time) { if (time < 0 || time > Short.MAX_VALUE) { Server.logError("invalid DEFER time for HOLD '" + time + "'."); } else { Core.DEFER_TIME_HOLD = (short) time; } } private static boolean REVERSE_REQUIRED = false; public static boolean isReverseRequired() { return REVERSE_REQUIRED; } public static void setReverseRequired(String required) { if (required != null && required.length() > 0) { try { setReverseRequired(Boolean.parseBoolean(required)); } catch (Exception ex) { Server.logError("invalid required reverse flag '" + required + "'."); } } } public static synchronized void setReverseRequired(boolean required) { Core.REVERSE_REQUIRED = required; } private static String RECAPTCHA_KEY_SITE = null; private static String RECAPTCHA_KEY_SECRET = null; public static boolean hasRecaptchaKeys() { return RECAPTCHA_KEY_SITE != null && RECAPTCHA_KEY_SECRET != null; } public static String getRecaptchaKeySite() { return RECAPTCHA_KEY_SITE; } public static void setRecaptchaKeySite(String key) { if (key != null && key.length() > 0) { RECAPTCHA_KEY_SITE = key; } } public static String getRecaptchaKeySecret() { return RECAPTCHA_KEY_SECRET; } public static void setRecaptchaKeySecret(String key) { if (key != null && key.length() > 0) { RECAPTCHA_KEY_SECRET = key; } } private static boolean SMTP_IS_AUTH = true; private static boolean SMTP_STARTTLS = true; private static String SMTP_HOST = null; private static short SMTP_PORT = 465; private static String SMTP_USER = null; private static String SMTP_PASSWORD = null; public static void setPortSMTP(String port) { if (port != null && port.length() > 0) { try { setPortSMTP(Integer.parseInt(port)); } catch (Exception ex) { Server.logError("invalid SMTP port '" + port + "'."); } } } public static synchronized void setPortSMTP(int port) { if (port < 1 || port > Short.MAX_VALUE) { Server.logError("invalid SMTP port '" + port + "'."); } else { Core.SMTP_PORT = (short) port; } } public static void setIsAuthSMTP(String auth) { if (auth != null && auth.length() > 0) { try { setIsAuthSMTP(Boolean.parseBoolean(auth)); } catch (Exception ex) { Server.logError("invalid SMTP is auth '" + auth + "'."); } } } public static synchronized void setIsAuthSMTP(boolean auth) { Core.SMTP_IS_AUTH = auth; } public static void setStartTLSSMTP(String startTLS) { if (startTLS != null && startTLS.length() > 0) { try { setStartTLSSMTP(Boolean.parseBoolean(startTLS)); } catch (Exception ex) { Server.logError("invalid SMTP start TLS '" + startTLS + "'."); } } } public static synchronized void setStartTLSSMTP(boolean startTLS) { Core.SMTP_STARTTLS = startTLS; } public static synchronized void setHostSMTP(String host) { if (host != null && host.length() > 0) { if (Subnet.isValidIP(host)) { Core.SMTP_HOST = Subnet.normalizeIP(host); } else if (Domain.isHostname(host)) { Core.SMTP_HOST = Domain.normalizeHostname(host, false); } else { Server.logError("invalid SMTP hostname '" + host + "'."); } } } public static synchronized void setUserSMTP(String user) { if (user != null && user.length() > 0) { if (Domain.isEmail(user) || Domain.isHostname(user)) { Core.SMTP_USER = user; } else { Server.logError("invalid SMTP user '" + user + "'."); } } } public static synchronized void setPasswordSMTP(String password) { if (password != null && password.length() > 0) { if (password.contains(" ")) { Server.logError("invalid SMTP password '" + password + "'."); } else { Core.SMTP_PASSWORD = password; } } } private static final short REPUTATION_LIMIT = 1024; public static short getReputationLimit() { return REPUTATION_LIMIT; } public static final DecimalFormat CENTENA_FORMAT = new DecimalFormat("000"); public static final NumberFormat DECIMAL_FORMAT = NumberFormat.getNumberInstance(); public static final NumberFormat PERCENT_FORMAT = NumberFormat.getPercentInstance(); public static final SimpleDateFormat SQL_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); /** * Constante para formatar datas com hora no padro de e-mail. */ private static final SimpleDateFormat DATE_EMAIL_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); public static synchronized String getEmailDate() { return DATE_EMAIL_FORMAT.format(new Date()); } public static boolean hasOutputSMTP() { if (isDirectSMTP()) { return true; } else if (hasRelaySMTP()) { return true; } else { return false; } } public static boolean isDirectSMTP() { if (SMTP_HOST == null) { return false; } else { return SMTP_HOST.equals(HOSTNAME); } } public static boolean hasRelaySMTP() { if (SMTP_HOST == null) { return false; } else if (SMTP_IS_AUTH && SMTP_USER == null) { return false; } else if (SMTP_IS_AUTH && SMTP_PASSWORD == null) { return false; } else { return true; } } public static synchronized boolean sendMessage(Message message, int timeout) throws Exception { if (message == null) { return false; } else if (isDirectSMTP()) { Server.logInfo("sending e-mail message."); Server.logSendMTP("authenticate: false."); Server.logSendMTP("start TLS: true."); Properties props = System.getProperties(); props.put("mail.smtp.auth", "false"); props.put("mail.smtp.port", "25"); props.put("mail.smtp.timeout", Integer.toString(timeout)); props.put("mail.smtp.connectiontimeout", "3000"); InternetAddress[] recipients = (InternetAddress[]) message.getAllRecipients(); Exception lastException = null; for (InternetAddress recipient : recipients) { String domain = Domain.normalizeHostname(recipient.getAddress(), false); for (String mx : Reverse.getMXSet(domain)) { mx = mx.substring(1); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.host", mx); props.put("mail.smtp.ssl.trust", mx); InternetAddress[] recipientAlone = new InternetAddress[1]; recipientAlone[0] = (InternetAddress) recipient; Session session = Session.getDefaultInstance(props); SMTPTransport transport = (SMTPTransport) session.getTransport("smtp"); try { transport.setLocalHost(HOSTNAME); Server.logSendMTP("connecting to " + mx + ":25."); transport.connect(mx, 25, null, null); Server.logSendMTP("sending '" + message.getSubject() + "' to " + recipient + "."); transport.sendMessage(message, recipientAlone); Server.logSendMTP("message '" + message.getSubject() + "' sent to " + recipient + "."); Server.logSendMTP("last response: " + transport.getLastServerResponse()); lastException = null; break; } catch (MailConnectException ex) { Server.logSendMTP("connection failed."); lastException = ex; } catch (SendFailedException ex) { Server.logSendMTP("send failed."); throw ex; } catch (MessagingException ex) { if (ex.getMessage().contains(" TLS ")) { Server.logSendMTP("cannot establish TLS connection."); if (transport.isConnected()) { transport.close(); Server.logSendMTP("connection closed."); } Server.logInfo("sending e-mail message without TLS."); props.put("mail.smtp.starttls.enable", "false"); session = Session.getDefaultInstance(props); transport = (SMTPTransport) session.getTransport("smtp"); try { transport.setLocalHost(HOSTNAME); Server.logSendMTP("connecting to " + mx + ":25."); transport.connect(mx, 25, null, null); Server.logSendMTP("sending '" + message.getSubject() + "' to " + recipient + "."); transport.sendMessage(message, recipientAlone); Server.logSendMTP( "message '" + message.getSubject() + "' sent to " + recipient + "."); Server.logSendMTP("last response: " + transport.getLastServerResponse()); lastException = null; break; } catch (SendFailedException ex2) { Server.logSendMTP("send failed."); throw ex2; } catch (Exception ex2) { lastException = ex2; } } else { lastException = ex; } } catch (Exception ex) { Server.logError(ex); lastException = ex; } finally { if (transport.isConnected()) { transport.close(); Server.logSendMTP("connection closed."); } } } } if (lastException == null) { return true; } else { throw lastException; } } else if (hasRelaySMTP()) { Server.logInfo("sending e-mail message."); Server.logSendMTP("authenticate: " + Boolean.toString(SMTP_IS_AUTH) + "."); Server.logSendMTP("start TLS: " + Boolean.toString(SMTP_STARTTLS) + "."); Properties props = System.getProperties(); props.put("mail.smtp.auth", Boolean.toString(SMTP_IS_AUTH)); props.put("mail.smtp.starttls.enable", Boolean.toString(SMTP_STARTTLS)); props.put("mail.smtp.host", SMTP_HOST); props.put("mail.smtp.port", Short.toString(SMTP_PORT)); props.put("mail.smtp.timeout", Integer.toString(timeout)); props.put("mail.smtp.connectiontimeout", "3000"); props.put("mail.smtp.ssl.trust", SMTP_HOST); Address[] recipients = message.getAllRecipients(); TreeSet<String> recipientSet = new TreeSet<String>(); for (Address recipient : recipients) { recipientSet.add(recipient.toString()); } Session session = Session.getDefaultInstance(props); SMTPTransport transport = (SMTPTransport) session.getTransport("smtp"); try { if (HOSTNAME != null) { transport.setLocalHost(HOSTNAME); } Server.logSendMTP("connecting to " + SMTP_HOST + ":" + SMTP_PORT + "."); transport.connect(SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD); Server.logSendMTP("sending '" + message.getSubject() + "' to " + recipientSet + "."); transport.sendMessage(message, recipients); Server.logSendMTP("message '" + message.getSubject() + "' sent to " + recipientSet + "."); return true; } catch (SendFailedException ex) { Server.logSendMTP("send failed."); throw ex; } catch (AuthenticationFailedException ex) { Server.logSendMTP("authentication failed."); return false; } catch (MailConnectException ex) { Server.logSendMTP("connection failed."); return false; } catch (MessagingException ex) { Server.logSendMTP("messaging failed."); return false; } catch (Exception ex) { Server.logError(ex); return false; } finally { if (transport.isConnected()) { transport.close(); Server.logSendMTP("connection closed."); } } } else { return false; } } /** * @param args the command line arguments */ public static void main(String[] args) { Thread.currentThread().setName("SYSTEMCOR"); try { String appId = Server.class.getCanonicalName(); ApplicationMessageHandler messageHandler = new ApplicationMessageHandler(); boolean alreadyRunning; try { JUnique.acquireLock(appId, messageHandler); alreadyRunning = false; } catch (AlreadyLockedException ex) { alreadyRunning = true; } if (alreadyRunning) { JUnique.sendMessage(appId, "register"); System.exit(1); } else { loadConfiguration(); Server.logInfo("starting server..."); Server.loadCache(); try { administrationTCP = new AdministrationTCP(PORT_ADMIN); administrationTCP.start(); } catch (BindException ex) { Server.logError( "system could not start because TCP port " + PORT_ADMIN + " is already in use."); System.exit(1); } if (PORT_WHOIS > 0) { try { new QueryTCP(PORT_WHOIS).start(); } catch (BindException ex) { Server.logError("WHOIS socket was not binded because TCP port " + PORT_WHOIS + " is already in use."); } } if (PORT_SPFBL > 0) { try { querySPF = new QuerySPF(PORT_SPFBL); querySPF.start(); } catch (BindException ex) { querySPF = null; Server.logError("SPFBL socket was not binded because TCP port " + PORT_SPFBL + " is already in use."); } if (HOSTNAME == null) { Server.logInfo("P2P socket was not binded because no hostname defined."); } else if (isRouteable(HOSTNAME)) { try { peerUDP = new PeerUDP(HOSTNAME, PORT_SPFBL, UDP_MAX); peerUDP.start(); } catch (BindException ex) { peerUDP = null; Server.logError("P2P socket was not binded because UDP port " + PORT_SPFBL + " is already in use."); } } else { Server.logError("P2P socket was not binded because '" + HOSTNAME + "' is not a routeable hostname."); } } if (PORT_DNSBL > 0) { try { queryDNSBL = new QueryDNS(PORT_DNSBL); queryDNSBL.start(); } catch (BindException ex) { queryDNSBL = null; Server.logError("DNSBL socket was not binded because UDP port " + PORT_DNSBL + " is already in use."); } } if (PORT_HTTP > 0) { if (HOSTNAME == null) { Server.logInfo("HTTP socket was not binded because no hostname defined."); } else { try { complainHTTP = new ServerHTTP(HOSTNAME, PORT_HTTP); complainHTTP.load(); complainHTTP.start(); } catch (BindException ex) { complainHTTP = null; Server.logError("HTTP socket was not binded because TCP port " + PORT_HTTP + " is already in use."); } } } Peer.sendHeloToAll(); Core.startTimer(); Analise.initProcess(); } } catch (Exception ex) { Server.logError(ex); System.exit(1); } } /** * Timer que controla os processos em background. */ private static final Timer TIMER = new Timer("BCKGROUND"); public static void cancelTimer() { TIMER.cancel(); } private static class TimerInterruptTimeout extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Interromper conexes vencidas. Core.interruptTimeout(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerRefreshSPF extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Atualiza registro SPF mais consultado. SPF.refreshSPF(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerRefreshHELO extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Atualiza registro HELO mais consultado. SPF.refreshHELO(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerRefreshReverse extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Atualiza registro de IP reverso mais consultado. Reverse.refreshLast(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerRefreshWHOIS extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Atualiza registros WHOIS expirando. Server.tryRefreshWHOIS(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredSPF extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Remoo de registros SPF expirados. SPF.dropExpiredSPF(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerCheckAccessSMTP extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); Analise.checkAccessSMTP(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerSendHoldingWarningMessages extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); User.sendHoldingWarning(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerSendSuspectWarningMessages extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); User.sendSuspectWarning(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerSendBlockedWarningMessages extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); User.sendBlockedWarning(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredPeer extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Remoo de registros de reputao expirados. Peer.sendHeloToAll(); Peer.dropExpired(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredHELO extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Apagar todas os registros de DNS de HELO vencidos. SPF.dropExpiredHELO(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredReverse extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Apagar todas os registros de IP reverso vencidos. Reverse.dropExpired(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredDistribution extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Apagar todas as distribuies e consultas vencidas. User.dropAllExpiredQuery(); SPF.dropExpiredDistribution(); Block.dropExpired(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDropExpiredDefer extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Apagar todas os registros de atrazo programado vencidos. Defer.dropExpired(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerStoreCache extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Armazena todos os registros atualizados durante a consulta. Server.tryStoreCache(); } catch (Exception ex) { Server.logError(ex); } } } private static class TimerDeleteLogExpired extends TimerTask { @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Apaga todos os arquivos de LOG vencidos. Server.deleteLogExpired(); // Apaga todos as listas de analise vencidas. Analise.dropExpired(); } catch (Exception ex) { Server.logError(ex); } } } private static long CACHE_TIME_STORE = 3600000; // Frequncia de 1 hora. public static void setCacheTimeStore(String time) { if (time != null && time.length() > 0) { try { setCacheTimeStore(Integer.parseInt(time)); } catch (Exception ex) { Server.logError("invalid cache time store '" + time + "'."); } } } public static synchronized void setCacheTimeStore(int time) { if (time < 0 || time > 1440) { Server.logError("invalid cache time store '" + time + "'."); } else { Core.CACHE_TIME_STORE = time * 60000; } } public static void startTimer() { TIMER.schedule(new TimerInterruptTimeout(), 10000, 10000); // Frequncia de 10 segundos. TIMER.schedule(new TimerRefreshSPF(), 30000, 60000); // Frequncia de 1 minuto. TIMER.schedule(new TimerRefreshHELO(), 60000, 60000); // Frequncia de 1 minuto. TIMER.schedule(new TimerRefreshReverse(), 60000, 60000); // Frequncia de 1 minuto. TIMER.schedule(new TimerRefreshWHOIS(), 600000, 600000); // Frequncia de 10 minutos. TIMER.schedule(new TimerSendHoldingWarningMessages(), 300000, 600000); // Frequncia de 10 minutos. TIMER.schedule(new TimerDropExpiredPeer(), 900000, 1800000); // Frequncia de 30 minutos. TIMER.schedule(new TimerDropExpiredSPF(), 600000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerDropExpiredHELO(), 1200000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerDropExpiredReverse(), 1200000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerDropExpiredDistribution(), 1800000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerDropExpiredDefer(), 2400000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerSendSuspectWarningMessages(), 2400000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerSendBlockedWarningMessages(), 3600000, 3600000); // Frequncia de 1 hora. TIMER.schedule(new TimerDeleteLogExpired(), 3600000, 3600000); // Frequncia de 1 hora. if (CACHE_TIME_STORE > 0) { TIMER.schedule(new TimerStoreCache(), CACHE_TIME_STORE, CACHE_TIME_STORE); } TIMER.schedule(new TimerCheckAccessSMTP(), 0, 86400000); // Frequncia de 24 horas. } public static String removerAcentuacao(String text) { if (text == null) { return null; } else { StringBuilder builder = new StringBuilder(); for (char character : text.toCharArray()) { switch (character) { case '?': case '': case '': case '': character = 'A'; break; case '': case '': character = 'E'; break; case '?': character = 'I'; break; case '': case '': case '': character = 'O'; break; case '': character = 'U'; break; case '': character = 'C'; break; case '': case '': case '': case '': case '': character = 'a'; break; case '': case '': character = 'e'; break; case '': character = 'i'; break; case '': case '': case '': case '': character = 'o'; break; case '': character = 'u'; break; case '': character = 'c'; break; } builder.append(character); } return builder.toString(); } } public static boolean isValidOTP(String secret, int code) { if (secret == null) { return false; } else { byte[] buffer = new Base32().decode(secret); long index = getTimeIndexOTP(); if (code == getCodeOTP(buffer, index - 2)) { return true; } else if (code == getCodeOTP(buffer, index - 1)) { return true; } else if (code == getCodeOTP(buffer, index)) { return true; } else if (code == getCodeOTP(buffer, index + 1)) { return true; } else if (code == getCodeOTP(buffer, index + 2)) { return true; } else { return false; } } } public static String generateSecretOTP() { byte[] buffer = new byte[10]; new SecureRandom().nextBytes(buffer); return new String(new Base32().encode(buffer)); } private static long getTimeIndexOTP() { return System.currentTimeMillis() / 1000 / 30; } private static long getCodeOTP(byte[] secret, long timeIndex) { try { SecretKeySpec signKey = new SecretKeySpec(secret, "HmacSHA1"); ByteBuffer buffer = ByteBuffer.allocate(8); buffer.putLong(timeIndex); byte[] timeBytes = buffer.array(); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signKey); byte[] hash = mac.doFinal(timeBytes); int offset = hash[19] & 0xf; long truncatedHash = hash[offset] & 0x7f; for (int i = 1; i < 4; i++) { truncatedHash <<= 8; truncatedHash |= hash[offset + i] & 0xff; } return (truncatedHash %= 1000000); } catch (Exception ex) { return 0; } } public static Integer getInteger(String text) { if (text == null) { return null; } else { try { return Integer.parseInt(text); } catch (NumberFormatException ex) { return null; } } } public static boolean equals(String text1, String text2) { if (text1 == null) { return text2 == null; } else { return text1.equals(text2); } } private static final Runtime RUNTIME = Runtime.getRuntime(); public static float relativeFreeMemory() { return (float) RUNTIME.freeMemory() / (float) RUNTIME.maxMemory(); } public static boolean hasLowMemory() { return relativeFreeMemory() < 0.0625f; } private static final QRCodeWriter qrCodeWriter = new QRCodeWriter(); public static File getQRCodeTempFile(String codigo) throws Exception { BitMatrix matrix = qrCodeWriter.encode(codigo, com.google.zxing.BarcodeFormat.QR_CODE, 256, 256); int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (!matrix.get(x, y)) { image.setRGB(x, y, Color.WHITE.getRGB()); } } } File file = File.createTempFile(Long.toString(Server.getNewUniqueTime()), ".png"); ImageIO.write(image, "PNG", file); Server.logTrace("QRCode temp file created at " + file.getAbsolutePath() + "."); file.deleteOnExit(); return file; } public static boolean isLong(String text) { try { Long.parseLong(text); return true; } catch (Exception ex) { return false; } } public static TreeSet<String> getTreeSet(String text, String demiliter) { if (text == null) { return null; } else if (demiliter == null) { return null; } else { TreeSet<String> resultSet = new TreeSet<String>(); StringTokenizer tokenizer = new StringTokenizer(text, demiliter); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); resultSet.add(token); } return resultSet; } } public static TreeMap<String, Boolean> getTreeMapBoolean(String text, String demiliter) { if (text == null) { return null; } else if (demiliter == null) { return null; } else { TreeMap<String, Boolean> resultMap = new TreeMap<String, Boolean>(); StringTokenizer tokenizer = new StringTokenizer(text, demiliter); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); int index = token.indexOf('='); boolean value = Boolean.parseBoolean(token.substring(index + 1)); String key = token.substring(0, index); resultMap.put(key, value); } return resultMap; } } public static String getSequence(TreeSet<String> set, String demiliter) { if (set == null) { return null; } else if (demiliter == null) { return null; } else if (set.isEmpty()) { return null; } else { StringBuilder builder = new StringBuilder(); for (String token : set) { if (builder.length() > 0) { builder.append(demiliter); } builder.append(token); } return builder.toString(); } } public static String getSequence(TreeMap<String, Boolean> map, String demiliter) { if (map == null) { return null; } else if (demiliter == null) { return null; } else if (map.isEmpty()) { return null; } else { StringBuilder builder = new StringBuilder(); for (String key : map.keySet()) { boolean value = map.get(key); if (builder.length() > 0) { builder.append(demiliter); } builder.append(key); builder.append('='); builder.append(value); } return builder.toString(); } } public static boolean hasUnicodeBlock(String text, Character.UnicodeBlock block) { if (text == null) { return false; } else { for (char character : text.toCharArray()) { if (Character.UnicodeBlock.of(character) == block) { return true; } } return false; } } public static boolean hasMiscellaneousSymbols(String text) { if (text == null) { return false; } else { for (char character : text.toCharArray()) { Character.UnicodeBlock block = Character.UnicodeBlock.of(character); if (block == Character.UnicodeBlock.MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A) { return true; } else if (block == Character.UnicodeBlock.MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B) { return true; } else if (block == Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS) { return true; } else if (block == Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_ARROWS) { return true; } else if (block == Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS) { return true; } else if (block == Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL) { return true; } } return false; } } private static final Locale LOCALE_BRAZIL = new Locale("pt", "BR"); private static final Locale LOCALE_PORTUGAL = new Locale("pt", "PT"); public static Locale getDefaultLocale(String address) { if (address == null) { return null; } else if (address.endsWith(".br")) { return LOCALE_BRAZIL; } else if (address.endsWith(".pt")) { return LOCALE_PORTUGAL; } else if (address.endsWith(".net")) { return Locale.US; } else if (address.endsWith(".com")) { return Locale.US; } else if (address.endsWith(".org")) { return Locale.US; } else if (address.endsWith(".uk")) { return Locale.US; } else { return Locale.getDefault(); } } public static URL getURL(String url) { if (url == null) { return null; } else { try { return new URL(url); } catch (MalformedURLException ex) { Server.logError(ex); return null; } } } }