/* neon-fm - Dateiverwaltung fuer neon Copyright (C) 2024 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.uhilger.neon.fm; import com.sun.net.httpserver.HttpExchange; import de.uhilger.neon.FileServer; import de.uhilger.neon.HttpResponder; import de.uhilger.fm.Duplicator; import de.uhilger.fm.Mover; import de.uhilger.fm.Renamer; import de.uhilger.fm.Inflator; import de.uhilger.fm.Deflator; import java.io.IOException; /** * Aenderungen an bestehenden Dateien. * * @author Ulrich Hilger * @version 0.1, 07.11.2024 */ public class FileManipulator extends AbstractFileActor { private static final String P_RENAME = "renameTo"; private static final String P_COPY = "copyFrom"; private static final String P_MOVE = "moveFrom"; private static final String P_DUPLICATE = "duplicate"; private static final String P_ZIP = "zip"; private static final String P_UNZIP = "unzip"; /** *

* Diese Methode ist als Reaktion auf einen HTTP PUT Aufruf an folgende URLs gedacht

* *
   * PUT [url]
   * [body]
   * 
* *
   * - Inhalt einer einzelnen Datei anlegen oder ueberschreiben: url=ziel, Dateiinhalt im Body
   * - Liste mit Dateien kopieren (?copyFrom=quelle): url=ziel, Dateiliste im Body
   * - Liste mit Dateien verschieben (?moveFrom=quelle): url=Ziel, Dateiliste im Body
   * - einzelne Datei duplizieren (?duplicate): url=Zieldatei
   * - einzelne Datei umbenennen (?renameTo=neuer Name): url=Datei oder -ordner
   * - Ordner packen (?zip): url=Ordner
   * - Zip-Datei entpacken (?unzip): url=Datei
   * 
* * *
   * HTTP PUT /pfad/zur/datei.txt ueberschreibt eine bestehende Datei mit dem im Body
   * uebergebenen Inhalt oder legt eine Datei mit diesem Inhalt an
   * 
   * HTTP PUT /pfad/zum/zielordner?copyFrom=/pfad/zum/quellordner
   * kopiert die Liste der Datei- oder Ordnernamen im Body
   * der Anfrage vom Pfad in 'copyFrom' zum Pfad dieser Anfrage. Jede Datei, die
   * im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
   * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
   * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
   * Nummer, dann wird der Quellordner ans Ziel kopiert.
   *
   * HTTP PUT /pfad/zum/zielordner?moveFrom=/pfad/zum/quellordner
   * verschiebt die Liste der Datei- oder Ordnernamen im
   * Body der Anfrage vom Pfad in 'moveFrom' zum Pfad dieser Anfrage. Jede Datei,
   * die im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
   * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
   * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
   * Nummer, dann wird der Quellordner ans Ziel kopiert.
   *
   * HTTP PUT /pfad/zur/datei.txt?duplicate legt eine Kopie der Datei an
   *
   * HTTP PUT /pfad/zur/datei.txt?renameTo=neuer Name benennt die Datei oder den Ordner um,
   * sofern der neue Name noch nicht vergeben ist
   *
   * HTTP PUT /pfad/zum/ordner?zip' packt den Ordner
   *
   * HTTP PUT /pfad/zur/datei.zip?unzip' entpackt eine Datei
   *
   * Eine Dateiliste im Body sieht z.B. wie folgt aus
   * ["test.txt","dok","weitere-datei.bin","bild.jpg"]
   *
   * 
* * @param exchange das Objekt mit Infos zu HTTP-Request, -Response usw. */ public void change(HttpExchange exchange) { try { init(exchange); String query = exchange.getRequestURI().getQuery(); if (query != null) { String[] params = query.split(FileServer.STR_EQUAL); switch (params[0]) { case P_RENAME: h.inspectFileName(params[1]); String neuerDateiName = new Renamer().rename(/*fileName, */params[1], file); antwort(exchange, HttpResponder.SC_OK, neuerDateiName); break; case P_COPY: h.inspectFileName(params[1]); copyOrMove(exchange, params[1], fileName, Mover.OP_COPY); break; case P_MOVE: h.inspectFileName(params[1]); copyOrMove(exchange, params[1], fileName, Mover.OP_MOVE); break; case P_DUPLICATE: if (Boolean.parseBoolean(params[1])) { String dup = new Duplicator().duplizieren(base, fileName); //logger.fine("neuer Name: " + neuerDateiName); antwort(exchange, HttpResponder.SC_OK, dup); } break; case P_ZIP: //String path = exchange.getRequestURI().toString(); zipAntwort(exchange, new Deflator().packFolder(fileName, /*path, */ base)); break; case P_UNZIP: //String path = exchange.getRequestURI().toString(); zipAntwort(exchange, new Inflator().extractZipfile(fileName, /*path,*/ base)); break; default: antwort(exchange, HttpResponder.SC_NOT_FOUND, "ungueltige Anfrage"); break; } } else { if (fileName.endsWith(FileServer.STR_SLASH)) { antwort(exchange, HttpResponder.SC_METHOD_NOT_ALLOWED, "PUT nicht erlaubt, POST verwenden."); } else { speichern(exchange); } } } catch (IOException | IllegalArgumentException ex) { fehlerAntwort(exchange, ex); } finally { free(); } } private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException { String[] dateiNamen = dateiliste(exchange); if (op == Mover.OP_COPY) { new Mover().copy(quelle, ziel, dateiNamen, base); } else { new Mover().move(quelle, ziel, dateiNamen, base); } //new Mover().copyOrMoveFiles(quelle, ziel, dateiNamen, op, base); antwort(exchange, HttpResponder.SC_OK, "Dateien verarbeitet."); } private void zipAntwort(HttpExchange exchange, String antw) throws IOException { if (antw.equalsIgnoreCase("ok")) { antwort(exchange, HttpResponder.SC_OK, antw); } else { antwort(exchange, HttpResponder.SC_UNPROCESSABLE_ENTITY, antw); } } }