/*
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 .
*/
package de.uhilger.httpserver.cm;
import com.google.gson.Gson;
import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Headers;
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.image.Datei;
import de.uhilger.httpserver.image.ImageActor;
import de.uhilger.httpserver.image.ImageThread;
import de.uhilger.httpserver.image.ImageThread.ThreadListener;
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;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
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;
/**
*
Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
* Dateisystems.
*
* HTTP GET fuer eine Datei innerhalb dieses Ordners liefert den Dateiinhalt aus
*
* HTTP GET fuer einen Ordner liefert eine Liste von dessen Inhalt in JSON
*
* HTTP PUT fuer eine Datei ueberschreibt eine bestehende Datei mit dem im Body
* uebergebenen Inhalt oder legt eine Datei mit diesem Inhalt an
*
* 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
*
* HTTP POST fuer einen Ordner legt einen neuen Ordner an wenn er noch nicht
* existiert oder erzeugt einen HTTP-Fehler 422
*
* HTTP DELETE loescht die Liste der Dateien und Ordner im Body
*
* 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.
*
* 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.
*
* HTTP PUT mit ?duplicate legt eine Kopie der Datei an
*
* HTTP PUT mit '?renameTo=neuer Name' benennt die Datei oder den Ordner um,
* sofern der neue Name noch nicht vergeben ist
*
* HTTP PUT mit '?zip' packt den Ordner
*
* HTTP PUT mit '?unzip' entpackt eine Datei
*
* Namenskonventionen:
* Ein Pfad mit Schraegstrich ('/') am Ende bezeichnet einen Ordner
* Ein Pfad ohne Schraegstrich ('/') am Ende bezeichnet eine Datei
*
* @author Ulrich Hilger
* @version 1, 13. Mai 2021
*/
public class FileManager extends FileHandler implements ThreadListener {
/*
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";
private final List waitingThreads;
private final int maxThreads;
private int threadCount;
//private String role;
//public FileManager(String absoluteDirectoryPathAndName, String role, String ctx) {
public FileManager() {
//super(absoluteDirectoryPathAndName, ctx);
//super(absoluteDirectoryPathAndName);
waitingThreads = new ArrayList();
maxThreads = 4;
threadCount = 0;
//this.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:
liste(e, helper);
break;
case HttpHelper.HTTP_PUT:
put(e, helper);
break;
case HttpHelper.HTTP_POST:
speichern(e, helper);
break;
case HttpHelper.HTTP_DELETE:
loeschen(e, helper);
break;
}
} else {
standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
}
} else {
standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
}
}
private void put(HttpExchange exchange, HttpHelper helper) throws IOException {
String query = exchange.getRequestURI().getQuery();
if (query != null) {
String[] params = query.split("=");
for (String param : params) {
//logger.fine("param: " + param);
}
switch (params[0]) {
case P_COPY:
copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_COPY);
break;
case P_MOVE:
copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_MOVE);
break;
case P_DUPLICATE:
if(Boolean.parseBoolean(params[1])) {
String neuerDateiName = duplizieren(exchange, helper);
//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);
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);
if(antwort.equalsIgnoreCase("ok")) {
standardHeaderUndAntwort(exchange, SC_OK, antwort);
} else {
standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
}
break;
case P_UNZIP:
path = exchange.getRequestURI().toString();
//logger.fine(path);
antwort = extractZipfile(helper.getFileName(exchange), path, exchange);
if(antwort.equalsIgnoreCase("ok")) {
standardHeaderUndAntwort(exchange, SC_OK, antwort);
} else {
standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
}
break;
}
} else {
speichern(exchange, helper);
}
}
public class DirList {
private String pfad;
private List dateien;
public String getPfad() {
return pfad;
}
public void setPfad(String pfad) {
this.pfad = pfad;
}
public List getDateien() {
return dateien;
}
public void setDateien(List dateien) {
this.dateien = dateien;
}
}
private void liste(HttpExchange e, HttpHelper helper) throws IOException {
String path = e.getRequestURI().toString();
//logger.fine(path);
String fName = helper.getFileName(e);
String dirListPath = e.getHttpContext().getPath() + fName;
if (path.endsWith(STR_SLASH)) {
//logger.fine("fName: " + fName);
File dir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
//logger.fine("absPath: " + dir.getAbsolutePath());
File[] files = dir.listFiles(new ImageFileFilter());
if(files != null && files.length > 0) {
Arrays.sort(files);
ArrayList liste = new ArrayList();
for (File file : files) {
Datei datei = new Datei();
String dateiName = file.getName();
datei.setName(dateiName);
if (file.isDirectory()) {
datei.setTyp(Datei.TYP_ORDNER);
} else {
datei.setTyp(Datei.TYP_DATEI);
}
//datei.setPfad(e.getHttpContext().getPath() + fName);
String lowerName = dateiName.toLowerCase();
if (lowerName.endsWith(ImageActor.JPEG)
|| lowerName.endsWith(ImageActor.JPG)
|| lowerName.endsWith(ImageActor.PNG)) {
datei.setBild(true);
String ext = dateiName.substring(dateiName.lastIndexOf(STR_DOT));
String ohneExt = dateiName.substring(0, dateiName.lastIndexOf(STR_DOT));
datei.setMiniurl(ohneExt + ImageActor.TN + ext);
buildImgSrc(file, datei, ohneExt, ext);
}
liste.add(datei);
}
while(threadCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(FileManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(liste.size() > 0) {
DirList list = new DirList();
list.setPfad(dirListPath);
list.setDateien(liste);
Gson gson = new Gson();
//String json = gson.toJson(liste);
String json = gson.toJson(list);
//byte[] bytes = json.getBytes();
//logger.fine("json: '" + json + "'");
HttpResponder r = new HttpResponder();
r.antwortSenden(e, SC_OK, json);
} else {
emptyListResponse(e);
}
} else {
emptyListResponse(e);
}
} else {
String lowerName = fName.toLowerCase();
if(lowerName.contains(ImageActor.B64)) {
ImageActor actor = new ImageActor();
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());
if(!toFile.exists()) {
actor.b64Image(fromFile, toFile);
}
super.handle(e);
} else {
super.handle(e);
}
}
}
// data:[][;charset=][;base64],
/*
[So. Juni 13 13:23:32 MESZ 2021] FEIN:
file: /home/ulrich/helix-files/bild-test/10419903-14-2-1920-r.jpg,
relname: bild-test/10419903-14-2-1920-r.jpg, ohneExt: 10419903-14-2-1920-r, ext: .jpg (de.uhilger.helix.FileManager buildImgSrc)
*/
private void buildImgSrc(File file, Datei datei, String ohneExt, String ext) throws IOException {
//logger.fine("file: " + file.getAbsolutePath() + ", ohneExt: " + ohneExt + ", ext: " + ext);
File dir = file.getParentFile();
String newRelName = ohneExt + ImageActor.TN + ImageActor.B64 + ext;
File b64File = new File(dir, newRelName);
//logger.fine("b64File: " + b64File.getAbsolutePath());
if(!b64File.exists()) {
//BildErzeuger be = new BildErzeuger();
//be.bildErzeugen(dir, newRelName, BildErzeuger.TN, 120, b64File);
ImageThread it = new ImageThread(dir, newRelName, ImageActor.TN, 120, b64File, datei, ext);
it.addListener(this);
if(threadCount < maxThreads) {
++threadCount;
//logger.fine("Thread started, threadCount: " + threadCount);
it.start();
} else {
waitingThreads.add(it);
//logger.fine("Thread added to wait queue.");
}
} else {
ImageActor be = new ImageActor();
be.setImgSrc(datei, ext, b64File);
}
}
@Override
public void finished() {
--threadCount;
//logger.fine("Thread finished, threadCound now: " + threadCount);
if (threadCount < maxThreads) {
if (waitingThreads.size() > 0) {
Object o = waitingThreads.get(0);
if (o instanceof ImageThread) {
waitingThreads.remove(o);
ImageThread it = (ImageThread) o;
++threadCount;
//logger.fine("Thread started from wait queue, threadCount now: " + threadCount);
it.start();
}
}
}
}
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);
}
private void speichern(HttpExchange exchange, HttpHelper helper) throws IOException {
String fileName = helper.getFileName(exchange);
//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());
// neuen Ordner erstellen oder ablehnen, wenn der Ordner schon existiert
if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
if (!file.exists()) {
file.mkdir();
standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
} else {
String antwort = "Ordner existiert bereits.";
standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
}
} else {
String antwort = "PUT fuer neuen Ordner nicht erlaubt, bitte POST verwenden.";
standardHeaderUndAntwort(exchange, SC_METHOD_NOT_ALLOWED, antwort);
}
} else {
//logger.info("Datei speichern: " + file.getAbsolutePath());
// Datei speichern
if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
if (file.exists()) {
FileTransporter trans = new FileTransporter();
file = trans.getNewFileName(file);
}
} else if (method.equalsIgnoreCase(HttpHelper.HTTP_PUT)) {
if (file.exists()) {
/*
muss delete() sein?
pruefen: ueberschreibt der FileWriter den alteen Inhalt oder
entsteht eine unerwuenschte Mischung aus altem und neuem
Inhalt?
*/
file.delete();
} else {
file.getParentFile().mkdirs();
}
}
// Request Body mit dem Dateiinhalt in einen String lesen
StringBuilder sb = new StringBuilder();
InputStream is = exchange.getRequestBody();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line = in.readLine();
while (line != null) {
sb.append(line);
line = in.readLine();
}
// dekodieren
String content = sb.toString();
//logger.fine(content);
String decoded = URLDecoder.decode(content, UTF8);
//logger.fine(decoded);
// in Datei schreiben
byte[] bytes = decoded.getBytes();
file.createNewFile();
OutputStream os = new FileOutputStream(file);
os.write(bytes);
os.flush();
os.close();
is.close();
// Antwort senden
standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
}
}
private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException {
//logger.fine("quelle: " + quelle + ", ziel: " + ziel);
String[] dateiNamen = dateiliste(exchange);
copyOrMoveFiles(quelle, ziel, dateiNamen, op, exchange);
standardHeaderUndAntwort(exchange, SC_OK, "Dateien verarbeitet.");
}
private String copyOrMoveFiles(String fromPath, String toPath, String[] fileNames, int operation, HttpExchange e) throws IOException {
String result = null;
File srcDir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fromPath);
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);
if (srcFile.isDirectory()) {
//logger.fine("srcFile is directory.");
OrdnerBearbeiter bearbeiter = new OrdnerBearbeiter();
bearbeiter.setTargetDir(targetDir.toPath());
bearbeiter.setOperation(operation);
Files.walkFileTree(srcFile.toPath(), bearbeiter);
} else {
Path source = srcFile.toPath();
File destFile = targetDir.toPath().resolve(source.getFileName()).toFile();
if (destFile.exists()) {
FileTransporter trans = new FileTransporter();
destFile = trans.getNewFileName(destFile);
}
if (operation == OP_MOVE) {
String fname = srcFile.getName().toLowerCase();
if (fname.endsWith(ImageActor.JPEG)
|| fname.endsWith(ImageActor.JPG)
|| fname.endsWith(ImageActor.PNG)) {
moveImgFilesToDirectory(srcFile, srcDir, targetDir, false);
} else {
Files.move(source, destFile.toPath());
}
} else {
Files.copy(source, destFile.toPath());
}
}
}
return result;
}
private void loeschen(HttpExchange exchange, HttpHelper helper) throws IOException {
String[] dateiNamen = dateiliste(exchange);
String relPfad = helper.getFileName(exchange);
deleteFiles(relPfad, Arrays.asList(dateiNamen), exchange);
standardHeaderUndAntwort(exchange, SC_OK, "Dateien geloescht.");
}
private String[] dateiliste(HttpExchange exchange) throws IOException {
String body = new HttpHelper().bodyLesen(exchange);
//logger.fine("dateien: " + body);
Gson gson = new Gson();
return gson.fromJson(body, String[].class);
}
public String duplizieren(HttpExchange exchange, HttpHelper helper) throws IOException {
String relPfad = helper.getFileName(exchange);
File srcFile = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), relPfad);
String fnameext = srcFile.getName();
int dotpos = fnameext.lastIndexOf(STR_DOT);
String fname = fnameext.substring(0, dotpos);
String ext = fnameext.substring(dotpos);
File srcDir = srcFile.getParentFile();
File destFile = new File(srcDir, fname + "-Kopie" + ext);
int i = 1;
while (destFile.exists()) {
destFile = new File(srcDir, fname + "-Kopie-" + Integer.toString(++i) + ext);
}
Files.copy(srcFile.toPath(), destFile.toPath());
return destFile.getName();
}
public String umbenennen(HttpExchange exchange, HttpHelper helper, String neuerName) throws IOException {
File neueDatei;
String relPfad = helper.getFileName(exchange);
File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), relPfad);
String fname = file.getName().toLowerCase();
if(fname.endsWith(ImageActor.JPEG) || fname.endsWith(ImageActor.JPG) || fname.endsWith(ImageActor.PNG)) {
neueDatei = renameImgFiles(file.getParentFile(), file, neuerName);
} else {
neueDatei = new File(file.getParentFile(), neuerName);
file.renameTo(neueDatei);
}
return neueDatei.getName();
}
public File renameImgFiles(File targetDir, File targetFile, String newName) throws IOException {
String alt;
String neu;
File neueDatei = targetFile;
int newdotpos = newName.lastIndexOf(STR_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(STR_DOT);
String fname = fnameext.substring(0, dotpos);
String ext = fnameext.substring(dotpos);
//logger.fine("fname: " + fname + ", ext: " + ext);
DirectoryStream stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
for (Path path : stream) {
//logger.fine(path.getFileName().toString());
alt = path.getFileName().toString();
//logger.fine("alt: " + alt);
if(alt.contains(ImageActor.TN)) {
neu = newfname + ImageActor.TN + newext;
} else if (alt.contains(ImageActor.KL)) {
neu = newfname + ImageActor.KL + newext;
} else if(alt.contains(ImageActor.GR)) {
neu = newfname + ImageActor.GR + newext;
} else if(alt.contains(ImageActor.MT)) {
neu = newfname + ImageActor.MT + newext;
} else if(alt.contains(ImageActor.SM)) {
neu = newfname + ImageActor.SM + newext;
} else {
neu = newName;
}
neueDatei = new File(targetDir, neu);
path.toFile().renameTo(neueDatei);
}
stream.close();
return neueDatei;
}
private String deleteFiles(String relPath, List fileNames, HttpExchange e) {
String result = null;
try {
//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);
for (String fileName : fileNames) {
File targetFile = new File(targetDir, fileName);
//logger.fine(targetFile.getAbsolutePath());
if (targetFile.isDirectory()) {
OrdnerBearbeiter bearbeiter = new OrdnerBearbeiter();
bearbeiter.setOperation(OP_DELETE);
Files.walkFileTree(targetFile.toPath(), bearbeiter);
} 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(ImageActor.JPEG)
|| fname.endsWith(ImageActor.JPG)
|| fname.endsWith(ImageActor.PNG)) {
deleteImgFiles(targetDir, targetFile);
} else {
targetFile.delete();
}
}
}
result = "deleted";
}
} catch (Throwable ex) {
//logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
}
return result;
}
private void deleteImgFiles(File targetDir, File targetFile) throws IOException {
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);
DirectoryStream stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
for (Path path : stream) {
//logger.fine(path.getFileName().toString());
Files.delete(path);
}
stream.close();
}
private void moveImgFilesToDirectory(File srcFile, File srcDir, File targetDir, boolean createDestDir) throws IOException {
String fnameext = srcFile.getName();
int dotpos = fnameext.lastIndexOf(STR_DOT);
String fname = fnameext.substring(0, dotpos);
String ext = fnameext.substring(dotpos);
//logger.fine("fname: " + fname + ", ext: " + ext);
Path targetPath = targetDir.toPath();
DirectoryStream stream = Files.newDirectoryStream(srcDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
for (Path path : stream) {
//logger.fine(path.getFileName().toString());
//Files.delete(path);
Files.move(path, targetPath.resolve(path.getFileName()));
}
stream.close();
}
private void standardHeaderUndAntwort(HttpExchange exchange, int status, String antwort) throws IOException {
Headers resHeaders = exchange.getResponseHeaders();
resHeaders.add(CONTENT_TYPE, HttpHelper.CT_TEXT_HTML);
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();
}
}