package br.com.ftt.bettaserver.streaming.http; import static org.jboss.netty.handler.codec.http.HttpHeaders.*; import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*; import static org.jboss.netty.handler.codec.http.HttpMethod.*; import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*; import static org.jboss.netty.handler.codec.http.HttpVersion.*; import java.io.File; import java.io.FileNotFoundException; import java.io.RandomAccessFile; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelFutureProgressListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.DefaultFileRegion; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.FileRegion; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.handler.codec.frame.TooLongFrameException; import org.jboss.netty.handler.codec.http.DefaultHttpResponse; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.jboss.netty.handler.ssl.SslHandler; import org.jboss.netty.handler.stream.ChunkedFile; import org.jboss.netty.util.CharsetUtil; public class BettaUdpFileServerHandler extends SimpleChannelUpstreamHandler { @Override public void messageReceived( ChannelHandlerContext ctx, MessageEvent e ) throws Exception { HttpRequest request = (HttpRequest)e.getMessage( ) ; if( request.getMethod( ) != GET ) { sendError( ctx, FORBIDDEN ) ; return ; } final String path = sanitizeUri( request.getUri( ) ) ; if( path == null ) { sendError( ctx, FORBIDDEN ) ; return ; } File file = new File(path) ; if( file.isHidden( ) || !file.exists( ) ) { sendError( ctx, NOT_FOUND ) ; return ; } RandomAccessFile raf ; try { raf = new RandomAccessFile( file, "r" ) ; } catch( FileNotFoundException fnfe ) { sendError( ctx, NOT_FOUND ) ; return; } long fileLength = raf.length( ) ; HttpResponse response = new DefaultHttpResponse( HTTP_1_1, OK ) ; setContentLength( response, fileLength ) ; Channel ch = e.getChannel( ) ; //Escreve a linha inicial do cabe�alho ch.write( response ) ; // Escreve o conte�do ChannelFuture writeFuture ; if( ch.getPipeline( ).get( SslHandler.class ) != null ) { writeFuture = ch.write( new ChunkedFile( raf, 0, fileLength, 8192 ) ) ; } else { final FileRegion region = new DefaultFileRegion( raf.getChannel( ), 0, fileLength ) ; writeFuture = ch.write( region ) ; writeFuture.addListener( new ChannelFutureProgressListener( ) { @Override public void operationComplete( ChannelFuture arg0 ) throws Exception { region.releaseExternalResources( ) ; } @Override public void operationProgressed( ChannelFuture future, long amount, long current, long total ) throws Exception { System.out.printf( "%s: %d / %d (+%d)%n", path, current, total, amount ); } }) ; } // Decide se fecha a conex�o ou n�o!! if( !isKeepAlive( request ) ) { writeFuture.addListener( ChannelFutureListener.CLOSE ) ; } } @Override public void exceptionCaught( ChannelHandlerContext ctx, ExceptionEvent e ) throws Exception { Channel ch = e.getChannel( ) ; Throwable cause = e.getCause( ) ; if( cause instanceof TooLongFrameException ) { sendError( ctx, BAD_REQUEST ) ; return ; } cause.printStackTrace( ) ; if( ch.isConnected( ) ) { sendError( ctx, INTERNAL_SERVER_ERROR ) ; } } private String sanitizeUri( String uri ) { try { uri = URLDecoder.decode( uri, "UTF-8" ) ; } catch ( UnsupportedEncodingException e ) { try { uri = URLDecoder.decode( uri, "ISO-8859-1" ) ; } catch ( UnsupportedEncodingException e1 ) { throw new Error( ) ; } } // Converte barras separadoras de Arquivos uri = uri.replace( '/', File.separatorChar ) ; // Uma simples valida��o de seguran�a if( uri.contains( File.separator + "." ) || uri.contains( "." + File.separator ) || uri.startsWith( "." ) || uri.endsWith( "." )) { return null ; } // Converte o caminho absoluto return System.getProperty( "user.dir" ) + File.separator + uri ; } private void sendError( ChannelHandlerContext ctx, HttpResponseStatus status ) { HttpResponse response = new DefaultHttpResponse( HTTP_1_1, status ) ; response.setHeader( CONTENT_TYPE, "tex/plain; charset=UTF-8" ) ; response.setContent( ChannelBuffers.copiedBuffer( "Failure: " + status.toString( ) + "\r\n", CharsetUtil.UTF_8 ) ) ; // Fecha a conex�o assim que a mensagem � enviada ctx.getChannel( ).write( response ).addListener( ChannelFutureListener.CLOSE ) ; } public static void main( String[ ] args ) { System.out.println( System.getProperty( "user.dir" ) + File.separator ); } }