Dateiverwaltung für die WebBox
ulrich
2018-04-03 af99308ac8192fd47be8f6ec030f973a0bf23072
commit | author | age
8931b7 1 /*
U 2     Dateiverwaltung - File management in your browser
3     Copyright (C) 2017 Ulrich Hilger, http://uhilger.de
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Affero General Public License as
7     published by the Free Software Foundation, either version 3 of the
8     License, or (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Affero General Public License for more details.
14
15     You should have received a copy of the GNU Affero General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
c7c502 19 package de.uhilger.filecms.api;
U 20
6e70be 21 import de.uhilger.filecms.data.FileRef;
d14d78 22 import de.uhilger.filecms.pub.AbstractComparator;
U 23 import de.uhilger.filecms.pub.FileNameComparator;
bb9f8c 24 import de.uhilger.wbx.Bild;
8e51b7 25 import java.io.File;
af9930 26 import java.io.FileInputStream;
3ad4db 27 import java.io.FileNotFoundException;
6bd2c1 28 import java.io.FileOutputStream;
3ad4db 29 import java.io.FileReader;
e5ff42 30 import java.io.FileWriter;
U 31 import java.io.IOException;
6bd2c1 32 import java.io.InputStream;
fab80c 33 import java.io.Reader;
e5ff42 34 import java.security.Principal;
7342b1 35 import java.util.ArrayList;
d14d78 36 import java.util.Arrays;
6bd2c1 37 import java.util.Enumeration;
5bfd34 38 import java.util.Iterator;
7342b1 39 import java.util.List;
e5ff42 40 import java.util.logging.Level;
8e51b7 41 import java.util.logging.Logger;
af9930 42 import java.util.zip.Adler32;
U 43 import java.util.zip.CheckedOutputStream;
6bd2c1 44 import java.util.zip.ZipEntry;
U 45 import java.util.zip.ZipFile;
af9930 46 import java.util.zip.ZipOutputStream;
bb9f8c 47 import net.coobird.thumbnailator.Thumbnails;
5bfd34 48 import org.apache.commons.io.FileUtils;
c7c502 49
U 50 /**
fafe1b 51  * Methoden zur Verwaltung von Dateien
c7c502 52  */
8931b7 53 public class FileMgr extends Api {
8e51b7 54   private static final Logger logger = Logger.getLogger(FileMgr.class.getName());
c7c502 55   
972e94 56   
9e2964 57   public static final int OP_COPY = 1;
U 58   public static final int OP_MOVE = 2;
59   
ea7193 60   public String hallo() {
U 61     return "Hallo Welt!";
62   }
63   
1f550a 64   /**
U 65    * Inhalte der WebBox listen. Hier wird nur der relative Pfad 
66    * ausgehend von www oder home ausgegeben sowie zudem ausgehend 
67    * von $daten und $basis, sofern der Benutzer die Rolle wbxAdmin hat.
68    * 
69    * Andere Inhalte werden nicht ausgegeben.
70    * 
71    * @param relPath
72    * @return 
73    */
7342b1 74   public List<FileRef> list(String relPath) {
d14d78 75     return listInt(relPath, "name", AbstractComparator.ORDER_ASC);
U 76   }
77   
78   public List<FileRef> listOrdered(String relPath, String orderBy, String order) {
79     return listInt(relPath, orderBy, order);
80   }
81   
82   /**
83    * Inhalte der WebBox listen. Hier wird nur der relative Pfad 
84    * ausgehend von www oder home ausgegeben sowie zudem ausgehend 
85    * von $daten und $basis, sofern der Benutzer die Rolle wbxAdmin hat.
86    * 
87    * Andere Inhalte werden nicht ausgegeben.
88    * 
89    * @param relPath
90    * @param orderBy 'name'
91    * @param order AbstractComparator.ORDER_ASC oder AbstractComparator.ORDER_DESC
92    * @return 
93    */
94   private List<FileRef> listInt(String relPath, String orderBy, String order) {
f7d8bf 95     Bild bild = new Bild();
5dfab6 96     List<FileRef> files = new ArrayList();
ac72fe 97     if (!relPath.startsWith(".") && !relPath.contains("WEB-INF") && !relPath.contains("META-INF")) {
3d0c6d 98       if (relPath.length() == 0) {
U 99         FileRef namedPublicFolder = new FileRef(PUB_DIR_NAME, true);
100         logger.finer(namedPublicFolder.getAbsolutePath());
101         FileRef namedHomeFolder = new FileRef(HOME_DIR_NAME, true);
102         logger.finer(namedHomeFolder.getAbsolutePath());
103         FileRef namedDavFolder = new FileRef(DAV_DIR_NAME, true);
104         logger.finer(namedDavFolder.getAbsolutePath());
105         files = new ArrayList();
106         files.add(namedHomeFolder);
107         files.add(namedPublicFolder);
108         files.add(namedDavFolder);
109         if (getRequest().isUserInRole(WBX_ADMIN_ROLE)) {
110           FileRef namedBaseFolder = new FileRef(WBX_BASE, true);
111           FileRef namedDataFolder = new FileRef(WBX_DATA, true);
112           files.add(namedBaseFolder);
113           files.add(namedDataFolder);
d14d78 114         }
3d0c6d 115       } else {
U 116         String path = getTargetDir(relPath).getAbsolutePath();
117         logger.fine("listing path: " + path);
118         File dir = new File(path);
119         if (dir.exists()) {
120           File[] fileArray = dir.listFiles();
121           if (orderBy != null && orderBy.equalsIgnoreCase("name")) {
122             Arrays.sort(fileArray, new FileNameComparator(order));
123           } else {
124             Arrays.sort(fileArray, new FileNameComparator(AbstractComparator.ORDER_ASC));
5bfd34 125           }
3d0c6d 126           for (int i = 0; i < fileArray.length; i++) {
U 127             logger.fine(fileArray[i].toURI().toString());
128             String fname = fileArray[i].toURI().toString().replace("file:/", "");
129             if (fileArray[i].isDirectory()) {
130               fname = fname.substring(0, fname.length() - 1);
131             }
132             logger.fine(fname);
ac72fe 133             if(!fname.contains("WEB-INF") && !fname.contains("META-INF")) {
c5eaaa 134               long fLen = fileArray[i].length();
U 135               long lastMod = fileArray[i].lastModified();
136               FileRef ref = new FileRef(fname, fileArray[i].isDirectory(), fileArray[i].isHidden(), lastMod, fLen);
ac72fe 137               ref.setMimetype(bild.getMimeType(fileArray[i]));
U 138               files.add(ref);
139             }
3d0c6d 140           }
5bfd34 141         }
5dfab6 142       }
3d0c6d 143     }
7342b1 144     return files;
2121cc 145   }
U 146   
d14d78 147   
c509a0 148   public FileRef newFolder(String relPath, String folderName) {
eb2a2d 149     if (!relPath.startsWith(".")) {
U 150       logger.finer(relPath);
151       String targetPath = null;
152       if(relPath.startsWith(PUB_DIR_NAME)) {
153         targetPath = PUB_DIR_PATH + getUserName() + "/" + relPath.substring(PUB_DIR_NAME.length()) + "/" + folderName;
154       } else if(relPath.startsWith(HOME_DIR_NAME)) {
155         targetPath = HOME_DIR_PATH + getUserName() + "/" + relPath.substring(HOME_DIR_NAME.length()) + "/" + folderName;
156       } else {
157         // kann eigentlich nicht sein..
158       }
159       logger.finer(targetPath);
160       File targetDir = new File(getBase().getAbsolutePath(), targetPath);
161       targetDir.mkdirs();
162       return new FileRef(targetDir.getAbsolutePath(), true);
c509a0 163     } else {
eb2a2d 164       return null;
c509a0 165     }
5dfab6 166   }
U 167   
3ad4db 168   public String getCode(String relPath, String fileName) {
U 169     String code = null;
eb2a2d 170     if (!relPath.startsWith(".")) {
U 171       Object p = getRequest().getUserPrincipal();
172       if (p instanceof Principal) {
173         Reader reader = null;
3ad4db 174         try {
eb2a2d 175           File targetFile = new File(getTargetDir(relPath), fileName);
U 176
177           //reader = new InputStreamReader(new FileInputStream(targetFile), "UTF8");
178           reader = new FileReader(targetFile);
179           StringBuffer buf = new StringBuffer();
180           char[] readBuffer = new char[1024];
181           int charsRead = reader.read(readBuffer);
182           while (charsRead > -1) {
183             buf.append(readBuffer, 0, charsRead);
184             charsRead = reader.read(readBuffer);
185           }
186           code = buf.toString();
187         } catch (FileNotFoundException ex) {
188           Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
3ad4db 189         } catch (IOException ex) {
U 190           Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
eb2a2d 191         } finally {
U 192           try {
193             reader.close();
194           } catch (IOException ex) {
195             Logger.getLogger(FileMgr.class.getName()).log(Level.SEVERE, null, ex);
196           }
3ad4db 197         }
eb2a2d 198
3ad4db 199       }
eb2a2d 200     }
3ad4db 201     return code;
U 202   }
203   
663ee9 204   public String renameFile(String relPath, String fname, String newName) {
eb2a2d 205     if (!relPath.startsWith(".")) {
U 206       File targetDir = getTargetDir(relPath);
207       File file = new File(targetDir, fname);
208       file.renameTo(new File(targetDir, newName));
209       return fname + " umbenannt zu " + newName;
210     } else {
211       return "Pfad nicht erlaubt.";
212     }
663ee9 213   }
U 214   
fc1897 215   public String deleteFiles(String relPath, List fileNames) {
U 216     String result = null;
217     try {
218       logger.fine(fileNames.toString());
eb2a2d 219       if (!relPath.startsWith(".")) {
U 220         File targetDir = getTargetDir(relPath);
221         for(int i=0; i < fileNames.size(); i++) {
222           Object o = fileNames.get(i);
223           if(o instanceof ArrayList) {
224             ArrayList al = (ArrayList) o;
225             logger.fine(al.get(0).toString());
226             File targetFile = new File(targetDir, al.get(0).toString());
227             logger.fine(targetFile.getAbsolutePath());
228             if(targetFile.isDirectory()) {
229               FileUtils.deleteDirectory(targetFile);
230             } else {
231               targetFile.delete();
232             }
5bfd34 233           }
fc1897 234         }
eb2a2d 235         result = "deleted";
fc1897 236       }
U 237     } catch (Throwable ex) {
238       logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
239     }
240     return result;
241   }
242   
9e2964 243   public String copyFiles(String fromPath, String toPath, List fileNames) {
fab629 244     return copyOrMoveFiles(fromPath, toPath, fileNames, OP_COPY);
9e2964 245   }
U 246   
247   public String moveFiles(String fromPath, String toPath, List fileNames) {
fab629 248     return copyOrMoveFiles(fromPath, toPath, fileNames, OP_MOVE);
U 249   }
250   
251   private String copyOrMoveFiles(String fromPath, String toPath, List fileNames, int operation) {
5bfd34 252     String result = null;
U 253     try {
eb2a2d 254       if (!fromPath.startsWith(".")) {
U 255         File srcDir = getTargetDir(fromPath);
256         File targetDir = getTargetDir(toPath);
257         Iterator i = fileNames.iterator();
258         while(i.hasNext()) {
259           Object o = i.next();
260           if (o instanceof ArrayList) {
261             ArrayList al = (ArrayList) o;
262             File srcFile = new File(srcDir, al.get(0).toString());
263             if(srcFile.isDirectory()) {
264               if(operation == OP_MOVE) {
265                 FileUtils.moveDirectoryToDirectory(srcFile, targetDir, false);
266               } else {
267                 FileUtils.copyDirectoryToDirectory(srcFile, targetDir);
268               }
fab629 269             } else {
eb2a2d 270               if(operation == OP_MOVE) {
U 271                 FileUtils.moveFileToDirectory(srcFile, targetDir, false);
272               } else {
273                 FileUtils.copyFileToDirectory(srcFile, targetDir);              
274               }
fab629 275             }
5bfd34 276           }
U 277         }
278       }
279     } catch (IOException ex) {
280       logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
281     }
282     return result;
9e2964 283   }
U 284   
47e9d4 285   public FileRef saveTextFileAs(String relPath, String fileName, String contents) {
U 286     FileRef savedFile = null;
287     logger.fine(relPath + " " + fileName);
eb2a2d 288     if (!relPath.startsWith(".")) {
U 289       //FileRef datenRef = getBase();
290       Object p = getRequest().getUserPrincipal();
291       if(p instanceof Principal) {
292         File targetFile = new File(getTargetDir(relPath), fileName);
293         if(targetFile.exists()) {
294           targetFile = getNewFileName(targetFile);
295         } else {
296           targetFile.getParentFile().mkdirs();
297         }
298         saveToFile(targetFile, contents);
47e9d4 299       }
U 300     }
301     return savedFile;
302   }
303   
304   private File getNewFileName(File file) {
305     File dir = file.getParentFile();
306     String targetName = file.getName();
307     logger.fine("targetName: " + targetName);
308     String ext = "";
309     int dotpos = targetName.indexOf(".");
310     if(dotpos > -1) {
311       ext = targetName.substring(dotpos);
312       targetName = targetName.substring(0, dotpos);
313     }
314     logger.fine("targetName: " + targetName + ", ext: " + ext);
315     int i = 1;
316     while(file.exists()) {
317       StringBuffer buf = new StringBuffer();
318       buf.append(targetName);
319       buf.append("-");
320       buf.append(i);
321       if(ext.length() > 0) {
322         buf.append(ext);
323       }
324       file = new File(dir, buf.toString());
325       i++;
326     }
327     logger.fine("new file: " + file.getName());
328     return file;
942d63 329   }  
47e9d4 330   
U 331   private FileRef saveToFile(File targetFile, String contents) {
ea7193 332     FileRef savedFile = null;
e5ff42 333     try {
47e9d4 334       targetFile.createNewFile();
U 335       FileWriter w = new FileWriter(targetFile);
942d63 336       //w.write(StringEscapeUtils.unescapeHtml(contents));
47e9d4 337       w.write(contents);
U 338       w.flush();
339       w.close();
340       savedFile = new FileRef(
341               targetFile.getAbsolutePath(),
342               targetFile.isDirectory(),
343               targetFile.isHidden(),
344               targetFile.lastModified(),
345               targetFile.length());
e5ff42 346     } catch (IOException ex) {
47e9d4 347       logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
U 348     }
349     return savedFile;
350   }
351   
352   public FileRef saveTextFile(String relPath, String fileName, String contents) {
353     FileRef savedFile = null;
354     logger.fine(relPath + " " + fileName);
eb2a2d 355     if (!relPath.startsWith(".")) {    
U 356       //FileRef datenRef = getBase();
357       Object p = getRequest().getUserPrincipal();
358       if(p instanceof Principal) {
359         File targetFile = new File(getTargetDir(relPath), fileName);
360         if(targetFile.exists()) {
361           /*
362             muss delete() sein?
363             pruefen: ueberschreibt der FileWriter den alteen Inhalt oder 
364             entsteht eine unerwuenschte Mischung aus altem und neuem 
365             Inhalt?
366           */
367           targetFile.delete();
368         } else {
369           targetFile.getParentFile().mkdirs();
370         }
371         saveToFile(targetFile, contents);
47e9d4 372       }
e5ff42 373     }
ea7193 374     return savedFile;
U 375   }
438b16 376   
U 377   public String bildVerkleinern(String relPath, String bildName) {
eb2a2d 378     if (!relPath.startsWith(".")) {
U 379       File dir = getTargetDir(relPath);
380       File original = new File(dir, bildName);
381       Bild bild = new Bild();
382       //for (int i = 0; i < Bild.GR.length; i++) {
383
438b16 384       //int gr = bild.getVariantenGroesse(i);
U 385       String ext = "";
386       String nurname = bildName;
387       int dotpos = bildName.indexOf(".");
388       if (dotpos > -1) {
389         ext = bildName.substring(dotpos);
390         nurname = bildName.substring(0, dotpos);
391       }
eb2a2d 392
bb9f8c 393           // 120, 240, 500, 700, 1200
U 394
395       
396       for (int i = 0; i < Bild.GR.length; i++) {
397         StringBuffer buf = new StringBuffer();
398         buf.append(nurname);
399         buf.append(bild.getVariantenName(i));
400         buf.append(ext);
401         File newImgFile = new File(dir, buf.toString());
402         try {
403           Thumbnails.of(original)
404                   .size(bild.getVariantenGroesse(i), bild.getVariantenGroesse(i))
405                   .keepAspectRatio(true)
8a8152 406                   .outputQuality(0.7)
bb9f8c 407                   .toFile(newImgFile);
U 408         } catch (IOException ex) {
409           logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
410         }
411       }
eb2a2d 412       return "ok";
U 413     } else {
414       return "Pfad micht erlaubt.";
415     }
438b16 416   }
6bd2c1 417   
bb9f8c 418   public String bildRotieren(String relPath, String bildName) {
U 419     if (!relPath.startsWith(".")) {
420       File dir = getTargetDir(relPath);
421       File original = new File(dir, bildName);
422
423       String ext = "";
424       String nurname = bildName;
425       int dotpos = bildName.indexOf(".");
426       if (dotpos > -1) {
427         ext = bildName.substring(dotpos);
428         nurname = bildName.substring(0, dotpos);
429       }
430
431       StringBuffer buf = new StringBuffer();
432       buf.append(nurname);
433       buf.append("-rot");
434       buf.append(ext);
435       File newImgFile = new File(dir, buf.toString());
436       
437       logger.fine("original: " + original.getAbsolutePath() + " newImgFile: " + newImgFile.getAbsolutePath());
438
439       try {
440         Thumbnails.of(original)
441                 .scale(1)
442                 .rotate(90)
443                 .toFile(newImgFile);
444       } catch (IOException ex) {
445         logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
446       }
447
448
449       return "ok";
450     } else {
451       return "Pfad micht erlaubt.";
452     }
453   }
af9930 454   
U 455   /* --------- ZIP entpacken ---------------- */
456   
6bd2c1 457   public String extractZipfile(String relPath, String filename) {
eb2a2d 458     String result = null;
U 459     if (!relPath.startsWith(".")) {    
460       try {
461         File targetDir = getTargetDir(relPath);
462         File archive = new File(targetDir, filename);
463         if(extract(archive)) {
464           result = "ok";
465         } else {
466           result = "error while extracting";
467         }
468       } catch(Exception ex) {
469         result = ex.getLocalizedMessage();
470         logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
6bd2c1 471       }
U 472     }
473     return result;
474   }
475   
476   /**
477      * extract a given ZIP archive to the folder respective archive resides in
478      * @param archive  the archive to extract
479      * @throws Exception
480      */
481     private boolean extract(File archive) throws Exception {
482         ZipFile zipfile = new ZipFile(archive);
483         Enumeration en = zipfile.entries();
484         while(en.hasMoreElements()) {
485             ZipEntry zipentry = (ZipEntry) en.nextElement();
486             unzip(zipfile, zipentry, archive.getParent());
487         }
488         zipfile.close();
489         return true;
490     }
491
492     /**
493      * unzip a given entry of a given zip file to a given location
494      * @param zipfile  the zip file to read an entry from
495      * @param zipentry  the zip entry to read
496      * @param destPath  the path to the destination location for the extracted content
497      * @throws IOException
498      */
499     private void unzip(ZipFile zipfile, ZipEntry zipentry, String destPath) throws IOException {
500         byte buf[] = new byte[1024];
501         InputStream is = zipfile.getInputStream(zipentry);
502         String outFileName = destPath + File.separator + zipentry.getName();
503         File file = new File(outFileName);
504         if(!zipentry.isDirectory()) {
505             file.getParentFile().mkdirs();
506             if(!file.exists())
507                 file.createNewFile();
508             FileOutputStream fos = new FileOutputStream(file);
509             int i = is.read(buf, 0, 1024);
510             while(i > -1) {
511                 fos.write(buf, 0, i);
512                 i = is.read(buf, 0, 1024);
513             }
514             fos.close();
515             is.close();
516         } else {
517             file.mkdirs();
518         }
519     }
520
af9930 521   /* ------------- Ornder als ZIP packen --------------- */
U 522   
523   public String packFolder(String relPath) {
524     if (!relPath.startsWith(".")) {    
525       try {
526         File targetDir = getTargetDir(relPath);
527         File parentDir = targetDir.getParentFile();
528         StringBuffer fname = new StringBuffer();
529         fname.append(targetDir.getName());
530         fname.append(".zip");
531         File archiveFile = new File(parentDir, fname.toString());
532         FileRef folderToPack = new FileRef(targetDir.getAbsolutePath());
533         FileRef archive = new FileRef(archiveFile.getAbsolutePath());
534         pack(folderToPack, archive);
535         return "ok";
536       } catch(Exception ex) {
537         String result = ex.getLocalizedMessage();
538         logger.log(Level.SEVERE, result, ex);
539         return result;
540       }
541     } else {
542       return "Falsche relative Pfadangabe";
543     }
544   }
545   
546     /**
547      * pack the contents of a given folder into a new ZIP compressed archive
548      * @param folder  the folder to pack
549      * @param archive  the archive to create from the given files
550      * @throws Exception
551      */
552     private boolean pack(FileRef folder, FileRef archive) throws Exception {
553         File file = new File(archive.getAbsolutePath());
554         FileOutputStream fos = new FileOutputStream(file);
555         CheckedOutputStream checksum = new CheckedOutputStream(fos, new Adler32());
556         ZipOutputStream zos = new ZipOutputStream(checksum);
557         pack(zos, folder.getAbsolutePath(), "");
558         zos.flush();
559         zos.finish();
560         zos.close();
561         fos.flush();
562         fos.close();
563         return true;
564     }
565
566     /**
567      * go through the given file structure recursively
568      * @param zipFile  the ZIP file to write to
569      * @param srcDir  the directory to pack during this cycle
570      * @param subDir  the subdirectory to append to names of file entries inside the archive
571      * @throws IOException
572      */
573     private void pack(ZipOutputStream zipFile, String srcDir, String subDir) throws IOException {
574         File[] files = new File(srcDir).listFiles();
575         for(int i = 0; i < files.length; i++) {
576             if(files[i].isDirectory()) {
577                 pack(zipFile, files[i].getAbsolutePath(), subDir + File.separator + files[i].getName());
578             }
579             else {
580                 packFile(zipFile, subDir, files[i]);
581             }
582         }
583     }
584
585     /**
586      * pack a given file
587      * @param zipFile  the ZIP archive to pack to
588      * @param dir  the directory name to append to name of file entry inside archive
589      * @param file  the file to pack
590      * @throws IOException
591      */
592     private void packFile(ZipOutputStream zipFile, String dir, File file) throws IOException
593     {
594         FileInputStream fileinputstream = new FileInputStream(file);
595         byte buf[] = new byte[fileinputstream.available()];
596         fileinputstream.read(buf);
597         String dirWithSlashes = dir.replace('\\', '/');
598         //System.out.println("zipping " + dirWithSlashes + "/" + file.getName());
599         ZipEntry ze = new ZipEntry(dirWithSlashes + "/" + file.getName());
600         ze.setMethod(ZipEntry.DEFLATED);
601         zipFile.putNextEntry(ze);
602         zipFile.write(buf, 0, buf.length);
603         zipFile.closeEntry();
604         fileinputstream.close();
605     }
606
6bd2c1 607   
438b16 608
5efd94 609   /* ---- Hilfsfunktionen ---- */
ea7193 610   
547755 611 }