// Path: api/src/main/java/xyz/docbleach/api/BleachSession.java
// public class BleachSession implements Serializable {
// 
//   private static final Logger LOGGER = LoggerFactory.getLogger(BleachSession.class);
//   private static final int MAX_ONGOING_TASKS = 10;
//   private final transient Bleach bleach;
//   private final Collection<Threat> threats = new ArrayList<>();
//   /**
//    * Counts ongoing tasks, to prevent fork bombs when handling zip archives for instance)
//    */
//   private int ongoingTasks = 0;
// 
//   public BleachSession(Bleach bleach) {
//     this.bleach = bleach;
//   }
// 
//   /**
//    * The BleachSession is able to record threats encountered by the bleach.
//    *
//    * @param threat The removed threat object, containing the threat type and more information
//    */
//   public void recordThreat(Threat threat) {
//     if (threat == null) {
//       return;
//     }
//     LOGGER.trace("Threat recorded: " + threat);
//     threats.add(threat);
//   }
// 
//   public Collection<Threat> getThreats() {
//     return threats;
//   }
// 
//   public int threatCount() {
//     return threats.size();
//   }
// 
//   /**
//    * @return The bleach used in this session
//    */
//   public Bleach getBleach() {
//     return bleach;
//   }
// 
//   public void sanitize(InputStream is, OutputStream os) throws BleachException {
//     try {
//       if (ongoingTasks++ >= MAX_ONGOING_TASKS) {
//         throw new RecursionBleachException(ongoingTasks);
//       }
//       if (!bleach.handlesMagic(is)) {
//         return;
//       }
//       bleach.sanitize(is, os, this);
//     } finally {
//       ongoingTasks--;
//     }
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/Threat.java
// @AutoValue
// public abstract class Threat {
// 
//   public static Builder builder() {
//     return new AutoValue_Threat.Builder();
//   }
// 
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     public abstract Builder type(ThreatType value);
// 
//     public abstract Builder severity(ThreatSeverity value);
// 
//     public abstract Builder action(ThreatAction value);
// 
//     public abstract Builder location(String value);
// 
//     public abstract Builder details(String value);
// 
//     public abstract Threat build();
//   }
// 
//   public abstract ThreatType type();
// 
//   public abstract ThreatSeverity severity();
// 
//   public abstract ThreatAction action();
// 
//   public abstract String location();
// 
//   public abstract String details();
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatAction.java
// public enum ThreatAction {
//   /**
//    * No actions had to be taken, for instance if the threat is innocuous.
//    */
//   NOTHING,
// 
//   /**
//    * The potential threat has been replaced by an innocuous content. ie: HTML file replaced by a
//    * screenshot of the page
//    */
//   DISARM,
// 
//   /**
//    * No actions were taken because of the configuration
//    */
//   IGNORE,
// 
//   /**
//    * The threat has been removed.
//    */
//   REMOVE;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatSeverity.java
// public enum ThreatSeverity {
//   LOW,
//   MEDIUM,
//   HIGH,
//   EXTREME;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatType.java
// public enum ThreatType {
//   /**
//    * Macros, JavaScript, ActiveX, AcroForms, DDEAUTO
//    */
//   ACTIVE_CONTENT,
// 
//   /**
//    * Word Template linking to an external "thing", ...
//    */
//   EXTERNAL_CONTENT,
// 
//   /**
//    * OLE Objects, ...
//    */
//   BINARY_CONTENT,
// 
//   /**
//    * OLE Objects, strange image in a document ...
//    */
//   UNRECOGNIZED_CONTENT
// }


import java.util.Set;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.BleachSession;
import xyz.docbleach.api.threat.Threat;
import xyz.docbleach.api.threat.ThreatAction;
import xyz.docbleach.api.threat.ThreatSeverity;
import xyz.docbleach.api.threat.ThreatType;
    String entryName = entry.getName();

    if (!isObject(entryName)) {
      return true;
    }

    LOGGER.info("Found Compound Objects, removing them.");
    StringBuilder infos = new StringBuilder();
    if (entry instanceof DirectoryEntry) {
      Set<String> entryNames = ((DirectoryEntry) entry).getEntryNames();
      LOGGER.trace("Compound Objects' entries: {}", entryNames);
      infos.append("Entries: ").append(entryNames);
    } else if (entry instanceof DocumentEntry) {
      int size = ((DocumentEntry) entry).getSize();
      infos.append("Size: ").append(size);
    }

    Threat threat = Threat.builder()
        .type(ThreatType.EXTERNAL_CONTENT)
        .severity(ThreatSeverity.HIGH)
        .action(ThreatAction.REMOVE)
        .location(entryName)
        .details(infos.toString())
        .build();

    session.recordThreat(threat);

    return false;
  }

// Path: api/src/main/java/xyz/docbleach/api/BleachSession.java
// public class BleachSession implements Serializable {
// 
//   private static final Logger LOGGER = LoggerFactory.getLogger(BleachSession.class);
//   private static final int MAX_ONGOING_TASKS = 10;
//   private final transient Bleach bleach;
//   private final Collection<Threat> threats = new ArrayList<>();
//   /**
//    * Counts ongoing tasks, to prevent fork bombs when handling zip archives for instance)
//    */
//   private int ongoingTasks = 0;
// 
//   public BleachSession(Bleach bleach) {
//     this.bleach = bleach;
//   }
// 
//   /**
//    * The BleachSession is able to record threats encountered by the bleach.
//    *
//    * @param threat The removed threat object, containing the threat type and more information
//    */
//   public void recordThreat(Threat threat) {
//     if (threat == null) {
//       return;
//     }
//     LOGGER.trace("Threat recorded: " + threat);
//     threats.add(threat);
//   }
// 
//   public Collection<Threat> getThreats() {
//     return threats;
//   }
// 
//   public int threatCount() {
//     return threats.size();
//   }
// 
//   /**
//    * @return The bleach used in this session
//    */
//   public Bleach getBleach() {
//     return bleach;
//   }
// 
//   public void sanitize(InputStream is, OutputStream os) throws BleachException {
//     try {
//       if (ongoingTasks++ >= MAX_ONGOING_TASKS) {
//         throw new RecursionBleachException(ongoingTasks);
//       }
//       if (!bleach.handlesMagic(is)) {
//         return;
//       }
//       bleach.sanitize(is, os, this);
//     } finally {
//       ongoingTasks--;
//     }
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/Threat.java
// @AutoValue
// public abstract class Threat {
// 
//   public static Builder builder() {
//     return new AutoValue_Threat.Builder();
//   }
// 
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     public abstract Builder type(ThreatType value);
// 
//     public abstract Builder severity(ThreatSeverity value);
// 
//     public abstract Builder action(ThreatAction value);
// 
//     public abstract Builder location(String value);
// 
//     public abstract Builder details(String value);
// 
//     public abstract Threat build();
//   }
// 
//   public abstract ThreatType type();
// 
//   public abstract ThreatSeverity severity();
// 
//   public abstract ThreatAction action();
// 
//   public abstract String location();
// 
//   public abstract String details();
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatAction.java
// public enum ThreatAction {
//   /**
//    * No actions had to be taken, for instance if the threat is innocuous.
//    */
//   NOTHING,
// 
//   /**
//    * The potential threat has been replaced by an innocuous content. ie: HTML file replaced by a
//    * screenshot of the page
//    */
//   DISARM,
// 
//   /**
//    * No actions were taken because of the configuration
//    */
//   IGNORE,
// 
//   /**
//    * The threat has been removed.
//    */
//   REMOVE;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatSeverity.java
// public enum ThreatSeverity {
//   LOW,
//   MEDIUM,
//   HIGH,
//   EXTREME;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/ThreatType.java
// public enum ThreatType {
//   /**
//    * Macros, JavaScript, ActiveX, AcroForms, DDEAUTO
//    */
//   ACTIVE_CONTENT,
// 
//   /**
//    * Word Template linking to an external "thing", ...
//    */
//   EXTERNAL_CONTENT,
// 
//   /**
//    * OLE Objects, ...
//    */
//   BINARY_CONTENT,
// 
//   /**
//    * OLE Objects, strange image in a document ...
//    */
//   UNRECOGNIZED_CONTENT
// }


// Path: module/module-office/src/main/java/xyz/docbleach/module/ole2/ObjectRemover.java
import java.util.Set;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.BleachSession;
import xyz.docbleach.api.threat.Threat;
import xyz.docbleach.api.threat.ThreatAction;
import xyz.docbleach.api.threat.ThreatSeverity;
import xyz.docbleach.api.threat.ThreatType;

    String entryName = entry.getName();

    if (!isObject(entryName)) {
      return true;
    }

    LOGGER.info("Found Compound Objects, removing them.");
    StringBuilder infos = new StringBuilder();
    if (entry instanceof DirectoryEntry) {
      Set<String> entryNames = ((DirectoryEntry) entry).getEntryNames();
      LOGGER.trace("Compound Objects' entries: {}", entryNames);
      infos.append("Entries: ").append(entryNames);
    } else if (entry instanceof DocumentEntry) {
      int size = ((DocumentEntry) entry).getSize();
      infos.append("Size: ").append(size);
    }

    Threat threat = Threat.builder()
        .type(ThreatType.EXTERNAL_CONTENT)
        .severity(ThreatSeverity.HIGH)
        .action(ThreatAction.REMOVE)
        .location(entryName)
        .details(infos.toString())
        .build();

    session.recordThreat(threat);

    return false;
  }

  protected boolean isObject(String entryName) {