// 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/bleach/Bleach.java
// public interface Bleach {
// 
//   /**
//    * Checks the magic header of the file and returns true if this bleach is able to sanitize this
//    * InputStream. The stream has to {@link InputStream#markSupported support mark}.
//    *
//    * <p>The Bleach is responsible for the error handling to prevent exceptions.
//    *
//    * @param stream file from wich we will read the data
//    * @return true if this bleach may handle this file, false otherwise
//    */
//   boolean handlesMagic(InputStream stream);
// 
//   /**
//    * @return this bleach's name
//    */
//   String getName();
// 
//   /**
//    * @param inputStream the file we want to sanitize
//    * @param outputStream the sanitized file this bleach will write to
//    * @param session the bleach session that stores threats
//    * @throws BleachException Any fatal error that might occur during the bleach
//    */
//   void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
//       throws BleachException;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/BleachException.java
// public class BleachException extends Exception {
// 
//   public BleachException(Throwable e) {
//     super(e);
//   }
// 
//   public BleachException(String message) {
//     super(message);
//   }
// }


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.function.Predicate;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.BleachSession;
import xyz.docbleach.api.bleach.Bleach;
import xyz.docbleach.api.exception.BleachException;
package xyz.docbleach.module.ole2;


/**
 * Sanitizes an OLE2 file (.doc, .xls, .ppt) by copying its elements into a new OLE2 container.
 * Information to be modified (template, ...) are changed on the fly, and entries to be removed are
 * just not copied over. This way, using a simple Visitor, it is possible to add rules applied on
 * each entry.
 */
public class OLE2Bleach implements Bleach {

  private static final Logger LOGGER = LoggerFactory.getLogger(OLE2Bleach.class);

  @Override
  public boolean handlesMagic(InputStream stream) {
    try {
      return stream.available() > 4 && FileMagic.valueOf(stream) == FileMagic.OLE2;
    } catch (Exception e) {
      LOGGER.warn("An exception occured", e);
      return false;
    }
  }

  @Override
  public String getName() {
    return "OLE2 Bleach";
  }

  @Override
  public void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
// 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/bleach/Bleach.java
// public interface Bleach {
// 
//   /**
//    * Checks the magic header of the file and returns true if this bleach is able to sanitize this
//    * InputStream. The stream has to {@link InputStream#markSupported support mark}.
//    *
//    * <p>The Bleach is responsible for the error handling to prevent exceptions.
//    *
//    * @param stream file from wich we will read the data
//    * @return true if this bleach may handle this file, false otherwise
//    */
//   boolean handlesMagic(InputStream stream);
// 
//   /**
//    * @return this bleach's name
//    */
//   String getName();
// 
//   /**
//    * @param inputStream the file we want to sanitize
//    * @param outputStream the sanitized file this bleach will write to
//    * @param session the bleach session that stores threats
//    * @throws BleachException Any fatal error that might occur during the bleach
//    */
//   void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
//       throws BleachException;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/BleachException.java
// public class BleachException extends Exception {
// 
//   public BleachException(Throwable e) {
//     super(e);
//   }
// 
//   public BleachException(String message) {
//     super(message);
//   }
// }


// Path: module/module-office/src/main/java/xyz/docbleach/module/ole2/OLE2Bleach.java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.function.Predicate;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.BleachSession;
import xyz.docbleach.api.bleach.Bleach;
import xyz.docbleach.api.exception.BleachException;

package xyz.docbleach.module.ole2;


/**
 * Sanitizes an OLE2 file (.doc, .xls, .ppt) by copying its elements into a new OLE2 container.
 * Information to be modified (template, ...) are changed on the fly, and entries to be removed are
 * just not copied over. This way, using a simple Visitor, it is possible to add rules applied on
 * each entry.
 */
public class OLE2Bleach implements Bleach {

  private static final Logger LOGGER = LoggerFactory.getLogger(OLE2Bleach.class);

  @Override
  public boolean handlesMagic(InputStream stream) {
    try {
      return stream.available() > 4 && FileMagic.valueOf(stream) == FileMagic.OLE2;
    } catch (Exception e) {
      LOGGER.warn("An exception occured", e);
      return false;
    }
  }

  @Override
  public String getName() {
    return "OLE2 Bleach";
  }

  @Override
  public void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
      throws BleachException {