Dateien verwalten mit Modul jdk.httpserver
ulrich
2024-01-15 020a97355fdd8133da6cfd490b7b1e9618a1eb06
src/de/uhilger/httpserver/cm/FileManager.java
@@ -31,7 +31,6 @@
import de.uhilger.httpserver.oauth.BearerAuthenticator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -43,15 +42,9 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
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;
/**
 * <p>Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
@@ -105,9 +98,6 @@
 */
public class FileManager extends FileHandler implements ThreadListener {
  /* Der Logger fuer diesen ListFileHandler */
  private static final Logger logger = Logger.getLogger(FileManager.class.getName());
  /*
  private static final String[] specialChars = {new String("\u00c4"), new String("\u00d6"),
    new String("\u00dc"), new String("\u00e4"), new String("\u00f6"), new String("\u00fc"), new String("\u00df")};
@@ -158,7 +148,7 @@
      String userId = e.getPrincipal().getUsername();
      if(auth.hasRole(userId, e.getHttpContext().getAttributes().get(ATTR_ROLE).toString())) {
        String method = e.getRequestMethod();
        logger.fine("method: " + method);
        //logger.fine("method: " + method);
        HttpHelper helper = new HttpHelper();
        switch (method) {
          case HttpHelper.HTTP_GET:
@@ -187,7 +177,7 @@
    if (query != null) {
      String[] params = query.split("=");
      for (String param : params) {
        logger.fine("param: " + param);
        //logger.fine("param: " + param);
      }
      switch (params[0]) {
        case P_COPY:
@@ -199,19 +189,19 @@
        case P_DUPLICATE:
          if(Boolean.parseBoolean(params[1])) {
            String neuerDateiName = duplizieren(exchange, helper);
            logger.fine("neuer Name: " + neuerDateiName);
            //logger.fine("neuer Name: " + neuerDateiName);
            standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          }
          break;
        case P_RENAME:
          String neuerDateiName = umbenennen(exchange, helper, params[1]);
          logger.fine("neuer Name: " + neuerDateiName);
          //logger.fine("neuer Name: " + neuerDateiName);
          standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          break;
        case P_ZIP:
          String path = exchange.getRequestURI().toString();
          logger.fine(path);
          String antwort = packFolder(helper.getFileName(exchange), path, exchange);
          //logger.fine(path);
          String antwort = new Zipper().packFolder(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
@@ -220,8 +210,8 @@
          break;
        case P_UNZIP:
          path = exchange.getRequestURI().toString();
          logger.fine(path);
          antwort = extractZipfile(helper.getFileName(exchange), path, exchange);
          //logger.fine(path);
          antwort = new Unzipper().extractZipfile(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
@@ -259,13 +249,13 @@
  private void liste(HttpExchange e, HttpHelper helper) throws IOException {
    String path = e.getRequestURI().toString();
    logger.fine(path);
    //logger.fine(path);
    String fName = helper.getFileName(e);
    String dirListPath = e.getHttpContext().getPath() + fName;
    if (path.endsWith(STR_SLASH)) {      
      logger.fine("fName: " + fName);
      //logger.fine("fName: " + fName);
      File dir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
      logger.fine("absPath: " + dir.getAbsolutePath());
      //logger.fine("absPath: " + dir.getAbsolutePath());
      File[] files = dir.listFiles(new ImageFileFilter());
      if(files != null && files.length > 0) {
        Arrays.sort(files);
@@ -323,7 +313,7 @@
        String fromName = fName.replace(ImageActor.B64, "");
        File fromFile = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fromName);
        File toFile = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
        logger.fine("from " + fromFile.getAbsolutePath() + ", to " + toFile.getAbsolutePath());
        //logger.fine("from " + fromFile.getAbsolutePath() + ", to " + toFile.getAbsolutePath());
        if(!toFile.exists()) {
          actor.b64Image(fromFile, toFile);
        }
@@ -387,20 +377,20 @@
  private void emptyListResponse(HttpExchange e) throws IOException {
    HttpResponder r = new HttpResponder();
    String json = "{}";
    logger.log(Level.FINE, "json: ''{0}''", json);
    //logger.log(Level.FINE, "json: ''{0}''", json);
    r.antwortSenden(e, SC_OK, json);        
  }
  private void speichern(HttpExchange exchange, HttpHelper helper) throws IOException {
    String fileName = helper.getFileName(exchange);
    logger.info("fileName: " + fileName);
    //logger.info("fileName: " + fileName);
    // file ist die Datei, um die es geht
    File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fileName);
    String method = exchange.getRequestMethod();
    if (fileName.endsWith(STR_SLASH)) {
      logger.info("neuer Ordner: " + file.getAbsolutePath());
      //logger.info("neuer Ordner: " + file.getAbsolutePath());
      // neuen Ordner erstellen oder ablehnen, wenn der Ordner schon existiert
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (!file.exists()) {
@@ -415,7 +405,7 @@
        standardHeaderUndAntwort(exchange, SC_METHOD_NOT_ALLOWED, antwort);        
      }
    } else {
      logger.info("Datei speichern: " + file.getAbsolutePath());
      //logger.info("Datei speichern: " + file.getAbsolutePath());
      // Datei speichern
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (file.exists()) {
@@ -447,9 +437,9 @@
      // dekodieren
      String content = sb.toString();
      logger.fine(content);
      //logger.fine(content);
      String decoded = URLDecoder.decode(content, UTF8);
      logger.fine(decoded);
      //logger.fine(decoded);
      // in Datei schreiben
      byte[] bytes = decoded.getBytes();
@@ -466,7 +456,7 @@
  }
  private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException {
    logger.fine("quelle: " + quelle + ", ziel: " + ziel);
    //logger.fine("quelle: " + quelle + ", ziel: " + ziel);
    String[] dateiNamen = dateiliste(exchange);
    copyOrMoveFiles(quelle, ziel, dateiNamen, op, exchange);
    standardHeaderUndAntwort(exchange, SC_OK, "Dateien verarbeitet.");
@@ -478,9 +468,9 @@
    File targetDir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), toPath);
    for (String fileName : fileNames) {
      File srcFile = new File(srcDir, fileName);
      logger.fine("srcFile: " + srcFile);
      //logger.fine("srcFile: " + srcFile);
      if (srcFile.isDirectory()) {
        logger.fine("srcFile is directory.");
        //logger.fine("srcFile is directory.");
        OrdnerBearbeiter bearbeiter = new OrdnerBearbeiter();
        bearbeiter.setTargetDir(targetDir.toPath());
        bearbeiter.setOperation(operation);
@@ -518,7 +508,7 @@
  private String[] dateiliste(HttpExchange exchange) throws IOException {
    String body = new HttpHelper().bodyLesen(exchange);
    logger.fine("dateien: " + body);
    //logger.fine("dateien: " + body);
    Gson gson = new Gson();
    return gson.fromJson(body, String[].class);
  }
@@ -562,19 +552,19 @@
    int newdotpos = newName.lastIndexOf(STR_DOT);
    String newfname = newName.substring(0, newdotpos);
    String newext = newName.substring(newdotpos);
    logger.fine("newfname: " + newfname + ", newext: " + newext);
    //logger.fine("newfname: " + newfname + ", newext: " + newext);
    
    String fnameext = targetFile.getName();
    int dotpos = fnameext.lastIndexOf(STR_DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    //logger.fine("fname: " + fname + ", ext: " + ext);
    
    DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
    for (Path path : stream) {
      logger.fine(path.getFileName().toString());
      //logger.fine(path.getFileName().toString());
      alt = path.getFileName().toString();
      logger.fine("alt: " + alt);
      //logger.fine("alt: " + alt);
      if(alt.contains(ImageActor.TN)) {
        neu = newfname + ImageActor.TN + newext;
      } else if (alt.contains(ImageActor.KL)) {
@@ -599,13 +589,13 @@
  private String deleteFiles(String relPath, List<String> fileNames, HttpExchange e) {
    String result = null;
    try {
      logger.fine(fileNames.toString());
      //logger.fine(fileNames.toString());
      if (!relPath.startsWith(STR_DOT)) {
        File targetDir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), relPath); // getTargetDir(relPath);
        logger.fine("targetDir: " + targetDir);
        //logger.fine("targetDir: " + targetDir);
        for (String fileName : fileNames) {
          File targetFile = new File(targetDir, fileName);
          logger.fine(targetFile.getAbsolutePath());
          //logger.fine(targetFile.getAbsolutePath());
          if (targetFile.isDirectory()) {
            OrdnerBearbeiter bearbeiter = new OrdnerBearbeiter();
            bearbeiter.setOperation(OP_DELETE);
@@ -629,7 +619,7 @@
        result = "deleted";
      }
    } catch (Throwable ex) {
      logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
      //logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    }
    return result;
  }
@@ -639,10 +629,10 @@
    int dotpos = fnameext.lastIndexOf(STR_DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    //logger.fine("fname: " + fname + ", ext: " + ext);
    DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
    for (Path path : stream) {
      logger.fine(path.getFileName().toString());
      //logger.fine(path.getFileName().toString());
      Files.delete(path);
    }
    stream.close();
@@ -653,11 +643,11 @@
    int dotpos = fnameext.lastIndexOf(STR_DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    logger.fine("fname: " + fname + ", ext: " + ext);
    //logger.fine("fname: " + fname + ", ext: " + ext);
    Path targetPath = targetDir.toPath();
    DirectoryStream<Path> stream = Files.newDirectoryStream(srcDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
    for (Path path : stream) {
      logger.fine(path.getFileName().toString());
      //logger.fine(path.getFileName().toString());
      //Files.delete(path);
      Files.move(path, targetPath.resolve(path.getFileName()));
    }
@@ -670,185 +660,7 @@
    new HttpResponder().antwortSenden(exchange, status, antwort);
  }  
  
  /* --------- ZIP entpacken ---------------- */
  public String extractZipfile(String fName, String relPath, HttpExchange e) {
    logger.fine("fName: " + fName + ", relPath: " + relPath);
    String result = null;
    if (!relPath.startsWith(".")) {
      try {
        //File targetDir = new File(fileBase, relPath);
        //File targetDir = getTargetDir(relPath);
        File archive = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
        if(extract(archive)) {
          result = "ok";
        } else {
          result = "error while extracting";
        }
      } catch(Exception ex) {
        result = ex.getLocalizedMessage();
        logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
      }
    } else {
      result = "Falsche relative Pfadangabe.";
    }
    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();
      }
   }
  /* --------------- Ordner packen ----------------- */
  /**
   * Einen Ordner packen.
   *
   * Als Ziel wird eine neue Datei mit Dateiendung '.zip' erzeugt, die so
   * heisst wie der Ordner, der gapckt werden soll. Die Datei mit
   * dem gepackten Ordnerinhalt wird in dem Ordner angelegt, der den zu
   * packenden Ordner enthaelt.
   *
   * @param fName  Name des zu packenden Ordners
   * @param relPath  relativer Pfad zum Ordner, der gepackt werden soll
   * @return die Meldung mit dem Ergebnis. Wenn die Meldung nicht "ok" lautet
   * wurde die ZIP-Datei nicht erzeugt und die Meldung nennt den Grund.
   */
  public String packFolder(String fName, String relPath, HttpExchange e) {
    if (!relPath.startsWith(".")) {
      try {
        //String fName = getFileName(e);
        logger.fine("fName: " + fName);
        if (fName.endsWith(STR_SLASH)) {
          File dir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
          if(dir.isDirectory()) {
            logger.fine("absPath: " + dir.getAbsolutePath());
            File parentDir = dir.getParentFile();
            StringBuilder fname = new StringBuilder();
            fname.append(dir.getName());
            fname.append(".zip");
            File archiveFile = new File(parentDir, fname.toString());
            pack(dir.getAbsolutePath(), archiveFile.getAbsolutePath());
            return "ok";
          } else {
            return "kein Ordner";
          }
        } else {
          return "kein Ordner";
        }
      } 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  absolute path and name of the folder to pack
    * @param archive  absolute path and name of the archive to create from the given files
    * @throws Exception
    */
   private boolean pack(String folder, String archive) throws Exception {
      File file = new File(archive);
      FileOutputStream fos = new FileOutputStream(file);
      CheckedOutputStream checksum = new CheckedOutputStream(fos, new Adler32());
      ZipOutputStream zos = new ZipOutputStream(checksum);
      pack(zos, folder, "");
      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();
   }
  
  
}