Package jnode.ftn

Source Code of jnode.ftn.FtnTools

/*
* Licensed to the jNode FTN Platform Develpoment Team (jNode Team)
* under one or more contributor license agreements.
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. 
* The jNode Team licenses this file to you under the
* Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package jnode.ftn;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import jnode.core.ConcurrentDateFormatAccess;
import jnode.core.FileUtils;
import jnode.dto.Echoarea;
import jnode.dto.Echomail;
import jnode.dto.EchomailAwaiting;
import jnode.dto.FileForLink;
import jnode.dto.FileSubscription;
import jnode.dto.Filearea;
import jnode.dto.Filemail;
import jnode.dto.FilemailAwaiting;
import jnode.dto.Link;
import jnode.dto.LinkOption;
import jnode.dto.Netmail;
import jnode.dto.Rewrite;
import jnode.dto.Robot;
import jnode.dto.Route;
import jnode.dto.Subscription;
import jnode.event.NewEchoareaEvent;
import jnode.event.NewFileareaEvent;
import jnode.event.Notifier;
import jnode.ftn.tosser.FtnTosser;
import jnode.ftn.types.Ftn2D;
import jnode.ftn.types.FtnAddress;
import jnode.ftn.types.FtnMessage;
import jnode.ftn.types.FtnPkt;
import jnode.logger.Logger;
import jnode.main.MainHandler;
import jnode.main.threads.PollQueue;
import jnode.main.threads.TosserQueue;
import jnode.ndl.FtnNdlAddress;
import jnode.ndl.FtnNdlAddress.Status;
import jnode.ndl.NodelistScanner;
import jnode.orm.ORMManager;
import jnode.protocol.io.Message;
import jnode.robot.IRobot;

/**
* Сборник всякой хрени
*
* @author kreon
*
*/
public final class FtnTools {
  private static final String BINKP_INBOUND = "binkp.inbound";
  private static final String NETMAIL_VALID = "netmail.only_valid";
  private static final String SEEN_BY = "SEEN-BY:";
  private static final String PATH = "\001PATH:";
  public static final Charset CP_866 = Charset.forName("CP866");
  private static final String ROUTE_VIA = "\001Via %s "
      + MainHandler.getVersion() + " %s";
  public static final ConcurrentDateFormatAccess FORMAT = new ConcurrentDateFormatAccess(
      "EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
  private static final Logger logger = Logger.getLogger(FtnTools.class);

  private static final Hashtable<String, IRobot> robotMaps = new Hashtable<>();

  /**
   * Сортировщик 2D-адресов
   *
   * @author kreon
   *
   */
  public static class Ftn2DComparator implements Comparator<Ftn2D> {

    @Override
    public int compare(Ftn2D o1, Ftn2D o2) {
      if (o1.getNet() == o2.getNet()) {
        return o1.getNode() - o2.getNode();
      } else {
        return o1.getNet() - o2.getNet();
      }
    }
  }

  /**
   * Сортировщик 4D-адресов
   *
   * @author kreon
   *
   */
  public static class Ftn4DComparator implements Comparator<FtnAddress> {

    @Override
    public int compare(FtnAddress o1, FtnAddress o2) {
      if (o1.getZone() == o2.getZone()) {
        if (o1.getNet() == o2.getNet()) {
          if (o1.getNode() == o2.getNode()) {
            if (o1.getPoint() == o2.getPoint()) {
              return 0;
            } else {
              return o1.getPoint() - o2.getPoint();
            }
          } else {
            return o1.getNode() - o2.getNode();
          }
        } else {
          return o1.getNet() - o2.getNet();
        }
      } else {
        return o1.getZone() - o2.getZone();
      }
    }
  }

  /**
   * Генерация 8d-рандома
   *
   * @return
   */
  public static String generate8d() {
    byte[] digest = new byte[4];
    for (int i = 0; i < 4; i++) {
      long a = Math.round(Integer.MAX_VALUE * Math.random());
      long b = Math.round(Integer.MIN_VALUE * Math.random());
      long c = a ^ b;
      byte d = (byte) ((c >> 12) & 0xff);
      digest[i] = d;
    }
    return String.format("%02x%02x%02x%02x", digest[0], digest[1],
        digest[2], digest[3]);
  }

  public static String generateTic() {
    char[] chars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i',
        'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
        'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
        '7', '8', '9' };
    StringBuilder sb = new StringBuilder(11);
    sb.append("jt");
    for (int i = 0; i < 6; i++) {
      sb.append(chars[(int) Math.round((chars.length - 1) * Math.random())]);
    }
    sb.append(".tic");
    return sb.toString();
  }

  /**
   * Big-Endian -> Little-Endian
   *
   * @param v
   * @return
   */
  public static short revShort(short v) {
    return (short) ((short) ((short) (v >> 8) & 0xff) | (short) (v << 8));
  }

  /**
   * Подстрока в виде байтов и в cp866
   *
   * @param s
   * @param len
   * @return
   */
  public static byte[] substr(String s, int maxlen) {
    byte[] bytes = s.getBytes(CP_866);
    int len = (bytes.length > maxlen) ? maxlen : bytes.length;
    byte[] ret = new byte[len];
    for (int i = 0; i < len; i++) {
      ret[i] = bytes[i];
    }
    return ret;
  }

  /**
   * Читаем пакет пока не встретим \0
   *
   * @param is
   * @return
   */
  public static String readUntillNull(InputStream is) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream(1);
    int b;
    try {
      while ((b = is.read()) != 0) {
        bos.write(b);
      }
    } catch (IOException e) {
      //
    }
    return new String(bos.toByteArray(), CP_866);
  }

  /**
   * Превращает строки синбаев в лист 2D адресов
   *
   * @param seenByLines
   * @return
   */
  public static List<Ftn2D> readSeenBy(String seenByLines) {
    List<Ftn2D> seen = new ArrayList<>();
    String[] seenBy = seenByLines.split("[ \n]");
    int net = 0;
    for (String parts : seenBy) {
      if (parts == null || parts.length() < 1 || parts.equals(SEEN_BY)) {
        continue;
      } else {

        try {
          String[] part = parts.split("/");
          int node;
          if (part.length == 2) {
            net = Integer.valueOf(part[0]);
            node = Integer.valueOf(part[1]);
          } else {
            node = Integer.valueOf(part[0]);
          }
          seen.add(new Ftn2D(net, node));
        } catch (NumberFormatException e) {
          logger.l2(MessageFormat.format(
              "Error: fail write seen {0} for lines {1}", parts,
              seenByLines), e);
        }

      }
    }
    return seen;
  }

  /**
   * Превращает лист синбаев в строку для добавления в письмо
   *
   * @param seenby
   * @return
   */
  public static String writeSeenBy(List<Ftn2D> seenby) {
    logger.l5("WriteSeenBy: " + seenby);
    StringBuilder ret = new StringBuilder();
    Collections.sort(seenby, new Ftn2DComparator());
    int net = 0;
    int linelen = 0;
    for (Ftn2D ftn : seenby) {
      if (linelen >= 72) {
        linelen = 0;
        net = 0;
        ret.append("\n");
      }
      if (linelen == 0) {
        ret.append(SEEN_BY);
        linelen += SEEN_BY.length();
      }
      if (net != ftn.getNet()) {
        net = ftn.getNet();
        String app = String.format(" %d/%d", ftn.getNet(),
            ftn.getNode());
        ret.append(app);
        linelen += app.length();
      } else {
        String app = String.format(" %d", ftn.getNode());
        ret.append(app);
        linelen += app.length();
      }
    }
    if (ret.length() == 0) {
      return "";
    }
    if (ret.charAt(ret.length() - 1) != '\n') {
      ret.append('\n');
    }
    return ret.toString();
  }

  /**
   * Превращает путь в List
   *
   * @param seenByLines
   * @return
   */
  public static List<Ftn2D> readPath(String seenByLines) {
    List<Ftn2D> seen = new ArrayList<>();
    String[] seenBy = seenByLines.split("[ \n]");
    int net = 0;
    for (String parts : seenBy) {
      if (parts == null || parts.length() < 1 || parts.equals(PATH)) {
        continue;
      } else {
        String[] part = parts.split("/");
        int node;
        if (part.length == 2) {
          net = Integer.valueOf(part[0]);
          node = Integer.valueOf(part[1]);
        } else {
          node = Integer.valueOf(part[0]);
        }
        seen.add(new Ftn2D(net, node));
      }
    }
    return seen;
  }

  /**
   * Превращает List в путь
   *
   * @param path
   * @return
   */
  public static String writePath(List<Ftn2D> path) {
    logger.l5("WritePath: " + path);
    StringBuilder ret = new StringBuilder();
    int net = 0;
    int linelen = 0;
    for (Ftn2D ftn : path) {
      if (linelen >= 72) {
        linelen = 0;
        net = 0;
        ret.append("\n");
      }
      if (linelen == 0) {
        ret.append(PATH);
        linelen += PATH.length();
      }
      if (net != ftn.getNet()) {
        net = ftn.getNet();
        String app = String.format(" %d/%d", ftn.getNet(),
            ftn.getNode());
        ret.append(app);
        linelen += app.length();
      } else {
        String app = String.format(" %d", ftn.getNode());
        ret.append(app);
        linelen += app.length();
      }
    }
    if (ret.length() == 0) {
      return "";
    }
    if (ret.charAt(ret.length() - 1) != '\n') {
      ret.append('\n');
    }
    return ret.toString();
  }

  /**
   * Читаем 2d-адреса через разделитель
   *
   * @param list2d
   * @return
   */
  public static List<Ftn2D> read2D(String list2d) {
    List<Ftn2D> ret = new ArrayList<>();

    if (list2d == null || list2d.length() == 0
        || list2d.trim().length() == 0) {
      return ret;
    }

    String lastNet = null;

    for (String l2d : list2d.split(" ")) {
      String[] part = l2d.split("/");

      String net;
      String node;

      switch (part.length) {
      case 2:
        // 5020/841
        net = part[0];
        node = part[1];
        break;
      case 1:
        // 841
        net = lastNet;
        node = part[0];
        break;
      default:
        throw new IllegalArgumentException(MessageFormat.format(
            "fail parse 2d address [{0}] in list [{1}]", l2d,
            list2d));
      }

      try {
        ret.add(Ftn2D.fromString(net, node));
        lastNet = net;
      } catch (IllegalArgumentException e) {
        lastNet = null;
        logger.l1(
            MessageFormat
                .format("fail parse 2d address [{0}] in list [{1}] - illegal arguments",
                    l2d, list2d), e);
      } catch (RuntimeException e2) {
        lastNet = null;
        logger.l1(
            MessageFormat
                .format("fail parse 2d address [{0}] in list [{1}] - unexpected error",
                    l2d, list2d), e2);
      }
    }
    return ret;
  }

  /**
   * Читаем 4d-адреса через разделитель
   *
   * @param list2d
   * @return
   */
  public static List<FtnAddress> read4D(String list2d) {
    List<FtnAddress> ret = new ArrayList<>();
    for (String l2d : list2d.split(" ")) {
      try {
        ret.add(new FtnAddress(l2d));
      } catch (RuntimeException e) {
      }
    }
    return ret;
  }

  /**
   * Пишем 2d-адреса через разделитель
   *
   * @param list
   * @param sort
   * @return
   */
  public static String write2D(List<Ftn2D> list, boolean sort) {
    StringBuilder ret = new StringBuilder();
    if (sort) {
      Collections.sort(list, new Ftn2DComparator());
    }
    boolean flag = false;
    for (Ftn2D d : list) {
      if (flag) {
        ret.append(" ");
      } else {
        flag = true;
      }
      ret.append(String.format("%d/%d", d.getNet(), d.getNode()));
    }
    return ret.toString();
  }

  /**
   * Пишем 4d-адреса через разделитель
   *
   * @param list
   * @return
   */
  public static String write4D(List<FtnAddress> list) {
    StringBuilder ret = new StringBuilder();

    boolean flag = false;
    for (FtnAddress d : list) {
      if (flag) {
        ret.append(" ");
      } else {
        flag = true;
      }
      ret.append(d.toString());
    }
    return ret.toString();
  }

  /**
   * Опции для линков
   *
   * @param link
   * @param option
   * @return
   */
  public static String getOption(Link link, String option) {
    String value = "";
    if (link.getId() != null) {
      LinkOption opt = ORMManager.get(LinkOption.class).getFirstAnd(
          "link_id", "=", link, "name", "=", option.toLowerCase());
      if (opt != null) {
        value = opt.getValue();
      }
    }
    return value;
  }

  public static String getOptionString(Link link, String option) {
    return getOption(link, option);
  }

  public static boolean getOptionBooleanDefFalse(Link link, String option) {
    String s = getOption(link, option);
    return s.equalsIgnoreCase("TRUE") || s.equalsIgnoreCase("ON");
  }

  public static boolean getOptionBooleanDefTrue(Link link, String option) {
    String s = getOption(link, option);
    return !(s.equalsIgnoreCase("FALSE") || s.equalsIgnoreCase("OFF"));
  }

  public static long getOptionLong(Link link, String option) {
    String s = getOption(link, option);
    long ret = 0;
    try {
      ret = Long.valueOf(s);
    } catch (NumberFormatException ignore) {
    }
    return ret;
  }

  public static String[] getOptionStringArray(Link link, String option) {
    String s = getOption(link, option);
    return s.split(" ");
  }

  /**
   * Конвертер
   *
   * @param mail
   * @return
   */
  public static FtnMessage netmailToFtnMessage(Netmail mail) {
    FtnMessage message = new FtnMessage();
    message.setNetmail(true);
    message.setFromName(mail.getFromName());
    message.setToName(mail.getToName());
    message.setFromAddr(new FtnAddress(mail.getFromFTN()));
    message.setToAddr(new FtnAddress(mail.getToFTN()));
    message.setDate(mail.getDate());
    message.setSubject(mail.getSubject());
    message.setAttribute(mail.getAttr());
    StringBuilder text = new StringBuilder();
    text.append(mail.getText());
    if (text.charAt(text.length() - 1) != '\n') {
      text.append('\n');
    }
    for (FtnAddress address : MainHandler.getCurrentInstance().getInfo()
        .getAddressList()) {
      text.append(String.format(ROUTE_VIA, address.toString(),
          FORMAT.format(new Date())));
    }
    message.setText(text.toString());
    return message;
  }

  /**
   * Конвертер
   *
   * @param mail
   * @return
   */
  public static Netmail ftnMessageToNetmail(FtnMessage mail) {
    Netmail netmail = new Netmail();
    netmail.setAttr(mail.getAttribute());
    netmail.setDate(mail.getDate());
    netmail.setFromFTN(mail.getFromAddr().toString());
    netmail.setFromName(mail.getFromName());
    netmail.setToFTN(mail.getToAddr().toString());
    netmail.setToName(mail.getToName());
    netmail.setSubject(mail.getSubject());
    netmail.setText(mail.getText());
    return netmail;
  }

  /**
   * Распаковка из зип-архива
   *
   * @param message
   * @return
   */
  public static void unpack(Message message) throws IOException {
    String filename = message.getMessageName().toLowerCase();
    if (filename.matches("^[a-f0-9]{8}\\.pkt$")) {
      File out = createInboundFile(message.isSecure());
      FileOutputStream fos = new FileOutputStream(out);
      int len = 0;
      do {
        byte[] buf = new byte[1024];
        len = message.getInputStream().read(buf);
        if (len > 0) {
          fos.write(buf, 0, len);
        }
      } while (len > 0);
      fos.close();
    } else if (filename
        .matches("^\\w{8}\\.(mo|tu|we|th|fr|sa|su)[0-9a-z]$")) {
      unpackBundle(message);
    } else if (message.isSecure()) {
      File f = guessFilename(filename, false);
      if (f != null) {
        FileOutputStream fos = new FileOutputStream(f);
        int len = 0;
        do {
          byte[] buf = new byte[1024];
          len = message.getInputStream().read(buf);
          if (len > 0) {
            fos.write(buf, 0, len);
          }
        } while (len > 0);
        fos.close();
        logger.l3("File saved " + f.getAbsolutePath() + " ("
            + f.length() + ")");
      }
    } else {
      logger.l2("File rejected via unsecure " + filename);
    }
  }

  protected static void unpackBundle(Message message) throws IOException {
    logger.l4("Unpacking " + message.getMessageName());
    ZipInputStream zis = new ZipInputStream(message.getInputStream());
    ZipEntry ze;
    while ((ze = zis.getNextEntry()) != null) {
      String name = ze.getName().toLowerCase();
      logger.l5("found " + name);
      int idx = name.lastIndexOf('/');
      if (idx >= 0) {
        name = name.substring(idx + 1);
      }
      idx = name.lastIndexOf('\\');
      if (idx >= 0) {
        name = name.substring(idx + 1);
      }
      if (name.matches("^[a-f0-9]{8}\\.pkt$")) {
        File out = createInboundFile(message.isSecure());
        FileOutputStream fos = new FileOutputStream(out);
        int len = 0;
        do {
          byte[] buf = new byte[1024];
          len = zis.read(buf);
          if (len > 0) {
            fos.write(buf, 0, len);
          }
        } while (len > 0);
        fos.close();
        logger.l4(name + " was written as " + out.getName());
      } else {
        logger.l3(name + " was deleted as unknown");
      }
    }
    zis.close();
  }

  public static File guessFilename(String filename, boolean read) {
    filename = filename.replaceAll("^[\\./\\\\]+", "_");
    File f = new File(getInbound() + File.separator + filename);
    boolean ninetoa = false;
    boolean ztonull = false;
    boolean underll = false;
    while ((read) ? !f.exists() : f.exists()) {
      if ((ninetoa && ztonull) || underll) {
        logger.l4(read ? "Files not found"
            : "Delete something to continue");
        f = null;
        break;
      } else {
        char[] array = filename.toCharArray();
        char c = array[array.length - 1];
        if ((c >= '0' && c <= '8') || (c >= 'a' && c <= 'y')) {
          c++;
        } else if (c == '9') {
          c = 'a';
          ninetoa = true;
        } else if (c == 'z') {
          c = '0';
          ztonull = true;
        } else {
          c = '_';
          underll = true;
        }
        array[array.length - 1] = c;
        filename = new String(array);
        f = new File(getInbound() + File.separator + filename);
      }
    }
    return f;
  }

  /**
   * Проверка соответствия маски :)
   *
   * @param route
   * @param message
   * @return
   */
  public static boolean completeMask(Route route, FtnMessage message) {
    boolean ok = true;
    String[] regexp = new String[] { route.getFromAddr(),
        route.getToAddr(), route.getFromName(), route.getToName(),
        route.getSubject() };
    String[] check = new String[] { message.getFromAddr().toString(),
        message.getToAddr().toString(), message.getFromName(),
        message.getToName(), message.getSubject() };
    for (int i = 0; i < 5; i++) {
      if (regexp[i] != null && !regexp[i].equals("*")) {
        logger.l5("Checks " + check[i] + " via regexp " + regexp[i]);
        if (check[i] == null || !check[i].matches(regexp[i])) {
          ok = false;
        }
      }
    }
    return ok;
  }

  /**
   * Проверка соответствия маски :)
   *
   * @param rewrite
   * @param message
   * @return
   */
  public static boolean completeMask(Rewrite rewrite, FtnMessage message) {
    boolean ok = true;
    String[] regexp = new String[] { rewrite.getOrig_from_addr(),
        rewrite.getOrig_to_addr(), rewrite.getOrig_from_name(),
        rewrite.getOrig_to_name(), rewrite.getOrig_subject() };
    String[] check = new String[] { message.getFromAddr().toString(),
        message.getToAddr().toString(), message.getFromName(),
        message.getToName(), message.getSubject() };
    for (int i = 0; i < 5; i++) {
      if (regexp[i] != null && !regexp[i].equals("*")) {
        logger.l5("Checks " + check[i] + " via " + regexp[i]);
        if (check[i] == null || !check[i].matches(regexp[i])) {
          ok = false;
        }
      }
    }
    return ok;
  }

  /**
   * Перезапись сообщения
   *
   * @param rewrite
   * @param message
   * @return
   */
  public static void rewrite(Rewrite rewrite, FtnMessage message) {
    String[] fields = new String[] { rewrite.getNew_from_addr(),
        rewrite.getNew_to_addr(), rewrite.getNew_from_name(),
        rewrite.getNew_to_name(), rewrite.getNew_subject() };
    for (int i = 0; i < 5; i++) {
      if (fields[i] != null && !fields[i].equals("*")) {
        switch (i) {
        case 0:
          FtnAddress nfa = new FtnAddress(fields[i]);
          if (message.getMsgid() != null) {
            Matcher msgid = Pattern.compile(
                "^" + message.getFromAddr() + " (\\S+)$")
                .matcher(message.getMsgid());
            if (msgid.find()) {
              String msg = msgid.replaceFirst(nfa + " $1");
              message.setText(message.getText().replace(
                  message.getMsgid(), msg));
              message.setMsgid(msg);

            }
          } // TODO : netmail msgid
          Matcher origin = Pattern.compile(
              "^ \\* Origin: (.*) \\(" + message.getFromAddr()
                  + "\\)$", Pattern.MULTILINE).matcher(
              message.getText());
          if (origin.find()) {
            message.setText(origin.replaceFirst(" * Origin: $1 ("
                + nfa + ")"));
          }
          message.setFromAddr(nfa);
          logger.l5("Rewrite fromAddr to " + fields[i]);
          break;
        case 1:
          message.setToAddr(new FtnAddress(fields[i]));
          logger.l5("Rewrite toAddr to " + fields[i]);
          break;
        case 2:
          message.setFromName(fields[i]);
          logger.l5("Rewrite fromAddr to " + fields[i]);
          break;
        case 3:
          message.setToName(fields[i]);
          logger.l5("Rewrite fromAddr to " + fields[i]);
          break;
        case 4:
          message.setSubject(fields[i]);
          logger.l5("Rewrite fromAddr to " + fields[i]);
          break;
        }
      }
    }
  }

  /**
   * Проверям сообщение на соответствие роботу
   *
   * @param message
   * @return
   */
  public static boolean checkRobot(FtnMessage message) {
    boolean isRobot = false;
    String robotname = "";
    if (message.isNetmail()) {
      if (MainHandler.getCurrentInstance().getInfo().getAddressList()
          .contains(message.getToAddr())) {
        // TODO: optiomize
        IRobot oRobot = robotMaps
            .get(message.getToName().toLowerCase());
        if (oRobot == null) {
          try {
            Robot robot = ORMManager.get(Robot.class).getById(
                message.getToName().toLowerCase());
            if (robot != null) {
              robotname = robot.getRobot();
              Class<?> clazz = Class
                  .forName(robot.getClassName());
              oRobot = (IRobot) clazz.newInstance();
              robotMaps.put(robotname, oRobot);
              logger.l4("Message " + message.getMsgid()
                  + " sent to robot " + robotname);
            }
          } catch (ClassNotFoundException e) {
            logger.l2("Robot class not found (INIT) " + robotname,
                e);
          } catch (Exception e) {
            logger.l2(
                "Robot excception  " + robotname + " (INIT) ",
                e);
          }
        }
        if (oRobot != null) {
          isRobot = true;
          try {
            oRobot.execute(message);
          } catch (Exception e) {
            logger.l2("Robot excception  " + robotname
                + " (PROCCESS) ", e);
          }
        }
      }
    }
    return isRobot;
  }

  /**
   * Получаем роутинг для нетмейла
   *
   * @param message
   * @return
   */
  public static Link getRouting(FtnMessage message) {
    Link routeVia;
    FtnAddress routeTo = message.getToAddr().clone();
    routeVia = getLinkByFtnAddress(routeTo);
    // check our point
    if (!isOurPoint(routeTo)) {
      routeTo.setPoint(0);
      routeVia = getLinkByFtnAddress(routeTo);
      // а теперь - по роутингу
      if (routeVia == null) {
        List<Route> routes = ORMManager.get(Route.class).getOrderAnd(
            "nice", true);
        for (Route route : routes) {
          if (completeMask(route, message)) {
            routeVia = route.getRouteVia();
            break;
          }
        }
      }
    }
    return routeVia;
  }

  public static Link getRoutingFallback(FtnMessage message,
      Link previousRouteVia) {
    Link routeVia = null;
    FtnAddress routeTo = message.getToAddr().clone();
    if (isOurPoint(routeTo)) {
      return null;
    }
    // direct link can be down for us - use cross way
    List<Route> routes = ORMManager.get(Route.class).getOrderAnd("nice",
        true);
    for (Route route : routes) {
      if (completeMask(route, message)) {
        if (route.getRouteVia().equals(previousRouteVia)) {
          continue;
        }
        routeVia = route.getRouteVia();
        break;
      }
    }
    if (routeVia == null) {
      routeVia = previousRouteVia;
    }
    return routeVia;
  }

  public static Link getLinkByFtnAddress(FtnAddress addr) {
    return ORMManager.get(Link.class).getFirstAnd("ftn_address", "=",
        addr.toString());
  }

  public static Link getLinkByFtnAddress(List<FtnAddress> addrs) {
    List<String> saddrs = new ArrayList<>();
    for (FtnAddress a : addrs) {
      saddrs.add(a.toString());
    }
    return ORMManager.get(Link.class).getFirstAnd("ftn_address", "in",
        saddrs);
  }

  public static boolean isOurPoint(FtnAddress routeTo) {
    boolean ourPoint = false;
    for (FtnAddress testAddress : MainHandler.getCurrentInstance()
        .getInfo().getAddressList()) {
      if (routeTo.isPointOf(testAddress)) {
        ourPoint = true;
        break;
      }
    }
    return ourPoint;
  }

  /**
   * Пишем ответ на нетмейл
   *
   * @param fmsg
   * @param subject
   * @param text
   * @throws SQLException
   */
  public static void writeReply(FtnMessage fmsg, String subject, String text) {
    FtnAddress from = getPrimaryFtnAddress();
    StringBuilder sb = new StringBuilder();
    if (fmsg.getMsgid() != null) {
      sb.append("\001REPLY: " + fmsg.getMsgid() + "\n");
    }
    sb.append(text);
    sb.append(quote(fmsg));
    writeNetmail(from, fmsg.getFromAddr(), fmsg.getToName(),
        fmsg.getFromName(), subject, sb.toString());
  }

  public static String quote(FtnMessage fmsg) {
    StringBuilder sb = new StringBuilder();
    sb.append("\n\n========== Original message ==========\n");
    sb.append("From: " + fmsg.getFromName() + " (" + fmsg.getFromAddr()
        + ")\n");
    if (fmsg.isNetmail()) {
      sb.append("To: " + fmsg.getToName() + " (" + fmsg.getToAddr()
          + ")\n");
    } else {
      sb.append("Area: " + fmsg.getArea() + "\nTo: " + fmsg.getToName()
          + "\n");
    }
    sb.append("Date: " + fmsg.getDate() + "\n");
    sb.append("Subject: " + fmsg.getSubject() + "\n");
    if (fmsg.getText() != null) {
      sb.append(fmsg.getText().replaceAll("\001", "@")
          .replaceAll("---", "+++")
          .replaceAll(" \\* Origin:", " + Origin:"));
    }
    sb.append("========== Original message ==========\n");
    return sb.toString();
  }

  public static void writeNetmail(FtnAddress from, FtnAddress to,
      String fromName, String toName, String subject, String text) {
    writeNetmail(from, to, fromName, toName, subject, text, 0, true);
  }

  /**
   * Создание нетмейла
   *
   * @param from
   * @param to
   * @param fromName
   * @param toName
   * @param subject
   * @param text
   */
  public static void writeNetmail(FtnAddress from, FtnAddress to,
      String fromName, String toName, String subject, String text,
      int attr, boolean route) {
    FtnMessage message = new FtnMessage();

    StringBuilder sb = new StringBuilder();
    sb.append(String.format("\001MSGID: %s %s\n\001PID: %s\n\001TID: %s\n",
        from.toString(), generate8d(), MainHandler.getVersion(),
        MainHandler.getVersion()));
    sb.append(text);
    sb.append("\n\n--- " + MainHandler.getVersion() + "\n");
    message.setDate(new Date());
    message.setToAddr(to);
    message.setFromAddr(from);
    message.setToName(toName);
    message.setFromName(fromName);
    message.setSubject(subject);
    message.setText(sb.toString());
    message.setNetmail(true);
    message.setAttribute(attr);
    processRewrite(message);
    Link routeVia = null;
    if (route) {
      routeVia = getRouting(message);
      if (routeVia == null) {
        logger.l2("Routing not found for " + to);
      }
    }
    Netmail net = ftnMessageToNetmail(message);
    net.setRouteVia(routeVia);
    ORMManager.get(Netmail.class).save(net);
    logger.l4("Netmail #" + net.getId() + " created");
    if (routeVia != null) {
      if (FtnTools.getOptionBooleanDefTrue(routeVia,
          LinkOption.BOOLEAN_CRASH_NETMAIL)) {
        PollQueue.getSelf().add(routeVia);
      }
    }
  }

  public static File createOutboundFile(Link link) {
    String template;
    if (link != null && link.getId() != null) {
      template = "out_" + link.getId() + ".%d";
    } else {
      template = "out_random.%d";
    }
    int i = 0;
    File f = new File(getInbound() + File.separator
        + String.format(template, i));
    while (f.exists()) {
      i++;
      f = new File(getInbound() + File.separator
          + String.format(template, i));
    }
    return f;
  }

  private static File createInboundFile(boolean secure) {
    String template = ((secure) ? "s" : "u") + "inb%d.pkt";
    int i = 0;
    File f = new File(getInbound() + File.separator
        + String.format(template, i));
    while (f.exists()) {
      i++;
      f = new File(getInbound() + File.separator
          + String.format(template, i));
    }
    return f;
  }

  public static String getInbound() {
    return MainHandler.getCurrentInstance().getProperty(BINKP_INBOUND,
        System.getProperty("file.tmp"));
  }

  private static File createZipFile(FtnPkt header, Link link,
      List<FtnMessage> messages) throws IOException {
    File np = createOutboundFile(link);
    FileOutputStream out = new FileOutputStream(np);
    ZipOutputStream zos = new ZipOutputStream(out);
    zos.setMethod(ZipOutputStream.DEFLATED);
    ZipEntry ze = new ZipEntry(String.format("%s.pkt", generate8d()));
    ze.setMethod(ZipEntry.DEFLATED);
    CRC32 crc32 = new CRC32();
    zos.putNextEntry(ze);
    int len = 0;
    byte[] data = header.pack();
    len += data.length;
    crc32.update(data);
    zos.write(data);
    for (FtnMessage m : messages) {
      data = m.pack();
      len += data.length;
      crc32.update(data);
      zos.write(data);
    }
    data = header.finalz();
    len += data.length;
    crc32.update(data);
    zos.write(data);
    ze.setSize(len);
    ze.setCrc(crc32.getValue());
    zos.close();
    out.close();
    return np;
  }

  /**
   * Эхобандл
   *
   * @return
   */
  public static String generateEchoBundle() {
    String suffix = "";
    switch (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)) {
    case Calendar.MONDAY:
      suffix = "mo";
      break;
    case Calendar.TUESDAY:
      suffix = "tu";
      break;
    case Calendar.WEDNESDAY:
      suffix = "we";
      break;
    case Calendar.THURSDAY:
      suffix = "th";
      break;
    case Calendar.FRIDAY:
      suffix = "fr";
      break;
    case Calendar.SATURDAY:
      suffix = "sa";
      break;
    case Calendar.SUNDAY:
      suffix = "su";
      break;
    }
    int d = (int) (Math.random() * 9);
    return generate8d() + "." + suffix + d;
  }

  /**
   * Паковка сообщений На удаление !
   *
   * @param messages
   * @param link
   * @return
   */
  @Deprecated
  protected static List<Message> pack(List<FtnMessage> messages, Link link) {
    boolean packNetmail = getOptionBooleanDefFalse(link,
        LinkOption.BOOLEAN_PACK_NETMAIL);
    boolean packEchomail = getOptionBooleanDefTrue(link,
        LinkOption.BOOLEAN_PACK_ECHOMAIL);

    List<Message> ret = new ArrayList<>();
    List<FtnMessage> packedEchomail = new ArrayList<>();
    List<FtnMessage> unpackedEchomail = new ArrayList<>();
    List<FtnMessage> packedNetmail = new ArrayList<>();
    List<FtnMessage> unpackedNetmail = new ArrayList<>();
    FtnAddress to = new FtnAddress(link.getLinkAddress());
    String password = link.getPaketPassword();
    FtnPkt header = new FtnPkt(selectOurAka(link), to, password, new Date());

    for (FtnMessage message : messages) {
      if (message.isNetmail()) {
        if (packNetmail) {
          packedNetmail.add(message);
        } else {
          unpackedNetmail.add(message);
        }
      } else {
        if (packEchomail) {
          packedEchomail.add(message);
        } else {
          unpackedEchomail.add(message);
        }
      }
    }

    if (!packedNetmail.isEmpty()) {

      try {
        for (FtnMessage net : packedNetmail) {
          FtnPkt head = new FtnPkt(header.getFromAddr(), to,
              password, new Date());
          Message m = new Message(createZipFile(head, link,
              Arrays.asList(net)));
          m.setMessageName(generateEchoBundle());
          ret.add(m);
        }
      } catch (Exception e) {
        logger.l1(
            "Error while writing netmail to link #" + link.getId(),
            e);
      }

    }
    if (!packedEchomail.isEmpty()) {
      try {
        Message m = new Message(createZipFile(header, link,
            packedEchomail));
        m.setMessageName(generateEchoBundle());
        ret.add(m);
      } catch (Exception e) {
        logger.l1(
            "Error while writing echomail to link #" + link.getId(),
            e);
      }
    }
    if (!unpackedNetmail.isEmpty()) {
      try {
        for (FtnMessage net : unpackedNetmail) {
          FtnPkt head = new FtnPkt(header.getFromAddr(), to,
              password, new Date());
          File out = createOutboundFile(link);
          FileOutputStream fos = new FileOutputStream(out);
          fos.write(head.pack());
          fos.write(net.pack());
          fos.write(head.finalz());
          fos.close();
          Message m = new Message(out);
          m.setMessageName(generate8d() + ".pkt");
          ret.add(m);
        }
      } catch (Exception e) {
        logger.l1(
            "Error while writing netmail to link #" + link.getId(),
            e);
      }
    }
    if (!unpackedEchomail.isEmpty()) {
      try {
        File out = createOutboundFile(link);
        FileOutputStream fos = new FileOutputStream(out);
        fos.write(header.pack());
        for (FtnMessage m : unpackedEchomail) {
          fos.write(m.pack());
        }
        fos.write(header.finalz());
        fos.close();
        Message m = new Message(out);
        m.setMessageName(generate8d() + ".pkt");
        ret.add(m);
      } catch (Exception e) {
        logger.l1(
            "Error while writing netmail to link #" + link.getId(),
            e);
      }
    }

    return ret;
  }

  public static FtnAddress selectOurAka(Link link) {
    if (MainHandler.getCurrentInstance().getInfo().getAddressList().size() < 2) {
      return getPrimaryFtnAddress();
    }
    FtnAddress ret = getPrimaryFtnAddress();
    FtnAddress addr = new FtnAddress(link.getLinkAddress());
    if (addr.getPoint() > 0) {
      for (FtnAddress address : MainHandler.getCurrentInstance()
          .getInfo().getAddressList()) {
        if (addr.isPointOf(address)) { // если это пойнт - то
                        // посылаем с того
                        // адреса, на
                        // который он
                        // привязан
          ret = address;
          break;
        }
      }
    } else {
      String ourAka = FtnTools.getOption(link, LinkOption.STRING_OUR_AKA);
      if (ourAka != null) {
        try {
          FtnAddress _our = new FtnAddress(ourAka);
          if (MainHandler.getCurrentInstance().getInfo()
              .getAddressList().contains(_our)) {
            ret = _our;
          }
        } catch (NumberFormatException e) {
        }
      }
    }
    logger.l5("Using aka " + ret + " for " + link.getLinkAddress() + "");
    return ret;
  }

  public static String getOptionForAddr(FtnAddress toAddr, String name) {
    Link link = getLinkByFtnAddress(toAddr);
    if (link != null) {
      return getOption(link, name);
    }
    return null;
  }

  /**
   * Кривые пакеты - в инбаунд -- на удаление
   *
   * @param pkt
   */
  @Deprecated
  protected static void moveToBad(FtnPkt pkt) {
    ByteArrayInputStream bis = new ByteArrayInputStream(pkt.pack());
    Message message = new Message(String.format("%s_%d.pkt", generate8d(),
        new Date().getTime() / 1000), bis.available());
    message.setInputStream(bis);
    try {
      unpack(message);
    } catch (IOException e) {
      logger.l2("fail move to bad", e);
    }
  }

  /**
   * Делаем реврайт
   *
   * @param message
   */
  public static void processRewrite(FtnMessage message) {
    List<Rewrite> rewrites = ORMManager.get(Rewrite.class).getOrderAnd(
        "nice",
        true,
        "type",
        "=",
        (message.isNetmail()) ? (Rewrite.Type.NETMAIL)
            : (Rewrite.Type.ECHOMAIL));
    for (Rewrite rewrite : rewrites) {
      if (FtnTools.completeMask(rewrite, message)) {
        logger.l5(((message.isNetmail()) ? "NET" : "ECH")
            + " - match found, rewriting " + message.getMsgid());
        rewrite(rewrite, message);
        if (rewrite.isLast()) {
          break;
        }
      }
    }
  }

  /**
   * получение и аутокриейт
   *
   * @param name
   * @param link
   * @return
   */
  public static Echoarea getAreaByName(String name, Link link) {
    Echoarea ret;
    name = name.toLowerCase();
    ret = ORMManager.get(Echoarea.class).getFirstAnd("name", "=", name);
    if (ret == null) {
      if (link == null
          || getOptionBooleanDefFalse(link,
              LinkOption.BOOLEAN_AUTOCREATE_AREA)) {
        ret = new Echoarea();
        ret.setName(name);
        ret.setDescription("Autocreated echoarea");
        ret.setReadlevel((link != null) ? getOptionLong(link,
            LinkOption.LONG_LINK_LEVEL) : 0);
        ret.setWritelevel((link != null) ? getOptionLong(link,
            LinkOption.LONG_LINK_LEVEL) : 0);
        ret.setGroup((link != null) ? getOptionString(link,
            LinkOption.SARRAY_LINK_GROUPS).split(" ")[0] : "");
        logger.l3("Echoarea " + name.toUpperCase() + " created");
        ORMManager.get(Echoarea.class).save(ret);
        if (link != null) {
          Subscription sub = new Subscription();
          sub.setArea(ret);
          sub.setLink(link);
          ORMManager.get(Subscription.class).save(sub);
        }
        Notifier.INSTANSE.notify(new NewEchoareaEvent(name, link));
      }
    } else {
      if (link != null
          && ORMManager.get(Subscription.class).getFirstAnd(
              "echoarea_id", "=", ret.getId(), "link_id", "=",
              link.getId()) == null) {
        ret = null;
      }
    }
    return ret;
  }

  /**
   * получение и аутокриейт
   *
   * @param name
   * @param link
   * @return
   */
  public static Filearea getFileareaByName(String name, Link link) {
    Filearea ret;
    name = name.toLowerCase();
    ret = ORMManager.get(Filearea.class).getFirstAnd("name", "=", name);
    if (ret == null) {
      if (link == null
          || getOptionBooleanDefFalse(link,
              LinkOption.BOOLEAN_AUTOCREATE_AREA)) {
        ret = new Filearea();
        ret.setName(name);
        ret.setDescription("Autocreated filearea");
        ret.setReadlevel((link != null) ? getOptionLong(link,
            LinkOption.LONG_LINK_LEVEL) : 0);
        ret.setWritelevel((link != null) ? getOptionLong(link,
            LinkOption.LONG_LINK_LEVEL) : 0);
        ret.setGroup((link != null) ? getOptionString(link,
            LinkOption.SARRAY_LINK_GROUPS).split(" ")[0] : "");
        logger.l3("Filearea " + name + " created");
        ORMManager.get(Filearea.class).save(ret);
        if (link != null) {
          FileSubscription sub = new FileSubscription();
          sub.setArea(ret);
          sub.setLink(link);
          ORMManager.get(FileSubscription.class).save(sub);
        }
        Notifier.INSTANSE.notify(new NewFileareaEvent(name, link));
      }
    } else {
      if (link != null
          && ORMManager.get(FileSubscription.class).getFirstAnd(
              "filearea_id", "=", ret.getId(), "link_id", "=",
              link.getId()) == null) {
        ret = null;
      }
    }
    return ret;
  }

  public static boolean isADupe(Echoarea area, String msgid) {
    return ORMManager.get(Echomail.class).getFirstAnd("msgid", "=", msgid,
        "echoarea_id", "=", area) != null;
  }

  /**
   * Проверка на дроп нетмейла
   *
   *
   * @param netmail
   * @return
   */
  public static boolean checkNetmailMustDropped(FtnMessage netmail) {
    // дополнительная проверка
    if (!MainHandler.getCurrentInstance().getBooleanProperty(NETMAIL_VALID,
        true)) {
      return false;
    }
    boolean validFrom = false;
    boolean validTo = false;
    // к нам на узел
    if (isOurPoint(netmail.getToAddr())) {
      validTo = true;
    } else if (getLinkByFtnAddress(netmail.getToAddr()) != null) {
      validTo = true;
    } else if (getLinkByFtnAddress(netmail.getToAddr().cloneNode()) != null) {
      validTo = true;
    } else {
      FtnNdlAddress to = NodelistScanner.getInstance().isExists(
          netmail.getToAddr());
      if (to == null) {
        FtnTools.writeReply(
            netmail,
            "Destination not found",
            "Sorry, but destination of your netmail is not found in nodelist\nMessage rejected");
        logger.l3(String.format(
            "Netmail %s -> %s reject ( dest not found )", netmail
                .getFromAddr().toString(), netmail.getToAddr()
                .toString()));

      } else {
        validTo = true;
        if (to.getStatus().equals(Status.DOWN)) {
          FtnTools.writeReply(netmail, "Destination is DOWN",
              "Warning! Destination of your netmail is DOWN.");
          logger.l3(String.format(
              "Netmail %s -> %s reject ( dest is DOWN )", netmail
                  .getFromAddr().toString(), netmail
                  .getToAddr().toString()));
          validTo = true;
        } else if (to.getStatus().equals(Status.HOLD)) {
          FtnTools.writeReply(netmail, "Destination is HOLD",
              "Warning! Destination of your netmail is HOLD");
          logger.l4(String.format(
              "Netmail %s -> %s warn ( dest is Hold )", netmail
                  .getFromAddr().toString(), netmail
                  .getToAddr().toString()));

        }
      }
    }

    if (isOurPoint(netmail.getFromAddr())) {
      validFrom = true;
    } else if (getLinkByFtnAddress(netmail.getFromAddr()) != null) {
      validFrom = true;
    } else if (getLinkByFtnAddress(netmail.getFromAddr().cloneNode()) != null) {
      validTo = true;
    } else {
      FtnNdlAddress from = NodelistScanner.getInstance().isExists(
          netmail.getFromAddr());
      if (from == null) {
        logger.l3(String.format(
            "Netmail %s -> %s reject ( origin not found )", netmail
                .getFromAddr().toString(), netmail.getToAddr()
                .toString()));
      } else {
        validFrom = true;
      }
    }

    return !(validFrom && validTo);
  }

  public static void writeEchomail(Echoarea area, String subject, String text) {
    writeEchomail(area, subject, text, MainHandler.getCurrentInstance()
        .getInfo().getStationName(), "All");
  }

  /**
   * Эхомейл
   *
   * @param area
   * @param subject
   * @param text
   * @param fromName
   * @param toName
   */
  public static void writeEchomail(Echoarea area, String subject,
      String text, String fromName, String toName) {
    Echomail mail = new Echomail();
    mail.setFromFTN(getPrimaryFtnAddress().toString());
    mail.setFromName(fromName);
    mail.setArea(area);
    mail.setDate(new Date());
    mail.setPath("");
    mail.setSeenBy("");
    mail.setToName(toName);
    mail.setSubject(subject);
    mail.setMsgid(getPrimaryFtnAddress().toString() + " "
        + FtnTools.generate8d());
    StringBuilder b = new StringBuilder();
    b.append(String.format("\001PID: %s\n\001TID: %s\n\n",
        MainHandler.getVersion(), MainHandler.getVersion()));
    b.append(text);
    b.append("\n--- "
        + MainHandler.getCurrentInstance().getInfo().getStationName()
        + "\n");
    b.append(" * Origin: " + MainHandler.getVersion() + " ("
        + getPrimaryFtnAddress().toString() + ")\n");
    mail.setText(b.toString());
    ORMManager.get(Echomail.class).save(mail);
    if (mail.getId() != null) {
      for (Subscription s : ORMManager.get(Subscription.class).getAnd(
          "echoarea_id", "=", area)) {
        ORMManager.get(EchomailAwaiting.class).save(
            new EchomailAwaiting(s.getLink(), mail));
      }
    }
  }

  public static FtnAddress getPrimaryFtnAddress() {
    return MainHandler.getCurrentInstance().getInfo().getAddressList()
        .get(0);
  }

  /**
   * Отправка файла в фэху
   *
   * @param area
   * @param attach
   * @param description
   */
  public static void hatchFile(Filearea area, File attach, String filename,
      String description) {
    Filemail mail = new Filemail();
    mail.setFilearea(area);
    mail.setFiledesc(description);
    mail.setFilename(filename);
    mail.setCreated(new Date());
    mail.setOrigin(getPrimaryFtnAddress().toString());
    mail.setPath("PATH " + getPrimaryFtnAddress().toString() + " "
        + (mail.getCreated().getTime() / 1000) + " "
        + mail.getCreated().toString() + "\r\n");
    mail.setSeenby("");
    String path = getFilePath(area.getName(), filename);
    File newFile = new File(path);
    if (FileUtils.move(attach, newFile, true)) {
      mail.setFilepath(newFile.getAbsolutePath());
    } else {
      mail.setFilepath(attach.getAbsolutePath());
      logger.l2("Failed to rename " + attach.getAbsolutePath() + " to "
          + path);
    }
    ORMManager.get(Filemail.class).save(mail);

    for (FileSubscription sub : ORMManager.get(FileSubscription.class)
        .getAnd("filearea_id", "=", area)) {
      ORMManager.get(FilemailAwaiting.class).save(
          new FilemailAwaiting(sub.getLink(), mail));
      if (getOptionBooleanDefFalse(sub.getLink(),
          LinkOption.BOOLEAN_CRASH_FILEMAIL)) {
        PollQueue.getSelf().add(sub.getLink());
      }
    }
  }

  public static String getFilePath(String area, String attach) {
    String areaPath = FtnTosser.getFileechoPath() + File.separator + area;
    File f = new File(areaPath);
    if (!f.isDirectory()) {
      if (f.exists()) {
        f.renameTo(new File(areaPath + "." + generate8d()));
        f = new File(areaPath);
      }
      f.mkdirs();
    }
    return (f.getAbsolutePath() + File.separator + attach).toLowerCase();
  }

  public static String md5(String protocolPassword) {
    MessageDigest mdEnc;
    try {
      mdEnc = MessageDigest.getInstance("MD5");
      mdEnc.update(protocolPassword.getBytes(), 0,
          protocolPassword.length());
      String md5 = new BigInteger(1, mdEnc.digest()).toString(16);
      return "MD5-" + md5;
    } catch (NoSuchAlgorithmException e) {
      return "PLAIN-" + protocolPassword;
    }

  }

  public static byte[] objectToBytes(Object object) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
      ObjectOutputStream os = new ObjectOutputStream(bos);
      os.writeObject(object);
      os.close();
      return bos.toByteArray();
    } catch (IOException e) {
      return null;
    }
  }

  public static void delete(Filearea area) {
    synchronized (Filearea.class) {
      if (area != null) {
        area.setGroup("_TO_DELETE_XXX"); // to prevent suncribing while
                          // deleting
        ORMManager.get(Filearea.class).update(area);
        ORMManager.get(FileSubscription.class).delete("filearea_id",
            "=", area);
        List<Filemail> toDelete = ORMManager.get(Filemail.class)
            .getAnd("filearea_id", "=", area);
        for (Filemail mail : toDelete) {
          ORMManager.get(FilemailAwaiting.class).delete(
              "filemail_id", "=", mail);
          ORMManager.get(Filemail.class).delete(mail);
        }
        ORMManager.get(Filearea.class).delete(area);
        logger.l2("Filearea " + area.getName() + " deleted");
      }
    }

  }

  public static void delete(Echoarea area) {
    synchronized (Echoarea.class) {
      if (area != null) {
        area.setGroup("_TO_DELETE_XXX"); // to prevent suncribing while
                          // deleting
        ORMManager.get(Echoarea.class).update(area);
        ORMManager.get(Subscription.class).delete("echoarea_id", "=",
            area);
        List<Echomail> toDelete = ORMManager.get(Echomail.class)
            .getAnd("echoarea_id", "=", area);
        for (Echomail mail : toDelete) {
          ORMManager.get(EchomailAwaiting.class).delete(
              "echomail_id", "=", mail);
          ORMManager.get(Echomail.class).delete(mail);
        }
        ORMManager.get(Echoarea.class).delete(area);
        logger.l2("Echoarea " + area.getName() + " deleted");
      }
    }

  }

  public static void delete(Link link) {
    synchronized (TosserQueue.getInstanse()) {
      if (link != null) {
        ORMManager.get(LinkOption.class).delete("link_id", "=", link);
        link.setProtocolHost("-");
        link.setProtocolPort(0);
        link.setProtocolPassword("_TO_DELETE_XXX");
        // to prevent connect
        ORMManager.get(Link.class).update(link);
        ORMManager.get(EchomailAwaiting.class).delete("link_id", "=",
            link);
        ORMManager.get(FilemailAwaiting.class).delete("link_id", "=",
            link);
        ORMManager.get(Subscription.class).delete("link_id", "=", link);
        ORMManager.get(FileSubscription.class).delete("link_id", "=",
            link);
        ORMManager.get(FileForLink.class).delete("link_id", "=", link);
        ORMManager.get(Route.class).delete("route_via", "=", link);
        ORMManager.get(Netmail.class).update("route_via", 0,
            "route_via", "=", link);
        ORMManager.get(Link.class).delete(link);
        logger.l2("Link " + link.getLinkAddress() + " deleted");
      }
    }

  }

  public static void setOption(Link link, String name, String value) {
    LinkOption option = ORMManager.get(LinkOption.class).getFirstAnd(
        "link_id", "=", link, "name", "=", name);
    if (option == null) {
      option = new LinkOption(link, name, value);
    } else {
      option.setValue(value);
    }
    ORMManager.get(LinkOption.class).saveOrUpdate(option);
  }

}
TOP

Related Classes of jnode.ftn.FtnTools

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.