net.spfbl.data.Trap.java Source code

Java tutorial

Introduction

Here is the source code for net.spfbl.data.Trap.java

Source

/*
 * 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.data;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import net.spfbl.core.Client;
import net.spfbl.core.ProcessException;
import net.spfbl.core.Server;
import net.spfbl.core.User;
import net.spfbl.whois.Domain;
import org.apache.commons.lang3.SerializationUtils;

/**
 * Representa a lista de spamtrap do sistema.
 * 
 * @author Leandro Carlos Rodrigues <leandro@spfbl.net>
 */
public class Trap {

    /**
     * Conjunto de destinatarios de spamtrap.
     */
    //    private static final HashSet<String> SET = new HashSet<String>();
    private static final HashMap<String, Long> MAP = new HashMap<String, Long>();
    /**
     * Flag que indica se o cache foi modificado.
     */
    private static boolean CHANGED = false;

    private synchronized static boolean dropExact(String token) {
        if (token == null) {
            return false;
        } else if (MAP.remove(token) == null) {
            return false;
        } else {
            CHANGED = true;
            return true;
        }
    }

    public static boolean putTrap(String client, String token, String timeString) throws ProcessException {
        if (!Domain.isValidEmail(client)) {
            throw new ProcessException("INVALID USER");
        } else if (!isValid(token)) {
            throw new ProcessException("INVALID TRAP");
        } else {
            try {
                Long time = timeString == null ? 0L : Long.parseLong(timeString);
                return putExact(client.toLowerCase() + ':' + token.toLowerCase(), time);
            } catch (NumberFormatException ex) {
                throw new ProcessException("INVALID TIME", ex);
            }
        }
    }

    public static boolean putInexistent(String client, String token, String timeString) throws ProcessException {
        if (!Domain.isValidEmail(client)) {
            throw new ProcessException("INVALID USER");
        } else if (!isValid(token)) {
            throw new ProcessException("INVALID ADDRESS");
        } else {
            try {
                long time = timeString == null ? System.currentTimeMillis() + 31536000000L
                        : Long.parseLong(timeString);
                if (time < System.currentTimeMillis()) {
                    throw new ProcessException("INVALID TIME");
                } else {
                    return putExact(client.toLowerCase() + ':' + token.toLowerCase(), time);
                }
            } catch (NumberFormatException ex) {
                throw new ProcessException("INVALID TIME", ex);
            }
        }
    }

    public static boolean putTrap(String token, String timeString) throws ProcessException {
        if (!isValid(token)) {
            throw new ProcessException("INVALID TRAP");
        } else {
            try {
                Long time = timeString == null ? 0L : Long.parseLong(timeString);
                return putExact(token.toLowerCase(), time);
            } catch (NumberFormatException ex) {
                throw new ProcessException("INVALID TIME", ex);
            }
        }
    }

    public static boolean putInexistent(String token, String timeString) throws ProcessException {
        if (!isValid(token)) {
            throw new ProcessException("INVALID ADDRESS");
        } else {
            try {
                long time = timeString == null ? System.currentTimeMillis() + 31536000000L
                        : Long.parseLong(timeString);
                if (time < System.currentTimeMillis()) {
                    throw new ProcessException("INVALID TIME");
                } else {
                    return putExact(token.toLowerCase(), time);
                }
            } catch (NumberFormatException ex) {
                throw new ProcessException("INVALID TIME", ex);
            }
        }
    }

    private synchronized static boolean putExact(String token, Long timeNew) {
        if (token == null || timeNew == null) {
            return false;
        } else {
            Long timeOld = MAP.put(token, timeNew);
            if (timeOld == null) {
                return CHANGED = true;
            } else {
                long timeNow = System.currentTimeMillis();
                boolean changed = timeOld < timeNow != timeNew < timeNow;
                CHANGED |= changed;
                return changed;
            }
        }
    }

    private synchronized static boolean addTrapExact(String token) {
        if (token == null) {
            return false;
        } else {
            Long time = MAP.put(token, 0L);
            if (time == null || !time.equals(0L)) {
                return CHANGED = true;
            } else {
                return false;
            }
        }
    }

    public synchronized static TreeSet<String> getTrapAllSet() {
        TreeSet<String> blockSet = new TreeSet<String>();
        for (String key : MAP.keySet()) {
            if (System.currentTimeMillis() > MAP.get(key)) {
                blockSet.add(key);
            }
        }
        return blockSet;
    }

    public synchronized static TreeSet<String> getInexistentAllSet() {
        TreeSet<String> blockSet = new TreeSet<String>();
        for (String key : MAP.keySet()) {
            if (System.currentTimeMillis() <= MAP.get(key)) {
                blockSet.add(key);
            }
        }
        return blockSet;
    }

    public synchronized static Long getTime(String address) {
        if (address == null) {
            return null;
        } else {
            return MAP.get(address);
        }
    }

    public synchronized static HashMap<String, Long> getMap() {
        HashMap<String, Long> map = new HashMap<String, Long>();
        map.putAll(MAP);
        return map;
    }

    public synchronized static boolean containsTrapExact(String address) {
        return System.currentTimeMillis() > MAP.get(address);
    }

    public synchronized static boolean containsInexistentExact(String address) {
        return System.currentTimeMillis() <= MAP.get(address);
    }

    public synchronized static boolean containsAnythingExact(String address) {
        return MAP.containsKey(address);
    }

    public static boolean isValid(String recipient) {
        if (recipient == null) {
            return false;
        } else if (Domain.isValidEmail(recipient)) {
            return true;
        } else {
            return recipient.startsWith("@") && Domain.containsDomain(recipient.substring(1));
        }
    }

    public static boolean addTrap(String recipient) throws ProcessException {
        if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            return addTrapExact(recipient.toLowerCase());
        }
    }

    public static boolean addTrap(Client client, String recipient) throws ProcessException {
        if (client == null || !client.hasEmail()) {
            throw new ProcessException("CLIENT INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            return addTrapExact(client.getEmail() + ':' + recipient.toLowerCase());
        }
    }

    public static boolean addTrap(String client, String recipient) throws ProcessException {
        if (client == null || !Domain.isValidEmail(client)) {
            throw new ProcessException("CLIENT INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            return addTrapExact(client + ':' + recipient.toLowerCase());
        }
    }

    public static boolean addInexistentForever(String recipient) {
        if (!isValid(recipient)) {
            return false;
        } else {
            return putExact(recipient.toLowerCase(), Long.MAX_VALUE);
        }
    }

    public static boolean addInexistentSafe(User user, String recipient) {
        if (user == null) {
            return false;
        } else if (!isValid(recipient)) {
            return false;
        } else {
            long time = System.currentTimeMillis() + 31536000000L;
            return putExact(user.getEmail() + ':' + recipient.toLowerCase(), time);
        }
    }

    public static boolean addInexistent(User user, String recipient) throws ProcessException {
        if (user == null) {
            throw new ProcessException("USER INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            long time = System.currentTimeMillis() + 31536000000L;
            return putExact(user.getEmail() + ':' + recipient.toLowerCase(), time);
        }
    }

    public static boolean addInexistentForever(User user, String recipient) {
        if (user == null) {
            return false;
        } else if (!isValid(recipient)) {
            return false;
        } else {
            return putExact(user.getEmail() + ':' + recipient.toLowerCase(), Long.MAX_VALUE);
        }
    }

    public static boolean addInexistent(Client client, String recipient) throws ProcessException {
        if (client == null || !client.hasEmail()) {
            throw new ProcessException("CLIENT INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            long time = System.currentTimeMillis() + 31536000000L;
            return putExact(client.getEmail() + ':' + recipient.toLowerCase(), time);
        }
    }

    public static TreeSet<String> dropTrapAll() throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        for (String trap : getTrapAllSet()) {
            if (dropExact(trap)) {
                trapSet.add(trap);
            }
        }
        return trapSet;
    }

    public static TreeSet<String> dropInexistentAll() throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        for (String trap : getInexistentAllSet()) {
            if (dropExact(trap)) {
                trapSet.add(trap);
            }
        }
        return trapSet;
    }

    public static boolean clear(User user, String address) throws ProcessException {
        if (isValid(address)) {
            int index = address.indexOf('@');
            String domain = address.substring(index);
            boolean dropped = drop(address);
            dropped |= drop(domain);
            if (user != null) {
                dropped |= drop(user, address);
                dropped |= drop(user, domain);
            }
            return dropped;
        } else {
            return false;
        }
    }

    public static boolean clear(Client client, User user, String address) throws ProcessException {
        if (isValid(address)) {
            int index = address.indexOf('@');
            String domain = address.substring(index);
            boolean dropped = drop(address);
            dropped |= drop(domain);
            if (user != null) {
                dropped |= drop(user, address);
                dropped |= drop(user, domain);
            }
            if (client != null) {
                dropped |= drop(client, address);
                dropped |= drop(client, domain);
            }
            return dropped;
        } else {
            return false;
        }
    }

    public static boolean clear(TreeSet<String> clientSet, User user, String address) throws ProcessException {
        if (isValid(address)) {
            int index = address.indexOf('@');
            String domain = address.substring(index);
            boolean dropped = drop(address);
            dropped |= drop(domain);
            if (user != null) {
                dropped |= drop(user, address);
                dropped |= drop(user, domain);
            }
            if (clientSet != null) {
                for (String client : clientSet) {
                    dropped |= drop(client, address);
                    dropped |= drop(client, domain);
                }
            }
            return dropped;
        } else {
            return false;
        }
    }

    public static boolean drop(String recipient) throws ProcessException {
        if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            return dropExact(recipient.toLowerCase());
        }
    }

    public static boolean drop(User user, String recipient) throws ProcessException {
        if (user == null) {
            throw new ProcessException("USER INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            boolean dropped = dropExact(user.getEmail() + ':' + recipient.toLowerCase());
            if (Domain.isValidEmail(recipient)) {
                dropped |= dropExact(recipient.toLowerCase());
                if (user.isPostmaster()) {
                    for (User localUser : User.getSet()) {
                        dropped |= dropExact(localUser.getEmail() + ':' + recipient.toLowerCase());
                    }
                }
            }
            return dropped;
        }
    }

    public static boolean drop(Client client, String recipient) throws ProcessException {
        if (client == null || !client.hasEmail()) {
            throw new ProcessException("CLIENT INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            boolean dropped = dropExact(client.getEmail() + ':' + recipient.toLowerCase());
            if (Domain.isValidEmail(recipient)) {
                dropped |= dropExact(recipient.toLowerCase());
            }
            return dropped;
        }
    }

    public static boolean drop(User user, Client client, String recipient) throws ProcessException {
        boolean dropped = drop(client, recipient);
        return dropped |= drop(user, recipient);
    }

    public static boolean drop(String client, String recipient) throws ProcessException {
        if (client == null || !Domain.isValidEmail(client)) {
            throw new ProcessException("CLIENT INVALID");
        } else if (!isValid(recipient)) {
            throw new ProcessException("RECIPIENT INVALID");
        } else {
            boolean dropped = dropExact(client + ':' + recipient.toLowerCase());
            if (Domain.isValidEmail(recipient)) {
                dropped |= dropExact(recipient.toLowerCase());
            }
            return dropped;
        }
    }

    public static TreeSet<String> getTrapSet(Client client) throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        if (client != null && client.hasEmail()) {
            for (String recipient : getTrapAllSet()) {
                if (recipient.startsWith(client.getEmail() + ':')) {
                    int index = recipient.indexOf(':') + 1;
                    recipient = recipient.substring(index);
                    trapSet.add(recipient);
                }
            }
        }
        return trapSet;
    }

    public static TreeSet<String> getInexistentSet(Client client) throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        if (client != null && client.hasEmail()) {
            for (String recipient : getInexistentAllSet()) {
                if (recipient.startsWith(client.getEmail() + ':')) {
                    int index = recipient.indexOf(':') + 1;
                    recipient = recipient.substring(index);
                    trapSet.add(recipient);
                }
            }
        }
        return trapSet;
    }

    public static TreeSet<String> getTrapSet() throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        for (String recipient : getTrapAllSet()) {
            if (!recipient.contains(":")) {
                trapSet.add(recipient);
            }
        }
        return trapSet;
    }

    public static TreeSet<String> getInexistentSet() throws ProcessException {
        TreeSet<String> trapSet = new TreeSet<String>();
        for (String recipient : getInexistentAllSet()) {
            if (!recipient.contains(":")) {
                trapSet.add(recipient);
            }
        }
        return trapSet;
    }

    public static boolean containsTrap(Client client, User user, String recipient) {
        // Definio do e-mail do usurio.
        String userEmail = null;
        if (user != null) {
            userEmail = user.getEmail();
        } else if (client != null) {
            userEmail = client.getEmail();
        }
        if (userEmail == null) {
            return false;
        } else if (!isValid(recipient)) {
            return false;
        } else {
            recipient = recipient.toLowerCase();
            int index2 = recipient.lastIndexOf('@');
            String domain = recipient.substring(recipient.lastIndexOf('@'));
            if (containsTrapExact(recipient)) {
                return true;
            } else if (containsTrapExact(domain)) {
                return true;
            } else if (containsTrapExact(userEmail + ':' + recipient)) {
                return true;
            } else if (containsTrapExact(userEmail + ':' + domain)) {
                return true;
            } else {
                int index3 = domain.length();
                while ((index3 = domain.lastIndexOf('.', index3 - 1)) > index2) {
                    String subdomain = domain.substring(0, index3 + 1);
                    if (containsTrapExact(subdomain)) {
                        return true;
                    } else if (containsTrapExact(userEmail + ':' + subdomain)) {
                        return true;
                    }
                }
                int index4 = recipient.length();
                while ((index4 = recipient.lastIndexOf('.', index4 - 1)) > index2) {
                    String subrecipient = recipient.substring(0, index4 + 1);
                    if (containsTrapExact(subrecipient)) {
                        return true;
                    } else if (containsTrapExact(userEmail + ':' + subrecipient)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }

    public static boolean containsInexistent(Client client, User user, String recipient) {
        // Definio do e-mail do usurio.
        String userEmail = null;
        if (user != null) {
            userEmail = user.getEmail();
        } else if (client != null) {
            userEmail = client.getEmail();
        }
        if (userEmail == null) {
            return false;
        } else if (!isValid(recipient)) {
            return false;
        } else {
            recipient = recipient.toLowerCase();
            int index2 = recipient.lastIndexOf('@');
            String domain = recipient.substring(recipient.lastIndexOf('@'));
            if (containsInexistentExact(recipient)) {
                return true;
            } else if (containsInexistentExact(domain)) {
                return true;
            } else if (containsInexistentExact(userEmail + ':' + recipient)) {
                return true;
            } else if (containsInexistentExact(userEmail + ':' + domain)) {
                return true;
            } else {
                int index3 = domain.length();
                while ((index3 = domain.lastIndexOf('.', index3 - 1)) > index2) {
                    String subdomain = domain.substring(0, index3 + 1);
                    if (containsInexistentExact(subdomain)) {
                        return true;
                    } else if (containsInexistentExact(userEmail + ':' + subdomain)) {
                        return true;
                    }
                }
                int index4 = recipient.length();
                while ((index4 = recipient.lastIndexOf('.', index4 - 1)) > index2) {
                    String subrecipient = recipient.substring(0, index4 + 1);
                    if (containsInexistentExact(subrecipient)) {
                        return true;
                    } else if (containsInexistentExact(userEmail + ':' + subrecipient)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }

    public static boolean containsAnything(Client client, User user, String recipient) {
        if (!isValid(recipient)) {
            return false;
        } else {
            recipient = recipient.toLowerCase();
            int index2 = recipient.lastIndexOf('@');
            String domain = recipient.substring(recipient.lastIndexOf('@'));
            String emailClient = client == null ? null : client.getEmail();
            String emailUser = user == null ? null : user.getEmail();
            if (containsAnythingExact(recipient)) {
                return true;
            } else if (containsAnythingExact(domain)) {
                return true;
            } else if (emailClient != null && containsAnythingExact(emailClient + ':' + recipient)) {
                return true;
            } else if (emailClient != null && containsAnythingExact(emailClient + ':' + domain)) {
                return true;
            } else if (emailUser != null && containsAnythingExact(emailUser + ':' + recipient)) {
                return true;
            } else if (emailUser != null && containsAnythingExact(emailUser + ':' + domain)) {
                return true;
            } else {
                int index3 = domain.length();
                while ((index3 = domain.lastIndexOf('.', index3 - 1)) > index2) {
                    String subdomain = domain.substring(0, index3 + 1);
                    if (containsAnythingExact(subdomain)) {
                        return true;
                    } else if (emailClient != null && containsAnythingExact(emailClient + ':' + subdomain)) {
                        return true;
                    } else if (emailUser != null && containsAnythingExact(emailUser + ':' + subdomain)) {
                        return true;
                    }
                }
                int index4 = recipient.length();
                while ((index4 = recipient.lastIndexOf('.', index4 - 1)) > index2) {
                    String subrecipient = recipient.substring(0, index4 + 1);
                    if (containsAnythingExact(subrecipient)) {
                        return true;
                    } else if (emailClient != null && containsAnythingExact(emailClient + ':' + subrecipient)) {
                        return true;
                    } else if (emailUser != null && containsAnythingExact(emailUser + ':' + subrecipient)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }

    public static boolean contaisAnything(String recipient) {
        return getTime(null, null, recipient) != null;
    }

    public static Long getTime(Client client, String recipient) {
        if (client == null) {
            return null;
        } else {
            return getTime(client.getEmail(), recipient);
        }
    }

    public static Long getTime(User user, String recipient) {
        if (user == null) {
            return null;
        } else {
            return getTime(user.getEmail(), recipient);
        }
    }

    public static Long getTime(Client client, User user, String recipient) {
        // Definio do e-mail do usurio.
        String userEmail = null;
        if (user != null) {
            userEmail = user.getEmail();
        } else if (client != null) {
            userEmail = client.getEmail();
        }
        return getTime(userEmail, recipient);
    }

    public static Long getTimeRecipient(Client client, User user, String recipient) {
        if (Domain.isValidEmail(recipient)) {
            Long timeClient = getTime(client, recipient);
            Long timeUser = getTime(user, recipient);
            if (timeClient == null) {
                return timeUser;
            } else if (timeUser == null) {
                return timeClient;
            } else {
                return Math.min(timeClient, timeUser);
            }
        } else {
            return Long.MAX_VALUE;
        }
    }

    public static Long getTime(String userEmail, String recipient) {
        if (!isValid(recipient)) {
            return null;
        } else {
            recipient = recipient.toLowerCase();
            int index2 = recipient.lastIndexOf('@');
            String domain = recipient.substring(recipient.lastIndexOf('@'));
            Long time;
            if ((time = Trap.getTime(recipient)) != null) {
                return time;
            } else if ((time = Trap.getTime(domain)) != null) {
                return time;
            } else if (userEmail != null && (time = Trap.getTime(userEmail + ':' + recipient)) != null) {
                return time;
            } else if (userEmail != null && (time = Trap.getTime(userEmail + ':' + domain)) != null) {
                return time;
            } else {
                int index3 = domain.length();
                while ((index3 = domain.lastIndexOf('.', index3 - 1)) > index2) {
                    String subdomain = domain.substring(0, index3 + 1);
                    if ((time = Trap.getTime(subdomain)) != null) {
                        return time;
                    } else if (userEmail != null && (time = Trap.getTime(userEmail + ':' + subdomain)) != null) {
                        return time;
                    }
                }
                int index4 = recipient.length();
                while ((index4 = recipient.lastIndexOf('.', index4 - 1)) > index2) {
                    String subrecipient = recipient.substring(0, index4 + 1);
                    if ((time = Trap.getTime(subrecipient)) != null) {
                        return time;
                    } else if (userEmail != null && (time = Trap.getTime(userEmail + ':' + subrecipient)) != null) {
                        return time;
                    }
                }
                return null;
            }
        }
    }

    public static void store() {
        if (CHANGED) {
            try {
                //                Server.logTrace("storing trap.map");
                long time = System.currentTimeMillis();
                File file = new File("./data/trap.map");
                HashMap<String, Long> map = getMap();
                FileOutputStream outputStream = new FileOutputStream(file);
                try {
                    SerializationUtils.serialize(map, outputStream);
                    CHANGED = false;
                } finally {
                    outputStream.close();
                }
                Server.logStore(time, file);
            } catch (Exception ex) {
                Server.logError(ex);
            }
        }
    }

    public static void load() {
        long time = System.currentTimeMillis();
        File file = new File("./data/trap.map");
        if (file.exists()) {
            try {
                Map<String, Long> map;
                FileInputStream fileInputStream = new FileInputStream(file);
                try {
                    map = SerializationUtils.deserialize(fileInputStream);
                } finally {
                    fileInputStream.close();
                }
                for (String token : map.keySet()) {
                    Long time2 = map.get(token);
                    putExact(token, time2);
                }
                CHANGED = false;
                Server.logLoad(time, file);
            } catch (Exception ex) {
                Server.logError(ex);
            }
        }
    }
}