package org.swellrt.server.ds; import com.google.inject.Inject; import com.google.inject.Singleton; import org.apache.commons.codec.binary.Base64; import org.waveprotocol.wave.util.logging.Log; import java.io.BufferedInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.StringTokenizer; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet to handle binary files via HTTP * * Experimental service for Decentralized-Sharing Working Group (DSWG) * * * @author pablojan@gmail.com * */ @SuppressWarnings("serial") @Singleton public class DSFileServlet extends HttpServlet { private static final Log LOG = Log.get(DSFileServlet.class); @Inject public DSFileServlet() { } /** * Puts a file into this server with basic authorization * * <pre> * curl -vX PUT http://localhost:9898/shared/file.txt * --data-binary @file.txt * -H "Authorization: Basic YXVzZXJuYW1lOmFwYXNzd29yZA==" * -H "Content-Type: text/plain" * </pre> * */ @Override protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { // Check auth checkCredentials(req); // Check if a place to store the file is in the URL String path = req.getPathInfo(); if (path == null) { throw new HttpResponseException(HttpServletResponse.SC_BAD_REQUEST); } // TODO match path with a destination for the file // Process file content // req.getContentType(); BufferedInputStream inputBuffer = new BufferedInputStream(req.getInputStream()); byte[] readBuffer = new byte[128]; int r = 0; int totalBytes = 0; while ((r = inputBuffer.read(readBuffer)) != -1) { // do something with data totalBytes += r; } LOG.info("Received " + totalBytes + " bytes for file " + path); } catch (HttpResponseException e) { for (Entry<String, String> h : e.getHeaders().entrySet()) resp.addHeader(h.getKey(), h.getValue()); resp.sendError(e.getHttpResponseCode()); } catch (IOException e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } resp.setStatus(HttpServletResponse.SC_OK); } protected void checkCredentials(HttpServletRequest req) throws HttpResponseException { String username = null; String password = null; String authHeader = req.getHeader("Authorization"); if (authHeader != null) { StringTokenizer st = new StringTokenizer(authHeader); if (st.hasMoreTokens()) { try { String basic = st.nextToken(); if (basic.equalsIgnoreCase("Basic")) { String credentials = ""; credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); int p = credentials.indexOf(":"); if (p != -1) { username = credentials.substring(0, p).trim(); password = credentials.substring(p + 1).trim(); } else { throw new HttpResponseException(HttpServletResponse.SC_BAD_REQUEST); } } } catch (IndexOutOfBoundsException e) { throw new HttpResponseException(HttpServletResponse.SC_BAD_REQUEST); } catch (UnsupportedEncodingException e) { throw new HttpResponseException(HttpServletResponse.SC_BAD_REQUEST); } catch (NoSuchElementException e) { throw new HttpResponseException(HttpServletResponse.SC_BAD_REQUEST); } } } if (username == null || username.isEmpty()) { // TODO check if this is the rigt response for a bad formed request throw new HttpResponseException(HttpServletResponse.SC_FORBIDDEN).addHeader( "WWW-Authenticate", "Basic realm=\"swell\""); } // TODO login with username and password } }