Package freenet.clients.fcp

Source Code of freenet.clients.fcp.FilterMessage

package freenet.clients.fcp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;

import freenet.client.DefaultMIMETypes;
import freenet.client.async.ClientContext;
import freenet.client.filter.ContentFilter;
import freenet.client.filter.FilterOperation;
import freenet.client.filter.UnsafeContentTypeException;
import freenet.client.filter.ContentFilter.FilterStatus;
import freenet.node.FSParseException;
import freenet.node.Node;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
import freenet.support.api.Bucket;
import freenet.support.api.BucketFactory;
import freenet.support.io.Closer;
import freenet.support.io.FileBucket;

/**
* Message for testing the content filter on a file.  Server will respond with a FilterResultMessage.
*
* Filter
* Identifier=filter1 // identifier
* Operation=BOTH // READ/WRITE/BOTH (ignored for now)
* MimeType=text/html // required if DataSource=DIRECT
*
* DataSource=DISK // read a file from disk
* Filename=/home/bob/file.html // path to the file
* End
* or
* DataSource=DIRECT // the data is in the message
* DataLength=1000 // 1000 bytes
* Data
*/
public class FilterMessage extends DataCarryingMessage {
  public static final String NAME = "Filter";

  private final String identifier;
  private final FilterOperation operation;
  private final DataSource dataSource;
  private final String mimeType;
  private final long dataLength;
  private final String filename;
 
  private final BucketFactory bf;

  public FilterMessage(SimpleFieldSet fs, BucketFactory bf) throws MessageInvalidException {
    try {
      identifier = fs.getString(IDENTIFIER);
    } catch (FSParseException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain an " + IDENTIFIER + " field", null, false);
    }
    String op;
    try {
      op = fs.getString("Operation");
    } catch (FSParseException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain an Operation field", identifier, false);
    }
    try {
      operation = FilterOperation.valueOf(op);
    } catch (IllegalArgumentException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Illegal Operation value", identifier, false);
    }
    String ds;
    try {
      ds = fs.getString("DataSource");
    } catch (FSParseException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain a DataSource field", identifier, false);
    }
    try {
      dataSource = DataSource.valueOf(ds);
    } catch (IllegalArgumentException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Illegal DataSource value", identifier, false);
    }
    String inputMimeType = fs.get("MimeType");
    filename = fs.get("Filename");
    if (dataSource == DataSource.DIRECT) {
      mimeType = inputMimeType;
      if (mimeType == null) {
        throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain a MimeType field", identifier, false);
      }
      String dl = fs.get("DataLength");
      if (dl == null) {
        throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain a DataLength field", identifier, false);
      }
      try {
        dataLength = fs.getLong("DataLength");
      } catch (FSParseException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "DataLength field must be a long", identifier, false);
      }
    } else if (dataSource == DataSource.DISK) {
      if (filename == null) {
        throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain a Filename field", identifier, false);
      }
      File file = new File(filename);
      if (!file.exists()) {
        throw new MessageInvalidException(ProtocolErrorMessage.FILE_NOT_FOUND, null, identifier, false);
      }
      if (!file.isFile()) {
        throw new MessageInvalidException(ProtocolErrorMessage.NOT_A_FILE_ERROR, null, identifier, false);
      }
      if (!file.canRead()) {
        throw new MessageInvalidException(ProtocolErrorMessage.COULD_NOT_READ_FILE, null, identifier, false);
      }
      if (inputMimeType != null) {
        mimeType = inputMimeType;
      } else {
        mimeType = bestGuessMimeType(filename);
        if (mimeType == null) {
          throw new MessageInvalidException(ProtocolErrorMessage.BAD_MIME_TYPE, "Could not determine MIME type from filename", identifier, false);
        }
      }
      dataLength = -1;
      this.bucket = new FileBucket(file, true, false, false, false);
    } else {
      throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Illegal DataSource value", identifier, false);
    }
    this.bf = bf;
  }

  @Override
  String getIdentifier() {
    return identifier;
  }

  @Override
  boolean isGlobal() {
    return false;
  }

  @Override
  long dataLength() {
    return dataLength;
  }

  @Override
  public SimpleFieldSet getFieldSet() {
    SimpleFieldSet fs = new SimpleFieldSet(true);
    fs.putSingle(IDENTIFIER, identifier);
    fs.putOverwrite("Operation", operation.name());
    fs.putOverwrite("DataSource", dataSource.name());
    fs.putOverwrite("MimeType", mimeType);
    fs.putOverwrite("Filename", filename);
    fs.put("DataLength", dataLength);
    return fs;
  }

  @Override
  public String getName() {
    return NAME;
  }

  @Override
  public void run(FCPConnectionHandler handler, Node node) throws MessageInvalidException {
    if (bucket == null) {
      throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Must contain data", identifier, false);
    }
    Bucket resultBucket;
    try {
      resultBucket = bf.makeBucket(-1);
    } catch (IOException e) {
      Logger.error(this, "Failed to create temporary bucket", e);
      throw new MessageInvalidException(ProtocolErrorMessage.INTERNAL_ERROR, e.toString(), identifier, false);
    }
    String resultCharset = null;
    String resultMimeType = null;
    boolean unsafe = false;
    InputStream input = null;
    OutputStream output = null;
    try {
      input = bucket.getInputStream();
      output = resultBucket.getOutputStream();
      FilterStatus status = applyFilter(input, output, handler.server.core.clientContext);
      resultCharset = status.charset;
      resultMimeType = status.mimeType;
    } catch (UnsafeContentTypeException e) {
      unsafe = true;
    } catch (IOException e) {
      Logger.error(this, "IO error running content filter", e);
      throw new MessageInvalidException(ProtocolErrorMessage.INTERNAL_ERROR, e.toString(), identifier, false);
    } finally {
      Closer.close(input);
      Closer.close(output);
    }
    FilterResultMessage response = new FilterResultMessage(identifier, resultCharset, resultMimeType, unsafe, resultBucket);
    handler.outputHandler.queue(response);
  }
 
  private FilterStatus applyFilter(InputStream input, OutputStream output, ClientContext clientContext) throws MessageInvalidException, UnsafeContentTypeException, IOException {
    URI fakeUri;
    try {
      fakeUri = new URI("http://127.0.0.1:8888/");
    } catch (URISyntaxException e) {
      Logger.error(this, "Inexplicable URI error", e);
      throw new MessageInvalidException(ProtocolErrorMessage.INTERNAL_ERROR, e.toString(), identifier, false);
    }
    //TODO: check operation, once ContentFilter supports write filtering
    return ContentFilter.filter(input, output, mimeType, fakeUri, null, null, null, clientContext.linkFilterExceptionProvider);
  }
 
  private String bestGuessMimeType(String filename)
  {
    String guessedMimeType = null;
    if (filename != null) {
      guessedMimeType = DefaultMIMETypes.guessMIMEType(filename, true);
    }
    return guessedMimeType;
  }

}
TOP

Related Classes of freenet.clients.fcp.FilterMessage

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.