Dateiverwaltung für die WebBox
ulrich@undisclosed
2020-03-01 2248cbff4f9506ea8e0876231f45bfce275a093f
src/java/de/uhilger/filecms/api/FileMgr.java
@@ -1,5 +1,4 @@
/*
    Dateiverwaltung - File management in your browser
    Copyright (C) 2017 Ulrich Hilger, http://uhilger.de
@@ -15,131 +14,703 @@
    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package de.uhilger.filecms.api;
import de.uhilger.filesystem.FileRef;
import de.uhilger.filecms.data.FileRef;
import de.uhilger.filecms.pub.AbstractComparator;
import de.uhilger.filecms.pub.FileNameComparator;
import de.uhilger.filecms.pub.ImgFileFilter;
import de.uhilger.wbx.Bild;
import de.uhilger.wbx.WbxUtils;
import static de.uhilger.wbx.WbxUtils.EMPTY_STRING;
import static de.uhilger.wbx.WbxUtils.WBX_FILE_BASE;
import de.uhilger.wbx.data.Inhalt;
import de.uhilger.wbx.web.TNServlet;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.servlet.http.HttpServletRequest;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
/**
 *
 * @author ulrich
 * Methoden zur Verwaltung von Dateien
 */
public class FileMgr extends Api {
  private static final Logger logger = Logger.getLogger(FileMgr.class.getName());
  public static final int OP_COPY = 1;
  public static final int OP_MOVE = 2;
  
  public static final String FILE_BASE = "fileBase";
  public static final String DOT = ".";
  
  public String hallo() {
    return "Hallo Welt!";
  }
  
  // http://localhost:8097/file-cms/rpc/de.uhilger.filecms.api.FileMgr/getBase/JSONNICE
  public FileRef getBase() {
    FileRef ref = null;
    //String fileBase = getServletContext().getInitParameter(FILE_BASE);
    // -Dfilecms.base=/pfad/zu/daten
    //String fileBase = System.getProperty("filecms.base");
    //File file = new File(fileBase);
    //logger.info(file.getAbsolutePath());
    //logger.info(getWebappsDir().getAbsolutePath());
    /*
        file = new File("."); liefert
        /home/ulrich/dev/lib/java/tomcat/tomcat2-8.5.9/bin/.
        ..auf der WebBox aber
        /home/ulrich/srv/wbx_probe/.
        ..weil das Startskript dort liegt
        der Tomcat der WebBox ist unter
        sys/jrs/tomcat/bin
        also z.B.
        /home/ulrich/srv/wbx_probe/sys/jrs/tomcat/bin
        das Datenverzeichnis ist z.B. auf
        /home/ulrich/srv/wbx_probe/daten
        dann ist das Datenverzeichnis unter
        ../../../daten
        Der Ausdruck file = new File("."); liefert stets den
        Ort von dem aus der Java-Prozess gestartet wurde.
        Die unten folgende Bestimmung des Datenverzeichnisses
        ist beschraenkt auf das Datenverzeichnis der WebBox,
        entweder relativ zum Startskript der WebBox oder
        dem Startskript von Tomcat, wie es aus Netbeans heraus
        waehrend der Entwicklung genutzt wird.
        Besser ware vielleicht eine Bestimmung ueber einen
        Systemparameter -Dfilecms.base=... wie weiter oben
        auskommentiert. Damit liesse sich das file-cms auch
        ohne WebBox einsetzen. Allerdings muss dann das
        Datenverzeichnis im Start-Skript gebildet werden,
        also ausserhalb von Java, wenn es dynamisch aus
        einem Pfad relativ zum Start-Skript erzeugt werden
        soll.
    */
    File file = new File(".");
    String path = file.getAbsolutePath();
    path = path.substring(0, path.length() - 1);
    file = new File(path);
    if(path.endsWith("bin")) {
      file = file.getParentFile().getParentFile().getParentFile();
    } else {
    }
    file = new File(file, "daten/");
    ref = new FileRef(file.getAbsolutePath(), file.isDirectory());
    return ref;
  /**
   * Inhalte der WebBox listen. Hier wird nur der relative Pfad
   * ausgehend von www oder home ausgegeben sowie zudem ausgehend
   * von $daten und $basis, sofern der Benutzer die Rolle wbxAdmin hat.
   *
   * Andere Inhalte werden nicht ausgegeben.
   *
   * @param relPath
   * @return
   */
  public List<FileRef> list(String relPath) {
    return listInt(relPath, "name", AbstractComparator.ORDER_ASC);
  }
  
  public FileRef saveTextFile(String relPath, String fileName, String contents) {
    FileRef savedFile = null;
    try {
      FileRef datenRef = getBase();
      File daten = new File(datenRef.getAbsolutePath());
  public List<FileRef> listOrdered(String relPath, String orderBy, String order) {
    return listInt(relPath, orderBy, order);
  }
  /**
   * Inhalte der WebBox listen. Hier wird nur der relative Pfad
   * ausgehend von www oder home ausgegeben sowie zudem ausgehend
   * von $daten und $basis, sofern der Benutzer die Rolle wbxAdmin hat.
   *
   * Andere Inhalte werden nicht ausgegeben.
   *
   * @param relPath
   * @param orderBy 'name'
   * @param order AbstractComparator.ORDER_ASC oder AbstractComparator.ORDER_DESC
   * @return
   */
  private List<FileRef> listInt(String relPath, String orderBy, String order) {
    Bild bild = new Bild();
    List<FileRef> files = new ArrayList();
    if (!relPath.startsWith(".") && !relPath.contains("WEB-INF") && !relPath.contains("META-INF")) {
      if (relPath.length() == 0) {
        FileRef namedPublicFolder = new FileRef(PUB_DIR_NAME, true);
        logger.finer(namedPublicFolder.getAbsolutePath());
        FileRef namedHomeFolder = new FileRef(HOME_DIR_NAME, true);
        logger.finer(namedHomeFolder.getAbsolutePath());
        FileRef namedDavFolder = new FileRef(DAV_DIR_NAME, true);
        logger.finer(namedDavFolder.getAbsolutePath());
        files = new ArrayList();
        files.add(namedHomeFolder);
        files.add(namedPublicFolder);
        files.add(namedDavFolder);
        if (getRequest().isUserInRole(WBX_ADMIN_ROLE)) {
          FileRef namedBaseFolder = new FileRef(WBX_BASE, true);
          FileRef namedDataFolder = new FileRef(WBX_DATA, true);
          files.add(namedBaseFolder);
          files.add(namedDataFolder);
        }
      } else {
        String path = getTargetDir(relPath).getAbsolutePath();
        logger.fine("listing path: " + path);
        File dir = new File(path);
        if (dir.exists()) {
          File[] fileArray = dir.listFiles(new ImgFileFilter());
          if (orderBy != null && orderBy.equalsIgnoreCase("name")) {
            Arrays.sort(fileArray, new FileNameComparator(order));
          } else {
            Arrays.sort(fileArray, new FileNameComparator(AbstractComparator.ORDER_ASC));
          }
          for (int i = 0; i < fileArray.length; i++) {
            logger.fine(fileArray[i].toURI().toString());
            String fname = fileArray[i].toURI().toString().replace("file:/", "");
            if (fileArray[i].isDirectory()) {
              fname = fname.substring(0, fname.length() - 1);
            }
            logger.fine(fname);
            if(!fname.contains("WEB-INF") && !fname.contains("META-INF")) {
              long fLen = fileArray[i].length();
              long lastMod = fileArray[i].lastModified();
              FileRef ref = new FileRef(fname, fileArray[i].isDirectory(), fileArray[i].isHidden(), lastMod, fLen);
              ref.setMimetype(bild.getMimeType(fileArray[i]));
              files.add(ref);
            }
          }
        }
      }
    }
    return files;
  }
  public List<Inhalt> collect(String relativePath, int maxTiefe, int maxAnzahl, int len) {
    WbxUtils wu = new WbxUtils();
    HttpServletRequest req = getRequest();
    String requestUrl = req.getRequestURL().toString();
    String contextPath = req.getContextPath();
    return wu.collectFiles(requestUrl, contextPath, relativePath, maxTiefe, maxAnzahl, len);
  }
  public FileRef newFolder(String relPath, String folderName) {
    if (!relPath.startsWith(".")) {
      logger.finer(relPath);
      String targetPath = null;
      if(relPath.startsWith(PUB_DIR_NAME)) {
        targetPath = PUB_DIR_PATH + getUserName() + "/" + relPath.substring(PUB_DIR_NAME.length()) + "/" + folderName;
      } else if(relPath.startsWith(HOME_DIR_NAME)) {
        targetPath = HOME_DIR_PATH + getUserName() + "/" + relPath.substring(HOME_DIR_NAME.length()) + "/" + folderName;
      } else {
        // kann eigentlich nicht sein..
      }
      logger.finer(targetPath);
      File targetDir = new File(getBase().getAbsolutePath(), targetPath);
      targetDir.mkdirs();
      return new FileRef(targetDir.getAbsolutePath(), true);
    } else {
      return null;
    }
  }
  public String getCode(String relPath, String fileName) {
    String code = null;
    if (!relPath.startsWith(".")) {
      Object p = getRequest().getUserPrincipal();
      if(p instanceof Principal) {
        File userDir = new File(daten, "www/" + ((Principal) p).getName());
        File saveDir = new File(userDir, relPath);
        File targetFile = new File(saveDir, fileName);
        if(!targetFile.exists()) {
          targetFile.getParentFile().mkdirs();
          targetFile.createNewFile();
          FileWriter w = new FileWriter(targetFile);
          w.write(contents);
          w.flush();
          w.close();
          savedFile = new FileRef(
                  targetFile.getAbsolutePath(),
                  targetFile.isDirectory(),
                  targetFile.isHidden(),
                  targetFile.lastModified(),
                  targetFile.length());
      if (p instanceof Principal) {
        Reader reader = null;
        try {
          File targetFile = new File(getTargetDir(relPath), fileName);
          //reader = new InputStreamReader(new FileInputStream(targetFile), "UTF8");
          reader = new FileReader(targetFile);
          StringBuffer buf = new StringBuffer();
          char[] readBuffer = new char[1024];
          int charsRead = reader.read(readBuffer);
          while (charsRead > -1) {
            buf.append(readBuffer, 0, charsRead);
            charsRead = reader.read(readBuffer);
          }
          code = buf.toString();
        } catch (FileNotFoundException ex) {
          Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
          Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
          try {
            reader.close();
          } catch (IOException ex) {
            Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
          }
        }
      }
    }
    return code;
  }
  public String renameFile(String relPath, String fname, String newName) {
    if (!relPath.startsWith(".")) {
      File targetDir = getTargetDir(relPath);
      File file = new File(targetDir, fname);
      if(fname.endsWith(TNServlet.JPEG) || fname.endsWith(TNServlet.JPG) || fname.endsWith(TNServlet.PNG)) {
        renameImgFiles(targetDir, file, newName);
      } else {
        file.renameTo(new File(targetDir, newName));
      }
      return fname + " umbenannt zu " + newName;
    } else {
      return "Pfad nicht erlaubt.";
    }
  }
  public void renameImgFiles(File targetDir, File targetFile, String newName) {
    String alt;
    String neu;
    int newdotpos = newName.lastIndexOf(DOT);
    String newfname = newName.substring(0, newdotpos);
    String newext = newName.substring(newdotpos);
    logger.fine("newfname: " + newfname + ", newext: " + newext);
    String fnameext = targetFile.getName();
    int dotpos = fnameext.lastIndexOf(DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    FileFilter fileFilter = new WildcardFileFilter(fname + "*" + ext);
    File[] files = targetDir.listFiles(fileFilter);
    for (int i = 0; i < files.length; i++) {
      alt = files[i].getName();
      logger.fine("alt: " + alt);
      if(alt.contains(TNServlet.TN)) {
        neu = newfname + TNServlet.TN + newext;
      } else if (alt.contains(TNServlet.KL)) {
        neu = newfname + TNServlet.KL + newext;
      } else if(alt.contains(TNServlet.GR)) {
        neu = newfname + TNServlet.GR + newext;
      } else if(alt.contains(TNServlet.MT)) {
        neu = newfname + TNServlet.MT + newext;
      } else if(alt.contains(TNServlet.SM)) {
        neu = newfname + TNServlet.SM + newext;
      } else {
        neu = newName;
      }
      files[i].renameTo(new File(targetDir, neu));
      logger.fine("neu: " + neu);
    }
  }
  public String deleteFiles(String relPath, List fileNames) {
    String result = null;
    try {
      logger.fine(fileNames.toString());
      if (!relPath.startsWith(DOT)) {
        File targetDir = getTargetDir(relPath);
        for(int i=0; i < fileNames.size(); i++) {
          Object o = fileNames.get(i);
          if(o instanceof ArrayList) {
            ArrayList al = (ArrayList) o;
            logger.fine(al.get(0).toString());
            File targetFile = new File(targetDir, al.get(0).toString());
            logger.fine(targetFile.getAbsolutePath());
            if(targetFile.isDirectory()) {
              FileUtils.deleteDirectory(targetFile);
            } else {
                /*
                Wenn targetFile mit jpg, jpeg oder png endet,
                muss eine Unterfunktion eine Liste aller Dateien bilden,
                die so heissen, also z.B. alle [Dateiname]*.jpg
                */
              String fname = targetFile.getName().toLowerCase();
              if(fname.endsWith(TNServlet.JPEG) || fname.endsWith(TNServlet.JPG) || fname.endsWith(TNServlet.PNG)) {
                deleteImgFiles(targetDir, targetFile);
              } else {
                targetFile.delete();
              }
            }
          }
        }
        result = "deleted";
      }
    } catch (Throwable ex) {
      logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    }
    return result;
  }
  public void deleteImgFiles(File targetDir, File targetFile) {
    String fnameext = targetFile.getName();
    int dotpos = fnameext.lastIndexOf(DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    FileFilter fileFilter = new WildcardFileFilter(fname + "*" + ext);
    File[] files = targetDir.listFiles(fileFilter);
    for (int i = 0; i < files.length; i++) {
        logger.fine(files[i].getName());
        files[i].delete();
    }
  }
  public String copyFiles(String fromPath, String toPath, List fileNames) {
    return copyOrMoveFiles(fromPath, toPath, fileNames, OP_COPY);
  }
  public String moveFiles(String fromPath, String toPath, List fileNames) {
    return copyOrMoveFiles(fromPath, toPath, fileNames, OP_MOVE);
  }
  private String copyOrMoveFiles(String fromPath, String toPath, List fileNames, int operation) {
    String result = null;
    try {
      if (!fromPath.startsWith(".")) {
        File srcDir = getTargetDir(fromPath);
        File targetDir = getTargetDir(toPath);
        Iterator i = fileNames.iterator();
        while(i.hasNext()) {
          Object o = i.next();
          if (o instanceof ArrayList) {
            ArrayList al = (ArrayList) o;
            File srcFile = new File(srcDir, al.get(0).toString());
            if(srcFile.isDirectory()) {
              if(operation == OP_MOVE) {
                FileUtils.moveDirectoryToDirectory(srcFile, targetDir, false);
              } else {
                FileUtils.copyDirectoryToDirectory(srcFile, targetDir);
              }
            } else {
              if(operation == OP_MOVE) {
                String fname = srcFile.getName().toLowerCase();
                if(fname.endsWith(TNServlet.JPEG) || fname.endsWith(TNServlet.JPG) || fname.endsWith(TNServlet.PNG)) {
                  moveImgFilesToDirectory(srcFile, srcDir, targetDir, false);
                } else {
                  FileUtils.moveFileToDirectory(srcFile, targetDir, false);
                }
              } else {
                FileUtils.copyFileToDirectory(srcFile, targetDir);
              }
            }
          }
        }
      }
    } catch (IOException ex) {
      logger.log(Level.SEVERE, null, ex);
      logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    }
    return result;
  }
  private void moveImgFilesToDirectory(File srcFile, File srcDir, File targetDir, boolean createDestDir) throws IOException {
    String fnameext = srcFile.getName();
    int dotpos = fnameext.lastIndexOf(DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    FileFilter fileFilter = new WildcardFileFilter(fname + "*" + ext);
    File[] files = srcDir.listFiles(fileFilter);
    for (int i = 0; i < files.length; i++) {
      logger.fine(files[i].getName());
      FileUtils.moveFileToDirectory(files[i], targetDir, createDestDir);
    }
  }
  public FileRef saveTextFileAs(String relPath, String fileName, String contents) {
    FileRef savedFile = null;
    logger.fine(relPath + " " + fileName);
    if (!relPath.startsWith(".")) {
      //FileRef datenRef = getBase();
      Object p = getRequest().getUserPrincipal();
      if(p instanceof Principal) {
        File targetFile = new File(getTargetDir(relPath), fileName);
        if(targetFile.exists()) {
          targetFile = getNewFileName(targetFile);
        } else {
          targetFile.getParentFile().mkdirs();
        }
        saveToFile(targetFile, contents);
      }
    }
    return savedFile;
  }
  
  private File getWebappsDir() {
    File cfile = new File(this.getClass().getResource(
            this.getClass().getSimpleName() + ".class").getFile());
    String path = cfile.getAbsolutePath();
    return new File(path.substring(0, path.indexOf(getRequest().getContextPath())));
  private File getNewFileName(File file) {
    File dir = file.getParentFile();
    String targetName = file.getName();
    logger.fine("targetName: " + targetName);
    String ext = "";
    int dotpos = targetName.indexOf(".");
    if(dotpos > -1) {
      ext = targetName.substring(dotpos);
      targetName = targetName.substring(0, dotpos);
    }
    logger.fine("targetName: " + targetName + ", ext: " + ext);
    int i = 1;
    while(file.exists()) {
      StringBuffer buf = new StringBuffer();
      buf.append(targetName);
      buf.append("-");
      buf.append(i);
      if(ext.length() > 0) {
        buf.append(ext);
      }
      file = new File(dir, buf.toString());
      i++;
    }
    logger.fine("new file: " + file.getName());
    return file;
  }
  private FileRef saveToFile(File targetFile, String contents) {
    FileRef savedFile = null;
    try {
      targetFile.createNewFile();
      FileWriter w = new FileWriter(targetFile);
      //w.write(StringEscapeUtils.unescapeHtml(contents));
      w.write(contents);
      w.flush();
      w.close();
      savedFile = new FileRef(
              targetFile.getAbsolutePath(),
              targetFile.isDirectory(),
              targetFile.isHidden(),
              targetFile.lastModified(),
              targetFile.length());
    } catch (IOException ex) {
      logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    }
    return savedFile;
  }
  
}
  public FileRef saveTextFile(String relPath, String fileName, String contents) {
    FileRef savedFile = null;
    logger.fine(relPath + " " + fileName);
    if (!relPath.startsWith(".")) {
      //FileRef datenRef = getBase();
      Object p = getRequest().getUserPrincipal();
      if(p instanceof Principal) {
        File targetFile = new File(getTargetDir(relPath), fileName);
        if(targetFile.exists()) {
          /*
            muss delete() sein?
            pruefen: ueberschreibt der FileWriter den alteen Inhalt oder
            entsteht eine unerwuenschte Mischung aus altem und neuem
            Inhalt?
          */
          targetFile.delete();
        } else {
          targetFile.getParentFile().mkdirs();
        }
        saveToFile(targetFile, contents);
      }
    }
    return savedFile;
  }
  public String bildVerkleinern(String relPath, String bildName) {
    if (!relPath.startsWith(".")) {
      File dir = getTargetDir(relPath);
      File original = new File(dir, bildName);
      Bild bild = new Bild();
      //for (int i = 0; i < Bild.GR.length; i++) {
      //int gr = bild.getVariantenGroesse(i);
      String ext = "";
      String nurname = bildName;
      int dotpos = bildName.indexOf(".");
      if (dotpos > -1) {
        ext = bildName.substring(dotpos);
        nurname = bildName.substring(0, dotpos);
      }
          // 120, 240, 500, 700, 1200
      for (int i = 0; i < Bild.GR.length; i++) {
        StringBuffer buf = new StringBuffer();
        buf.append(nurname);
        buf.append(bild.getVariantenName(i));
        buf.append(ext);
        File newImgFile = new File(dir, buf.toString());
        try {
          Thumbnails.of(original)
                  .size(bild.getVariantenGroesse(i), bild.getVariantenGroesse(i))
                  .keepAspectRatio(true)
                  .outputQuality(0.7)
                  .toFile(newImgFile);
        } catch (IOException ex) {
          logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
        }
      }
      return "ok";
    } else {
      return "Pfad micht erlaubt.";
    }
  }
  public String bildRotieren(String relPath, String bildName) {
    if (!relPath.startsWith(".")) {
      File dir = getTargetDir(relPath);
      File original = new File(dir, bildName);
      String ext = "";
      String nurname = bildName;
      int dotpos = bildName.indexOf(".");
      if (dotpos > -1) {
        ext = bildName.substring(dotpos);
        nurname = bildName.substring(0, dotpos);
      }
      StringBuffer buf = new StringBuffer();
      buf.append(nurname);
      buf.append("-rot");
      buf.append(ext);
      File newImgFile = new File(dir, buf.toString());
      logger.fine("original: " + original.getAbsolutePath() + " newImgFile: " + newImgFile.getAbsolutePath());
      try {
        Thumbnails.of(original)
                .scale(1)
                .rotate(90)
                .toFile(newImgFile);
      } catch (IOException ex) {
        logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
      }
      return "ok";
    } else {
      return "Pfad micht erlaubt.";
    }
  }
  /* --------- ZIP entpacken ---------------- */
  public String extractZipfile(String relPath, String filename) {
    String result = null;
    if (!relPath.startsWith(".")) {
      try {
        File targetDir = getTargetDir(relPath);
        File archive = new File(targetDir, filename);
        if(extract(archive)) {
          result = "ok";
        } else {
          result = "error while extracting";
        }
      } catch(Exception ex) {
        result = ex.getLocalizedMessage();
        logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
      }
    }
    return result;
  }
  /**
    * extract a given ZIP archive to the folder respective archive resides in
    * @param archive  the archive to extract
    * @throws Exception
    */
   private boolean extract(File archive) throws Exception {
      ZipFile zipfile = new ZipFile(archive);
      Enumeration en = zipfile.entries();
      while(en.hasMoreElements()) {
         ZipEntry zipentry = (ZipEntry) en.nextElement();
         unzip(zipfile, zipentry, archive.getParent());
      }
      zipfile.close();
      return true;
   }
   /**
    * unzip a given entry of a given zip file to a given location
    * @param zipfile  the zip file to read an entry from
    * @param zipentry  the zip entry to read
    * @param destPath  the path to the destination location for the extracted content
    * @throws IOException
    */
   private void unzip(ZipFile zipfile, ZipEntry zipentry, String destPath) throws IOException {
      byte buf[] = new byte[1024];
      InputStream is = zipfile.getInputStream(zipentry);
      String outFileName = destPath + File.separator + zipentry.getName();
      File file = new File(outFileName);
      if(!zipentry.isDirectory()) {
         file.getParentFile().mkdirs();
         if(!file.exists())
            file.createNewFile();
         FileOutputStream fos = new FileOutputStream(file);
         int i = is.read(buf, 0, 1024);
         while(i > -1) {
            fos.write(buf, 0, i);
            i = is.read(buf, 0, 1024);
         }
         fos.close();
         is.close();
      } else {
         file.mkdirs();
      }
   }
  /* ------------- Ornder als ZIP packen --------------- */
  public String packFolder(String relPath) {
    if (!relPath.startsWith(".")) {
      try {
        File targetDir = getTargetDir(relPath);
        File parentDir = targetDir.getParentFile();
        StringBuffer fname = new StringBuffer();
        fname.append(targetDir.getName());
        fname.append(".zip");
        File archiveFile = new File(parentDir, fname.toString());
        FileRef folderToPack = new FileRef(targetDir.getAbsolutePath());
        FileRef archive = new FileRef(archiveFile.getAbsolutePath());
        pack(folderToPack, archive);
        return "ok";
      } catch(Exception ex) {
        String result = ex.getLocalizedMessage();
        logger.log(Level.SEVERE, result, ex);
        return result;
      }
    } else {
      return "Falsche relative Pfadangabe";
    }
  }
   /**
    * pack the contents of a given folder into a new ZIP compressed archive
    * @param folder  the folder to pack
    * @param archive  the archive to create from the given files
    * @throws Exception
    */
   private boolean pack(FileRef folder, FileRef archive) throws Exception {
      File file = new File(archive.getAbsolutePath());
      FileOutputStream fos = new FileOutputStream(file);
      CheckedOutputStream checksum = new CheckedOutputStream(fos, new Adler32());
      ZipOutputStream zos = new ZipOutputStream(checksum);
      pack(zos, folder.getAbsolutePath(), "");
      zos.flush();
      zos.finish();
      zos.close();
      fos.flush();
      fos.close();
      return true;
   }
   /**
    * go through the given file structure recursively
    * @param zipFile  the ZIP file to write to
    * @param srcDir  the directory to pack during this cycle
    * @param subDir  the subdirectory to append to names of file entries inside the archive
    * @throws IOException
    */
   private void pack(ZipOutputStream zipFile, String srcDir, String subDir) throws IOException {
      File[] files = new File(srcDir).listFiles();
      for(int i = 0; i < files.length; i++) {
         if(files[i].isDirectory()) {
            pack(zipFile, files[i].getAbsolutePath(), subDir + File.separator + files[i].getName());
         }
         else {
            packFile(zipFile, subDir, files[i]);
         }
      }
   }
   /**
    * pack a given file
    * @param zipFile  the ZIP archive to pack to
    * @param dir  the directory name to append to name of file entry inside archive
    * @param file  the file to pack
    * @throws IOException
    */
   private void packFile(ZipOutputStream zipFile, String dir, File file) throws IOException
   {
      FileInputStream fileinputstream = new FileInputStream(file);
      byte buf[] = new byte[fileinputstream.available()];
      fileinputstream.read(buf);
      String dirWithSlashes = dir.replace('\\', '/');
      //System.out.println("zipping " + dirWithSlashes + "/" + file.getName());
      ZipEntry ze = new ZipEntry(dirWithSlashes + "/" + file.getName());
      ze.setMethod(ZipEntry.DEFLATED);
      zipFile.putNextEntry(ze);
      zipFile.write(buf, 0, buf.length);
      zipFile.closeEntry();
      fileinputstream.close();
   }
  /* ---- Hilfsfunktionen ---- */
}