Package org.gudy.azureus2.pluginsimpl.local.tracker

Source Code of org.gudy.azureus2.pluginsimpl.local.tracker.TrackerWebPageResponseImpl

/*
* File    : TrackerWebPageReplyImpl.java
* Created : 08-Dec-2003
* By      : parg
*
* Azureus - a Java Bittorrent client
*
* 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 2 of the License.
*
* 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 ( see the LICENSE file ).
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package org.gudy.azureus2.pluginsimpl.local.tracker;

/**
* @author parg
*
*/

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.core3.tracker.host.TRHostTorrent;
import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils;
import org.gudy.azureus2.core3.util.AsyncController;
import org.gudy.azureus2.core3.util.BEncoder;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TimeFormatter;
import org.gudy.azureus2.core3.util.TorrentUtils;
import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;

import com.aelitis.azureus.core.util.HTTPUtils;

public class
TrackerWebPageResponseImpl
  implements TrackerWebPageResponse
{
  private static final String  NL      = "\r\n";

  private ByteArrayOutputStream  baos = new ByteArrayOutputStream(2048);

  private String        content_type = "text/html";

  private int          reply_status  = 200;

  private Map<String,String>    header_map   = new LinkedHashMap<String,String>();

  private TrackerWebPageRequestImpl   request;
  private boolean            is_async;
 
  private int              explicit_gzip  = 0; // not set, 1 = gzip, 2 = no gzip
  private boolean            is_gzipped;
 
  protected
  TrackerWebPageResponseImpl(
    TrackerWebPageRequestImpl   _request )
  {
    request     = _request;

    String  formatted_date_now     = TimeFormatter.getHTTPDate( SystemTime.getCurrentTime());

    setHeader( "Last-Modified",  formatted_date_now );

    setHeader( "Expires", formatted_date_now );
  }

  public void
  setLastModified(
    long    time )
  {
    String  formatted_date     = TimeFormatter.getHTTPDate( time );

    setHeader( "Last-Modified",  formatted_date );
  }

  public void
  setExpires(
    long    time )
  {
    String  formatted_date     = TimeFormatter.getHTTPDate( time );

    setHeader( "Expires",  formatted_date );
  }

  public void
  setContentType(
    String    type )
  {
    content_type  = type;
  }

  public void
  setReplyStatus(
    int    status )
  {
    reply_status   = status;
  }

  public void
  setHeader(
    String    name,
    String    value )
  {
    addHeader( name, value, true );
  }

  public void
  setGZIP(
    boolean    gzip )
  {
    explicit_gzip = gzip?1:2;
  }
 
  protected String
  addHeader(
    String    name,
    String    value,
    boolean    replace )
  {
    Iterator<String>  it = header_map.keySet().iterator();

    while( it.hasNext()){

      String  key = it.next();

      if ( key.equalsIgnoreCase( name )){

        if ( replace ){

          it.remove();

        }else{

          return( header_map.get( key ));
        }
      }
    }

    header_map.put( name, value );
   
    return( value );
  }

  public OutputStream
  getOutputStream()
  {
    return( baos );
  }

  protected void
  complete()

    throws IOException
  {
    if ( is_async ){
     
      return;
    }
   
    byte[]  reply_bytes = baos.toByteArray();

    // System.out.println( "TrackerWebPageResponse::complete: data = " + reply_bytes.length );

    String  status_string = "BAD";

      // random collection

    if ( reply_status == 200 ){

      status_string = "OK";

    }else if ( reply_status == 204 ){

      status_string = "No Content";

    }else if ( reply_status == 206 ){

      status_string = "Partial Content";

    }else if ( reply_status == 401 ){

      status_string = "Unauthorized";

    }else if ( reply_status == 404 ){

      status_string = "Not Found";

    }else if ( reply_status == 501 ){

      status_string = "Not Implemented";
    }

    String reply_header = "HTTP/1.1 " + reply_status + " " + status_string + NL;

      // add header fields if not already present

    addHeader( "Server", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION, false );
   
    if ( request.canKeepAlive()){
     
      String  applied_value = addHeader( "Connection", "keep-alive", false );
     
      if ( applied_value.equalsIgnoreCase( "keep-alive" )){
     
        request.setKeepAlive( true );
      }
    }else{
     
      addHeader( "Connection", "close", true );
    }
   
    addHeader( "Content-Type", content_type, false );

    boolean do_gzip = false;
   
    if ( explicit_gzip == 1 && !is_gzipped ){
     
      Map headers = request.getHeaders();
   
      String  accept_encoding = (String)headers.get("accept-encoding");
   
      if ( HTTPUtils.canGZIP(accept_encoding)){
     
        is_gzipped = do_gzip = true;
       
        header_map.put("Content-Encoding", "gzip");
      }
    }
   
    Iterator  it = header_map.keySet().iterator();

    while( it.hasNext()){

      String  name   = (String)it.next();
      String  value   = (String)header_map.get(name);

      reply_header += name + ": " + value + NL;
    }
   
    if ( do_gzip ){

        // try and set the content-length to that of the compressed data
     
      if ( reply_bytes.length < 512*1024 ){
       
        ByteArrayOutputStream temp = new ByteArrayOutputStream( reply_bytes.length );
       
        GZIPOutputStream gzos = new GZIPOutputStream(temp);
       
        gzos.write( reply_bytes );
       
        gzos.finish();
       
        reply_bytes = temp.toByteArray();
       
        do_gzip = false;
      }
    }
   
    reply_header +=
      "Content-Length: " + reply_bytes.length + NL +
      NL;

    // System.out.println( "writing reply:" + reply_header );

    OutputStream os = request.getOutputStream();
   
    os.write( reply_header.getBytes());

    if ( do_gzip ){
     
      GZIPOutputStream gzos = new GZIPOutputStream(os);
     
      gzos.write( reply_bytes );
     
      gzos.finish();
     
    }else{
   
      os.write( reply_bytes );
    }
   
    os.flush();
  }

  public boolean
  useFile(
    String    root_dir,
    String    relative_url )

    throws IOException
  {
    String  target = root_dir + relative_url.replace('/',File.separatorChar);

    File canonical_file = new File(target).getCanonicalFile();

      // make sure some fool isn't trying to use ../../ to escape from web dir

    if ( !canonical_file.toString().toLowerCase().startsWith( root_dir.toLowerCase())){

      return( false );
    }

    if ( canonical_file.isDirectory()){

      return( false );
    }

    if ( canonical_file.canRead()){

      String str = canonical_file.toString().toLowerCase();

      int  pos = str.lastIndexOf( "." );

      if ( pos == -1 ){

        return( false );
      }

      String  file_type = str.substring(pos+1);

      FileInputStream  fis = null;

      try{
        fis = new FileInputStream(canonical_file);

        useStream( file_type, fis );

        return( true );

      }finally{

        if ( fis != null ){

          fis.close();
        }
      }
    }

    return( false );
  }

  public void
  useStream(
    String    file_type,
    InputStream  input_stream )

    throws IOException
  {
    OutputStream  os = getOutputStream();

    String response_type = HTTPUtils.guessContentTypeFromFileType(file_type);
   
    if ( explicit_gzip != 2 && HTTPUtils.useCompressionForFileType(response_type)){
     
      Map headers = request.getHeaders();
     
      String  accept_encoding = (String)headers.get("accept-encoding");
     
      if ( HTTPUtils.canGZIP(accept_encoding)){

        is_gzipped = true;
       
        os = new GZIPOutputStream(os);
       
        header_map.put("Content-Encoding", "gzip");
      }
    }
   
    setContentType( response_type );

    byte[]  buffer = new byte[4096];

    while(true){

      int  len = input_stream.read(buffer);

      if ( len <= 0 ){

        break;
      }

      os.write( buffer, 0, len );
    }
   
    if ( os instanceof GZIPOutputStream ){
     
      ((GZIPOutputStream)os).finish();
    }
  }

  public void
  writeTorrent(
    TrackerTorrent  tracker_torrent )

    throws IOException
  {
    try{

      TRHostTorrent  host_torrent = ((TrackerTorrentImpl)tracker_torrent).getHostTorrent();

      TOTorrent  torrent = host_torrent.getTorrent();

      // make a copy of the torrent

      TOTorrent  torrent_to_send = TOTorrentFactory.deserialiseFromMap(torrent.serialiseToMap());

      // remove any non-standard stuff (e.g. resume data)

      torrent_to_send.removeAdditionalProperties();

      if ( !TorrentUtils.isDecentralised( torrent_to_send )){

        URL[][]  url_sets = TRTrackerUtils.getAnnounceURLs();

          // if tracker ip not set then assume they know what they're doing

        if ( host_torrent.getStatus() != TRHostTorrent.TS_PUBLISHED && url_sets.length > 0 ){

            // if the user has disabled the mangling of urls when hosting then don't do it here
            // either

          if ( COConfigurationManager.getBooleanParameter("Tracker Host Add Our Announce URLs")){

            String protocol = torrent_to_send.getAnnounceURL().getProtocol();

            for (int i=0;i<url_sets.length;i++){

              URL[]  urls = url_sets[i];

              if ( urls[0].getProtocol().equalsIgnoreCase( protocol )){

                torrent_to_send.setAnnounceURL( urls[0] );

                torrent_to_send.getAnnounceURLGroup().setAnnounceURLSets( new TOTorrentAnnounceURLSet[0]);

                for (int j=1;j<urls.length;j++){

                  TorrentUtils.announceGroupsInsertLast( torrent_to_send, new URL[]{ urls[j] });
                }

                break;
              }
            }
          }
        }
      }

      baos.write( BEncoder.encode( torrent_to_send.serialiseToMap()));

      setContentType( "application/x-bittorrent" );

    }catch( TOTorrentException e ){

      Debug.printStackTrace( e );

      throw( new IOException( e.toString()));
    }
  }
 
  public void
  setAsynchronous(
    boolean a )
 
    throws IOException
  {
    AsyncController async_control = request.getAsyncController();
   
    if ( async_control == null ){
     
      throw( new IOException( "Request is not non-blocking" ));
    }
   
    if ( a ){
     
      is_async  = true;
     
      async_control.setAsyncStart();
     
    }else{
     
      is_async  = false;
     
      complete();
     
      async_control.setAsyncComplete();
    }
  }
 
  public boolean
  getAsynchronous()
  {
    return( is_async );
  }
}
TOP

Related Classes of org.gudy.azureus2.pluginsimpl.local.tracker.TrackerWebPageResponseImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.