33import java .io .BufferedOutputStream ;
44import java .io .ByteArrayInputStream ;
55import java .io .ByteArrayOutputStream ;
6+ import java .io .File ;
67import java .io .IOException ;
78import java .io .InputStream ;
89import java .io .OutputStream ;
910import java .io .UnsupportedEncodingException ;
1011import java .net .ServerSocket ;
1112import java .net .Socket ;
1213import java .net .URLDecoder ;
14+ import java .text .DateFormat ;
1315import java .util .ArrayList ;
1416import java .util .Collection ;
1517import java .util .Collections ;
@@ -30,6 +32,9 @@ public abstract class WebServer {
3032 private static final int LINE_SIZE = 128 ;
3133 private static final String UTF_8 = "utf-8" ;
3234 private static final String TOKEN = "token" ;
35+ private static final int SC_OKAY = 200 ;
36+ private static final int SC_NOT_AUTHORISED = 401 ;
37+ private static final int SC_NOT_FOUND = 404 ;
3338
3439 public WebServer () {
3540 super ();
@@ -52,8 +57,8 @@ public void run() {
5257 }
5358
5459 protected abstract void execStream (InputStream inputStream ) throws IOException ;
55- protected abstract Collection <FileData > getFileData () throws IOException ;
5660 protected abstract Response getFile (String path , boolean asset ) throws IOException ;
61+ protected abstract Collection <FileData > getFileData () throws IOException ;
5762 protected abstract void log (String message );
5863 protected abstract void log (String message , Exception exception );
5964 protected abstract boolean renameFile (String from , String to );
@@ -154,7 +159,14 @@ private Response handleWebResponse(String asset) throws IOException {
154159 } else {
155160 path = asset ;
156161 }
157- return getFile (path , true );
162+ Response result ;
163+ try {
164+ result = getFile (path , true );
165+ } catch (Exception e ) {
166+ log ("error: " + e );
167+ result = null ;
168+ }
169+ return result != null ? result : new Response (SC_NOT_FOUND );
158170 }
159171
160172 /**
@@ -181,7 +193,6 @@ private void runServer(final int socketNum, final String token) throws IOExcepti
181193 request .invoke (inputStream , token );
182194 } catch (Exception e ) {
183195 log ("Server failed" , e );
184- break ;
185196 } finally {
186197 log ("socket cleanup" );
187198 if (socket != null ) {
@@ -192,7 +203,6 @@ private void runServer(final int socketNum, final String token) throws IOExcepti
192203 }
193204 }
194205 }
195- log ("server stopped" );
196206 }
197207
198208 /**
@@ -208,6 +218,13 @@ public FileData(String fileName, String date, long size) {
208218 this .date = date ;
209219 this .size = size ;
210220 }
221+
222+ public FileData (File file ) {
223+ DateFormat dateFormat = DateFormat .getDateInstance (DateFormat .DEFAULT );
224+ this .fileName = file .getName ();
225+ this .date = dateFormat .format (file .lastModified ());
226+ this .size = file .length ();
227+ }
211228 }
212229
213230 /**
@@ -265,8 +282,14 @@ public Request(Socket socket, InputStream inputStream) throws IOException {
265282 this .headers = getHeaders (inputStream );
266283 this .socket = socket ;
267284 this .token = getToken (headers );
268- String [] fields = headers .get (0 ).split ("\\ s" );
269- if (fields .length > 1 ) {
285+ String first = headers .get (0 );
286+ String [] fields ;
287+ if (first != null ) {
288+ fields = first .split ("\\ s" );
289+ } else {
290+ fields = null ;
291+ }
292+ if (fields != null && fields .length > 1 ) {
270293 this .method = fields [0 ];
271294 this .url = fields [1 ];
272295 } else {
@@ -405,6 +428,9 @@ private void handleGet(Map<String, Collection<String>> parameters, String tokenK
405428 if (url .startsWith ("/api/download?" )) {
406429 if (tokenKey .equals (token )) {
407430 handleDownload (parameters ).send (socket , null );
431+ } else {
432+ log ("Invalid token" );
433+ new Response (SC_NOT_AUTHORISED ).send (socket , null );
408434 }
409435 } else {
410436 handleWebResponse (url ).send (socket , null );
@@ -421,23 +447,30 @@ private void handlePost(Map<String, String> data, String tokenKey) throws IOExce
421447 }
422448 log ("userToken=" + userToken );
423449 if (tokenKey .equals (userToken )) {
424- if (url .startsWith ("/api/files " )) {
450+ if (url .startsWith ("/api/login " )) {
425451 handleFileList ().send (socket , userToken );
452+ } else if (url .startsWith ("/api/files" )) {
453+ handleFileList ().send (socket , null );
426454 } else if (url .startsWith ("/api/upload" )) {
427455 handleUpload (data ).send (socket , null );
428456 } else if (url .startsWith ("/api/rename" )) {
429457 handleRename (data ).send (socket , null );
458+ } else {
459+ new Response (SC_NOT_FOUND ).send (socket , null );
430460 }
431461 log ("Sent POST response" );
432462 } else {
433463 log ("Invalid token" );
434- handleStatus (false , "Invalid token" ).send (socket , null );
464+ if (url .startsWith ("/api/login" )) {
465+ handleStatus (false , "Invalid token" ).send (socket , null );
466+ } else {
467+ new Response (SC_NOT_AUTHORISED ).send (socket , null );
468+ }
435469 }
436470 }
437471
438472 private void handleRun (InputStream inputStream , String tokenKey ) throws IOException {
439- if (tokenKey .equals (token )) {
440- execStream (inputStream );
473+ if (tokenKey .equals (token )) { execStream (inputStream );
441474 } else {
442475 log ("Invalid token" );
443476 }
@@ -450,29 +483,40 @@ private void handleRun(InputStream inputStream, String tokenKey) throws IOExcept
450483 public class Response {
451484 private final InputStream inputStream ;
452485 private final long length ;
486+ private final int errorCode ;
453487
454488 public Response (InputStream inputStream , long length ) {
455489 this .inputStream = inputStream ;
456490 this .length = length ;
491+ this .errorCode = SC_OKAY ;
457492 }
458493
459494 public Response (byte [] bytes ) {
460495 this .inputStream = new ByteArrayInputStream (bytes );
461496 this .length = bytes .length ;
497+ this .errorCode = SC_OKAY ;
498+ }
499+
500+ public Response (int errorCode ) throws IOException {
501+ byte [] bytes = ("Error: " + errorCode ).getBytes (UTF_8 );
502+ this .inputStream = new ByteArrayInputStream (bytes );
503+ this .length = bytes .length ;
504+ this .errorCode = errorCode ;
462505 }
463506
464507 /**
465508 * Sends the response to the given socket
466509 */
467- void send (Socket socket , String session ) throws IOException {
510+ void send (Socket socket , String cookie ) throws IOException {
468511 log ("sendResponse() entered" );
469512 String contentLength = "Content-length: " + length + "\r \n " ;
470513 BufferedOutputStream out = new BufferedOutputStream (socket .getOutputStream ());
471- out .write ("HTTP/1.0 200 OK\r \n " .getBytes ());
514+ String code = errorCode == SC_OKAY ? SC_OKAY + " OK" : String .valueOf (errorCode );
515+ out .write (("HTTP/1.0 " + code + "\r \n " ).getBytes ());
472516 out .write ("Content-type: text/html\r \n " .getBytes ());
473517 out .write (contentLength .getBytes ());
474- if (session != null ) {
475- out .write (("Set-Cookie: " + TOKEN + "=" + session + "\r \n " ).getBytes ());
518+ if (cookie != null ) {
519+ out .write (("Set-Cookie: " + TOKEN + "=" + cookie + "\r \n " ).getBytes ());
476520 }
477521 out .write ("Server: SmallBASIC for Android\r \n \r \n " .getBytes ());
478522 socket .setSendBufferSize (SEND_SIZE );
0 commit comments