/*
|
http-cm - File management extensions to jdk.httpserver
|
Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
*/
|
package de.uhilger.httpserver.cm;
|
|
import com.sun.net.httpserver.Authenticator;
|
import com.sun.net.httpserver.HttpExchange;
|
import de.uhilger.httpserver.base.HttpResponder;
|
import de.uhilger.httpserver.base.HttpHelper;
|
import de.uhilger.httpserver.base.handler.FileHandler;
|
import de.uhilger.httpserver.cm.actor.Lister;
|
import de.uhilger.httpserver.cm.actor.Writer;
|
import de.uhilger.httpserver.oauth.BearerAuthenticator;
|
import java.io.IOException;
|
|
/**
|
* <p>Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
|
* Dateisystems.</p>
|
*
|
* <p>HTTP GET fuer eine Datei innerhalb dieses Ordners liefert den Dateiinhalt aus</p>
|
*
|
* <p>HTTP GET fuer einen Ordner liefert eine Liste von dessen Inhalt in JSON</p>
|
*
|
* <p>HTTP PUT fuer eine Datei ueberschreibt eine bestehende Datei mit dem im Body
|
* uebergebenen Inhalt oder legt eine Datei mit diesem Inhalt an</p>
|
*
|
* <p>HTTP POST fuer eine Datei legt eine neue Datei mit dem im Body uebergebenen
|
* Inhalt an oder erzeugt eine neue Datei mit einer laufenden Nummer, falls
|
* diese Datei schon existiert</p>
|
*
|
* <p>HTTP POST fuer einen Ordner legt einen neuen Ordner an wenn er noch nicht
|
* existiert oder erzeugt einen HTTP-Fehler 422</p>
|
*
|
* <p>HTTP DELETE loescht die Liste der Dateien und Ordner im Body</p>
|
*
|
* <p>HTTP PUT ?copyFrom=pfad 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.</p>
|
*
|
* <p>HTTP PUT ?moveFrom=pfad 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.</p>
|
*
|
* <p>HTTP PUT mit ?duplicate legt eine Kopie der Datei an</p>
|
*
|
* <p>HTTP PUT mit '?renameTo=neuer Name' benennt die Datei oder den Ordner um,
|
* sofern der neue Name noch nicht vergeben ist</p>
|
*
|
* <p>HTTP PUT mit '?zip' packt den Ordner</p>
|
*
|
* <p>HTTP PUT mit '?unzip' entpackt eine Datei</p>
|
*
|
* <p>Namenskonventionen:<br>
|
* Ein Pfad mit Schraegstrich ('/') am Ende bezeichnet einen Ordner<br>
|
* Ein Pfad ohne Schraegstrich ('/') am Ende bezeichnet eine Datei</p>
|
*
|
* @author Ulrich Hilger
|
* @version 1, 13. Mai 2021
|
*/
|
public class FileManager extends FileHandler {
|
|
/*
|
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")};
|
*/
|
|
//public static final String UNWANTED_PATTERN = "[^a-zA-Z_0-9 ]";
|
/* HTTP Methoden */
|
|
public static final String UTF8 = "UTF-8";
|
|
public static final String STR_SLASH = "/";
|
public static final String STR_DOT = ".";
|
|
public static final String P_COPY = "copyFrom";
|
public static final String P_MOVE = "moveFrom";
|
public static final String P_DUPLICATE = "duplicate";
|
public static final String P_RENAME = "renameTo";
|
public static final String P_ZIP = "zip";
|
public static final String P_UNZIP = "unzip";
|
|
public static final int OP_COPY = 1;
|
public static final int OP_MOVE = 2;
|
public static final int OP_DELETE = 3;
|
|
public static final String ATTR_ROLE = "role";
|
|
@Override
|
public void handle(HttpExchange e) throws IOException {
|
Authenticator a = e.getHttpContext().getAuthenticator();
|
if(a instanceof BearerAuthenticator) {
|
BearerAuthenticator auth = (BearerAuthenticator) a;
|
//Realm realm = auth.getRealm();
|
String userId = e.getPrincipal().getUsername();
|
if(auth.hasRole(userId, e.getHttpContext().getAttributes().get(ATTR_ROLE).toString())) {
|
String method = e.getRequestMethod();
|
//logger.fine("method: " + method);
|
HttpHelper helper = new HttpHelper();
|
switch (method) {
|
case HttpHelper.HTTP_GET:
|
String path = e.getRequestURI().toString();
|
if (path.endsWith(STR_SLASH)) {
|
String json = new Lister().liste(helper.getFileName(e),
|
e.getHttpContext().getPath(),
|
e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(),
|
path);
|
if(null != json) {
|
HttpResponder r = new HttpResponder();
|
r.antwortSenden(e, SC_OK, json);
|
} else {
|
emptyListResponse(e);
|
}
|
} else {
|
new Lister().b64Action(helper.getFileName(e),
|
e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
|
super.handle(e);
|
}
|
break;
|
case HttpHelper.HTTP_PUT:
|
new Writer().put(e, helper);
|
break;
|
case HttpHelper.HTTP_POST:
|
new Writer().speichern(e, helper);
|
break;
|
case HttpHelper.HTTP_DELETE:
|
new Writer().loeschen(e, helper);
|
break;
|
}
|
} else {
|
new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
|
}
|
} else {
|
new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
|
}
|
}
|
|
private void emptyListResponse(HttpExchange e) throws IOException {
|
HttpResponder r = new HttpResponder();
|
String json = "{}";
|
//logger.log(Level.FINE, "json: ''{0}''", json);
|
r.antwortSenden(e, SC_OK, json);
|
}
|
}
|