package com.l7tech.server.transport.ftp;

import com.l7tech.common.ftp.FtpCommand;
import com.l7tech.common.log.HybridDiagnosticContext;
import com.l7tech.common.mime.ContentTypeHeader;
import com.l7tech.gateway.common.transport.SsgConnector;
import com.l7tech.message.FtpRequestKnob;
import com.l7tech.message.HasServiceId;
import com.l7tech.message.HasServiceIdImpl;
import com.l7tech.message.Message;
import com.l7tech.objectmodel.Goid;
import com.l7tech.policy.assertion.AssertionStatus;
import com.l7tech.server.MessageProcessor;
import com.l7tech.server.StashManagerFactory;
import com.l7tech.server.event.FaultProcessed;
import com.l7tech.server.message.PolicyEnforcementContext;
import com.l7tech.server.message.PolicyEnforcementContextFactory;
import com.l7tech.server.policy.PolicyVersionException;
import com.l7tech.server.util.EventChannel;
import com.l7tech.server.util.SoapFaultManager;
import com.l7tech.util.CausedIOException;
import com.l7tech.util.ExceptionUtils;
import com.l7tech.util.ResourceUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.ftpserver.ftplet.DataConnection;
import org.apache.ftpserver.ftplet.DefaultFtpReply;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.impl.FtpIoSession;
import org.apache.ftpserver.impl.FtpServerContext;
import org.apache.ftpserver.impl.IODataConnectionFactory;
import org.apache.ftpserver.impl.LocalizedFtpReply;
import org.apache.ftpserver.impl.ServerDataConnectionFactory;

public abstract class AbstractFtpRequestProcessor implements FtpRequestProcessor {
   private final Logger a;
   private final MessageProcessor b;
   private final SoapFaultManager c;
   private final StashManagerFactory d;
   private final EventChannel e;
   private final ExecutorService f;
   private final ContentTypeHeader g;
   private final Goid h;
   private final SsgConnector i;
   private final long j;
   private static final String[] l;

   public AbstractFtpRequestProcessor(
      MessageProcessor var1,
      SoapFaultManager var2,
      StashManagerFactory var3,
      EventChannel var4,
      ExecutorService var5,
      ContentTypeHeader var6,
      Goid var7,
      SsgConnector var8,
      long var9,
      Logger var11
   ) {
      this.b = var1;
      this.c = var2;
      this.d = var3;
      this.e = var4;
      this.f = var5;
      this.g = var6;
      this.h = var7;
      this.i = var8;
      this.j = var9;
      this.a = var11;
   }

   protected void addDiagnosticContextInfo(FtpIoSession var1) {
      String var2 = ((InetSocketAddress)var1.getRemoteAddress()).getAddress().getHostAddress();
      String[] var3 = l;
      HybridDiagnosticContext.put(var3[7], this.i.getGoid().toString());
      HybridDiagnosticContext.put(var3[19], this.i.getName());
      HybridDiagnosticContext.put(var3[1], var2);
   }

   protected void removeDiagnosticContextInfo() {
      String[] var1 = l;
      HybridDiagnosticContext.remove(var1[6]);
      HybridDiagnosticContext.remove(var1[2]);
      HybridDiagnosticContext.remove(var1[16]);
   }

   protected boolean validateConnectionFactoryState(FtpIoSession var1) {
      boolean var2 = true;
      ServerDataConnectionFactory var3 = var1.getDataConnection();
      if (var3 instanceof IODataConnectionFactory) {
         InetAddress var4 = ((IODataConnectionFactory)var3).getInetAddress();
         if (var4 == null) {
            var2 = false;
         }
      }

      return var2;
   }

   protected void resetStateAndCloseConnection(FtpIoSession var1) {
      var1.resetState();
      var1.getDataConnection().closeDataConnection();
   }

   protected void handleCreateRequestMessageFailure(FtpIoSession var1, FtpCommand var2, IOException var3) {
      this.a.log(Level.WARNING, l[8] + ExceptionUtils.getMessage(var3), ExceptionUtils.getDebugException(var3));
      this.reply550ProcessingError(var1, var2);
   }

   protected void handleMessageProcessingFailure(FtpIoSession var1, FtpCommand var2, AssertionStatus var3) {
      Logger var10000 = this.a;
      Level var10001 = Level.WARNING;
      String var10002 = String.valueOf(var2);
      String var10003 = var3.getMessage();
      String[] var4 = l;
      var10000.log(var10001, var4[10] + var10002 + var4[5] + var10003);
      this.reply550ProcessingError(var1, var2);
   }

   protected void handleOpenConnectionFailure(FtpIoSession var1, FtpServerContext var2, FtpRequest var3, Exception var4) {
      this.a.log(Level.WARNING, l[18] + ExceptionUtils.getMessage(var4), ExceptionUtils.getDebugException(var4));
      var1.write(LocalizedFtpReply.translate(var1, var3, var2, 425, var3.getCommand(), var3.getArgument()));
   }

   protected void handleDataTransferFailure(FtpIoSession var1, FtpServerContext var2, FtpRequest var3, Exception var4) {
      this.a.log(Level.WARNING, l[11] + var4.getMessage(), ExceptionUtils.getDebugException(var4));
      var1.write(LocalizedFtpReply.translate(var1, var3, var2, 426, var3.getCommand(), var3.getArgument()));
   }

   protected void reply150FileStatusOk(FtpIoSession var1, FtpServerContext var2, FtpRequest var3) {
      var1.write(LocalizedFtpReply.translate(var1, var3, var2, 150, var3.getCommand(), var3.getArgument()));
   }

   protected void reply226ClosingConnection(FtpIoSession var1, FtpServerContext var2, FtpRequest var3) {
      var1.write(LocalizedFtpReply.translate(var1, var3, var2, 226, var3.getCommand(), var3.getArgument()));
   }

   protected void reply501SyntaxError(FtpIoSession var1, FtpServerContext var2, FtpRequest var3) {
      var1.write(LocalizedFtpReply.translate(var1, var3, var2, 501, var3.getCommand(), null));
   }

   protected void reply503BadSequence(FtpIoSession var1) {
      var1.write(new DefaultFtpReply(503, l[0]));
   }

   protected void reply550ProcessingError(FtpIoSession var1, FtpCommand var2) {
      String var10004 = String.valueOf(var2);
      String[] var3 = l;
      var1.write(new DefaultFtpReply(550, var3[15] + var10004 + var3[17]));
   }

   protected AssertionStatus submitRequestMessage(PolicyEnforcementContext var1) {
      String var2 = null;
      AssertionStatus var3 = AssertionStatus.UNDEFINED;

      try {
         var3 = this.b.processMessage(var1);

         try {
            if (this.a.isLoggable(Level.FINER)) {
               this.a.log(Level.FINER, l[3], var3);
            }
         } catch (PolicyVersionException var7) {
            throw a(var7);
         }

         if (var3 != AssertionStatus.NONE) {
            var2 = this.c.constructReturningFault(var1.getFaultlevel(), var1).getContent();
         }
      } catch (PolicyVersionException var8) {
         String[] var5 = l;
         this.a.log(Level.INFO, var5[9]);
         var2 = this.c.constructExceptionFault(var8, var1.getFaultlevel(), var1).getContent();
      } catch (Throwable var9) {
         this.a.log(Level.WARNING, l[4] + ExceptionUtils.getMessage(var9), ExceptionUtils.getDebugException(var9));
         var2 = this.c.constructExceptionFault(var9, var1.getFaultlevel(), var1).getContent();
      }

      try {
         if (var2 != null) {
            this.e.publishEvent(new FaultProcessed(var1, var2, this.b));
         }

         return var3;
      } catch (PolicyVersionException var6) {
         throw a(var6);
      }
   }

   protected Message createRequestMessage(FtpIoSession var1, FtpRequest var2, FtpCommand var3, InputStream var4) throws FtpException, IOException {
      AbstractFtpRequestProcessor var10000;
      FtpIoSession var10001;
      FtpRequest var10002;
      FtpCommand var10003;
      try {
         var10000 = this;
         var10001 = var1;
         var10002 = var2;
         var10003 = var3;
         if (FtpCommand.STOU == var3) {
            return this.createRequestMessage(var1, var2, var3, true, var4);
         }
      } catch (FtpException var5) {
         throw a(var5);
      }

      return var10000.createRequestMessage(var10001, var10002, var10003, false, var4);
   }

   protected Message createRequestMessage(FtpIoSession var1, FtpRequest var2, FtpCommand var3, boolean var4, InputStream var5) throws FtpException, IOException {
      User var6 = var1.getUser();
      String var7 = var2.getArgument();
      String var8 = var1.getFileSystemView().getWorkingDirectory().getAbsolutePath();
      boolean var9 = this.a(var1);

      long var10000;
      label41: {
         try {
            if (this.j == -1L) {
               var10000 = Message.getMaxBytes();
               break label41;
            }
         } catch (FtpException var17) {
            throw a(var17);
         }

         var10000 = this.j;
      }

      long var10 = var10000;

      label33: {
         try {
            if (this.g != null) {
               var18 = this.g;
               break label33;
            }
         } catch (FtpException var16) {
            throw a(var16);
         }

         var18 = this.getDefaultMessageContentType();
      }

      ContentTypeHeader var12 = var18;
      Message var13 = new Message();
      var13.initialize(this.d.createStashManager(), var12, var5, var10);
      InetSocketAddress var14 = (InetSocketAddress)var1.getLocalAddress();

      try {
         var13.attachFtpRequestKnob(
            this.buildFtpKnob(
               var14.getAddress(), var14.getPort(), ((InetSocketAddress)var1.getRemoteAddress()).getAddress(), var3, var7, var8, var9, var4, var6
            )
         );
         if (null != this.h) {
            var13.attachKnob(HasServiceId.class, new HasServiceIdImpl(this.h));
         }

         return var13;
      } catch (FtpException var15) {
         throw a(var15);
      }
   }

   protected abstract ContentTypeHeader getDefaultMessageContentType();

   protected PolicyEnforcementContext createPolicyEnforcementContext(Message var1) {
      return PolicyEnforcementContextFactory.createPolicyEnforcementContext(var1, new Message(), true);
   }

   private boolean a(FtpIoSession var1) {
      boolean var2 = var1.getDataConnection().isSecure();
      boolean var3 = var1.getListener().isImplicitSsl();
      if (this.a.isLoggable(Level.FINE)) {
         this.a.log(Level.FINE, l[13], new Object[]{var3, var2});
      }

      return var2 && var3;
   }

   protected FtpRequestKnob buildFtpKnob(
      InetAddress var1, int var2, InetAddress var3, FtpCommand var4, String var5, String var6, boolean var7, boolean var8, User var9
   ) {
      return new a(this, var2, var3, var1, var4, var5, var6, var7, var8, var9);
   }

   protected InputStream transferDataFromClient(FtpSession var1, DataConnection var2, String var3) throws IOException {
      PipedInputStream var4 = new PipedInputStream();
      CountDownLatch var5 = new CountDownLatch(1);
      this.f.execute(new b(this, var3, var4, var5, var2, var1));

      try {
         var5.await();
         return var4;
      } catch (InterruptedException var7) {
         Thread.currentThread().interrupt();
         throw new CausedIOException(l[14], var7);
      }
   }

   protected void transferDataToClient(FtpSession var1, DataConnection var2, InputStream var3) throws IOException {
      try {
         var2.transferToClient(var1, var3);
      } finally {
         ResourceUtils.closeQuietly(var3);
      }
   }

   @Override
   public void dispose() {
      if (this.f != null) {
         this.f.shutdown();

         try {
            this.f.awaitTermination(5000L, TimeUnit.MILLISECONDS);
         } catch (InterruptedException var2) {
            this.a.log(Level.FINE, l[12] + var2.getMessage());
         }
      }
   }

   private static Exception a(Exception var0) {
      return var0;
   }

   static {
      String[] var5 = new String[20];
      int var3 = 0;
      String var2 = "!XM\u000e}4\bQG^\t\u000b{\u0017\u0004dkz?>Z\u0018dl/8?Z\u0017~m))\t\u0012{v?3/W\u0018g\u000b\u001d~l.85W\u0001xm.\"!xs3>\"Z\u0003rl/1/\u001f\u00157v4}(\u000e\u0010cj)}|]\n'b}zu(4o|?-/\u0013\u001ey?-52\u0016\u00147o(28\u001f\u0002dv4:{<%G?78(\t\u0010pz`}\u001cQzz).:\u001d\u00147o(28\u001f\u0002dv4:{\u001c\u0010~s?9aZ\u000e\u001d~l.85W\u0001xm.p2\u001e\u000e\u001d~l.85W\u0001xm.p2\u001e 4em5/{\u0019\u0003r~.45\u001dQez+(>\t\u00057r?.(\u001b\u0016r%z2#rn/8(\u000eQez<8)\b\u0014s?.2{\u001b\u001f7p/)?\u001b\u0005r{z+>\b\u0002~p4}4\u001cQgp648\u0003_\u00047COz\u001c4em5/{\u001e\u0004ev4:{\u001e\u0010c~z))\u001b\u001fdy?/aZ\"%\u007fm?<?Z\u0001xp6}(\u0012\u0004c{5*5Z\u0018yk?/)\u000f\u0001cz>g{=\"r|//2\u000e\b7s?+>\u0016\u0002;?925\u000e\u0003xsz.>\u0019\u0004ezzz|\u0001Aj8}q{\u001e\u0010c~z.>\u0019\u0004ezzz|\u0001@j8}s\u001d8yk?/)\u000f\u0001cz>},\u001b\u0018cv4:{\u001c\u001ee?></\u001b_\u00184em5/{\n\u0003x|?.(\u0013\u001fp?\u001c\t\u000bR\">?\t\u0012{v?3/W\u0018g\tQez+(>\t\u00059";
      int var4 = "!XM\u000e}4\bQG^\t\u000b{\u0017\u0004dkz?>Z\u0018dl/8?Z\u0017~m))\t\u0012{v?3/W\u0018g\u000b\u001d~l.85W\u0001xm.\"!xs3>\"Z\u0003rl/1/\u001f\u00157v4}(\u000e\u0010cj)}|]\n'b}zu(4o|?-/\u0013\u001ey?-52\u0016\u00147o(28\u001f\u0002dv4:{<%G?78(\t\u0010pz`}\u001cQzz).:\u001d\u00147o(28\u001f\u0002dv4:{\u001c\u0010~s?9aZ\u000e\u001d~l.85W\u0001xm.p2\u001e\u000e\u001d~l.85W\u0001xm.p2\u001e 4em5/{\u0019\u0003r~.45\u001dQez+(>\t\u00057r?.(\u001b\u0016r%z2#rn/8(\u000eQez<8)\b\u0014s?.2{\u001b\u001f7p/)?\u001b\u0005r{z+>\b\u0002~p4}4\u001cQgp648\u0003_\u00047COz\u001c4em5/{\u001e\u0004ev4:{\u001e\u0010c~z))\u001b\u001fdy?/aZ\"%\u007fm?<?Z\u0001xp6}(\u0012\u0004c{5*5Z\u0018yk?/)\u000f\u0001cz>g{=\"r|//2\u000e\b7s?+>\u0016\u0002;?925\u000e\u0003xsz.>\u0019\u0004ezzz|\u0001Aj8}q{\u001e\u0010c~z.>\u0019\u0004ezzz|\u0001@j8}s\u001d8yk?/)\u000f\u0001cz>},\u001b\u0018cv4:{\u001c\u001ee?></\u001b_\u00184em5/{\n\u0003x|?.(\u0013\u001fp?\u001c\t\u000bR\">?\t\u0012{v?3/W\u0018g\tQez+(>\t\u00059"
         .length();
      char var1 = '!';
      int var7 = -1;

      label24:
      while (true) {
         byte var10000 = 54;
         String var10001 = var2.substring(++var7, var7 + var1);
         byte var10002 = -1;

         while (true) {
            String var8 = a(var10000, a(var10001));
            switch (var10002) {
               case 0:
                  var5[var3++] = var8;
                  if ((var7 += var1) >= var4) {
                     l = var5;
                     return;
                  }

                  var1 = var2.charAt(var7);
                  break;
               default:
                  var5[var3++] = var8;
                  if ((var7 += var1) < var4) {
                     var1 = var2.charAt(var7);
                     continue label24;
                  }

                  var2 = ")hh(&!D\u001bf!+3 \nOh! \"1\u0005Ojn*- \u0007\u001b`n*ye\u000b\u0003`r0&+I\u001ffs0";
                  var4 = ")hh(&!D\u001bf!+3 \nOh! \"1\u0005Ojn*- \u0007\u001b`n*ye\u000b\u0003`r0&+I\u001ffs0".length();
                  var1 = '"';
                  var7 = -1;
            }

            var10000 = 40;
            var10001 = var2.substring(++var7, var7 + var1);
            var10002 = 0;
         }
      }
   }

   private static char[] a(String var0) {
      char[] var10000 = var0.toCharArray();
      if (var10000.length < 2) {
         var10000[0] = (char)(var10000[0] ^ 76);
      }

      return var10000;
   }

   private static String a(int var0, char[] var1) {
      int var10003 = var1.length;
      int var10002 = var0;
      char[] var10001 = var1;
      int var10000 = var10003;

      for (int var2 = 0; var10000 > var2; var2++) {
         var10001[var2] = (char)(var10001[var2] ^ var10002 ^ switch (var2 % 7) {
            case 0 -> 71;
            case 1 -> 33;
            case 2 -> 41;
            case 3 -> 108;
            case 4 -> 107;
            case 5 -> 109;
            default -> 76;
         });
      }

      return new String(var10001).intern();
   }
}
