/** Copyright (C) 2012 Delcyon, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.delcyon.capo.http; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.logging.Level; import com.delcyon.capo.CapoApplication; import com.delcyon.capo.Configuration; import com.delcyon.capo.CapoApplication.Location; import com.delcyon.capo.Configuration.PREFERENCE; import com.delcyon.capo.annotations.DirectoyProvider; import com.delcyon.capo.datastream.StreamProcessor; import com.delcyon.capo.datastream.StreamProcessorProvider; import com.delcyon.capo.datastream.StreamUtil; import com.delcyon.capo.resourcemanager.ResourceDescriptor; import com.delcyon.capo.resourcemanager.ResourceParameter; import com.delcyon.capo.resourcemanager.ResourceParameter.Source; import com.delcyon.capo.resourcemanager.types.FileResourceType; import com.delcyon.capo.server.CapoServer; /** * @author jeremiah */ @StreamProcessorProvider(streamIdentifierPatterns = { "GET .*","POST .*","PUT .*" }) @DirectoyProvider(preferenceName="WEB_DIR",preferences=Configuration.PREFERENCE.class,location=Location.SERVER) public class HTTPStreamConsumer implements StreamProcessor { private static final byte[] messageBoundryPattern = new String("\r\n\r\n").getBytes(); @Override public void init(HashMap<String, String> sessionHashMap) throws Exception { } @Override public void processStream(BufferedInputStream bufferedInputStream, OutputStream outputStream) throws Exception { byte[] buffer = new byte[CapoApplication.getConfiguration().getIntValue(PREFERENCE.BUFFER_SIZE)]; int bytesRead = 0; while (bytesRead >= 0) { bytesRead = bufferedInputStream.read(buffer); List<Integer> matchList = StreamUtil.searchForBytePattern(messageBoundryPattern, buffer, 0, bytesRead); if(matchList.size() > 0) { //we only care about headers here, so trim, and jump out bytesRead = matchList.get(0)+messageBoundryPattern.length; break; } } SimpleHttpRequest request = new SimpleHttpRequest(new String(buffer,0,bytesRead)); SimpleHttpResponse response = new SimpleHttpResponse(); ResourceDescriptor updatesResourceDescriptor = CapoApplication.getDataManager().getResourceDirectory(PREFERENCE.WEB_DIR.toString()); ResourceDescriptor fileResourceDescriptor = updatesResourceDescriptor.getChildResourceDescriptor(null, request.getPath()); //verify we're not trying to jump out of our directory tree here String trimmedURIString = fileResourceDescriptor.getResourceURI().getResourceURIString().substring(updatesResourceDescriptor.getResourceURI().getResourceURIString().length()); if (trimmedURIString.equals(request.getPath()) == false) { CapoServer.logger.log(Level.WARNING, "HTTP Security Issue: '"+request.getPath()+"'"); outputStream.close(); bufferedInputStream.close(); } try { fileResourceDescriptor.addResourceParameters(null, new ResourceParameter(FileResourceType.Parameters.PARENT_PROVIDED_DIRECTORY,PREFERENCE.WEB_DIR,Source.CALL)); fileResourceDescriptor.open(null); if (fileResourceDescriptor.getResourceMetaData(null).exists() == true && fileResourceDescriptor.getResourceMetaData(null).isReadable() == true && fileResourceDescriptor.getResourceMetaData(null).isContainer() == false) { response.setHeader("Content-Length", fileResourceDescriptor.getResourceMetaData(null).getLength()+""); response.setHeader("Content-Type", "application/octet-stream"); outputStream.write(response.getBytes()); StreamUtil.readInputStreamIntoOutputStream(fileResourceDescriptor.getInputStream(null), outputStream); } else { response.setResponseCode(404,"NOT FOUND"); CapoServer.logger.log(Level.FINE, "Sent response:\n"+new String(response.getBytes())); CapoServer.logger.log(Level.WARNING, "File Not Found: '"+request.getPath()+"'"); outputStream.write(response.getBytes()); } outputStream.close(); bufferedInputStream.close(); } catch (IOException ioException) { ioException.printStackTrace(); } finally { if(fileResourceDescriptor != null) { fileResourceDescriptor.release(null); } } } }