Dateien verwalten mit Modul jdk.httpserver
ulrich
2024-01-15 342aebc6b1143ab81a626a71b8bf7ce15eb5f361
commit | author | age
7fdd7e 1 /*
U 2   http-cm - File management extensions to jdk.httpserver
3   Copyright (C) 2021  Ulrich Hilger
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 <https://www.gnu.org/licenses/>.
17  */
18 package de.uhilger.httpserver.cm;
19
20 import com.sun.net.httpserver.Authenticator;
21 import com.sun.net.httpserver.HttpExchange;
22 import de.uhilger.httpserver.base.HttpResponder;
23 import de.uhilger.httpserver.base.HttpHelper;
24 import de.uhilger.httpserver.base.handler.FileHandler;
cc154b 25 import de.uhilger.httpserver.cm.actor.Lister;
342aeb 26 import de.uhilger.httpserver.cm.actor.Writer;
7fdd7e 27 import de.uhilger.httpserver.oauth.BearerAuthenticator;
U 28 import java.io.IOException;
29
30 /**
31  * <p>Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
32  * Dateisystems.</p>
33  *
34  * <p>HTTP GET fuer eine Datei innerhalb dieses Ordners liefert den Dateiinhalt aus</p>
35  *
36  * <p>HTTP GET fuer einen Ordner liefert eine Liste von dessen Inhalt in JSON</p>
37  *
38  * <p>HTTP PUT fuer eine Datei ueberschreibt eine bestehende Datei mit dem im Body
39  * uebergebenen Inhalt oder legt eine Datei mit diesem Inhalt an</p>
40  *
41  * <p>HTTP POST fuer eine Datei legt eine neue Datei mit dem im Body uebergebenen
42  * Inhalt an oder erzeugt eine neue Datei mit einer laufenden Nummer, falls
43  * diese Datei schon existiert</p>
44  *
45  * <p>HTTP POST fuer einen Ordner legt einen neuen Ordner an wenn er noch nicht
46  * existiert oder erzeugt einen HTTP-Fehler 422</p>
47  *
48  * <p>HTTP DELETE loescht die Liste der Dateien und Ordner im Body</p>
49  *
50  * <p>HTTP PUT ?copyFrom=pfad kopiert die Liste der Datei- oder Ordnernamen im Body
51  * der Anfrage vom Pfad in 'copyFrom' zum Pfad dieser Anfrage. Jede Datei, die
52  * im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
53  * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
54  * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
55  * Nummer, dann wird der Quellordner ans Ziel kopiert.</p>
56  *
57  * <p>HTTP PUT ?moveFrom=pfad verschiebt die Liste der Datei- oder Ordnernamen im
58  * Body der Anfrage vom Pfad in 'moveFrom' zum Pfad dieser Anfrage. Jede Datei,
59  * die im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
60  * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
61  * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
62  * Nummer, dann wird der Quellordner ans Ziel kopiert.</p>
63  *
64  * <p>HTTP PUT mit ?duplicate legt eine Kopie der Datei an</p>
65  *
66  * <p>HTTP PUT mit '?renameTo=neuer Name' benennt die Datei oder den Ordner um,
67  * sofern der neue Name noch nicht vergeben ist</p>
68  *
69  * <p>HTTP PUT mit '?zip' packt den Ordner</p>
70  *
71  * <p>HTTP PUT mit '?unzip' entpackt eine Datei</p>
72  * 
73  * <p>Namenskonventionen:<br>
74  * Ein Pfad mit Schraegstrich ('/') am Ende bezeichnet einen Ordner<br>
75  * Ein Pfad ohne Schraegstrich ('/') am Ende bezeichnet eine Datei</p>
76  *
77  * @author Ulrich Hilger
78  * @version 1, 13. Mai 2021
79  */
cc154b 80 public class FileManager extends FileHandler {
7fdd7e 81
U 82   /*
83   private static final String[] specialChars = {new String("\u00c4"), new String("\u00d6"),
84     new String("\u00dc"), new String("\u00e4"), new String("\u00f6"), new String("\u00fc"), new String("\u00df")};
85   */
86   
87   //public static final String UNWANTED_PATTERN = "[^a-zA-Z_0-9 ]";
88   /* HTTP Methoden */
89
90   public static final String UTF8 = "UTF-8";
91
92   public static final String STR_SLASH = "/";
93   public static final String STR_DOT = ".";
94   
95   public static final String P_COPY = "copyFrom";
96   public static final String P_MOVE = "moveFrom";
97   public static final String P_DUPLICATE = "duplicate";
98   public static final String P_RENAME = "renameTo";
99   public static final String P_ZIP = "zip";
100   public static final String P_UNZIP = "unzip";
101
102   public static final int OP_COPY = 1;
103   public static final int OP_MOVE = 2;
104   public static final int OP_DELETE = 3;
105   
106   public static final String ATTR_ROLE = "role";
107   
108   @Override
109   public void handle(HttpExchange e) throws IOException {
110     Authenticator a = e.getHttpContext().getAuthenticator();
111     if(a instanceof BearerAuthenticator) {
112       BearerAuthenticator auth = (BearerAuthenticator) a;
113       //Realm realm = auth.getRealm();
114       String userId = e.getPrincipal().getUsername();
115       if(auth.hasRole(userId, e.getHttpContext().getAttributes().get(ATTR_ROLE).toString())) {
116         String method = e.getRequestMethod();
5adf10 117         //logger.fine("method: " + method);
7fdd7e 118         HttpHelper helper = new HttpHelper();
U 119         switch (method) {
120           case HttpHelper.HTTP_GET:
cc154b 121             String path = e.getRequestURI().toString();
U 122             if (path.endsWith(STR_SLASH)) {
123               String json = new Lister().liste(helper.getFileName(e), 
124                       e.getHttpContext().getPath(), 
125                       e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(),
126                       path);
127               if(null != json) {
128                 HttpResponder r = new HttpResponder();
129                 r.antwortSenden(e, SC_OK, json);              
130               } else {
131                 emptyListResponse(e);    
132               }
133             } else {
134               new Lister().b64Action(helper.getFileName(e), 
135                       e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
136               super.handle(e);
137             }
7fdd7e 138             break;
U 139           case HttpHelper.HTTP_PUT:
342aeb 140             new Writer().put(e, helper);
7fdd7e 141             break;
U 142           case HttpHelper.HTTP_POST:
342aeb 143             new Writer().speichern(e, helper);
7fdd7e 144             break;
U 145           case HttpHelper.HTTP_DELETE:
342aeb 146             new Writer().loeschen(e, helper);
7fdd7e 147             break;
U 148         }
149       } else {
342aeb 150         new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
7fdd7e 151       }
U 152     } else {
342aeb 153       new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
7fdd7e 154     }
U 155   }
156   
157   private void emptyListResponse(HttpExchange e) throws IOException {
158     HttpResponder r = new HttpResponder();
159     String json = "{}";
5adf10 160     //logger.log(Level.FINE, "json: ''{0}''", json);
7fdd7e 161     r.antwortSenden(e, SC_OK, json);        
U 162   }
163 }