Package freenet.clients.http

Source Code of freenet.clients.http.StaticToadlet

package freenet.clients.http;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.Date;

import freenet.client.DefaultMIMETypes;
import freenet.l10n.NodeL10n;
import freenet.support.api.Bucket;
import freenet.support.api.HTTPRequest;
import freenet.support.io.FileBucket;

/**
* Static Toadlet.
* Serve up static files
*/
public class StaticToadlet extends Toadlet {
  StaticToadlet() {
    super(null);
  }
 
  public static final String ROOT_URL = "/static/";
  public static final String ROOT_PATH = "staticfiles/";
  public static final String OVERRIDE = "override/";
  public static final String OVERRIDE_URL = ROOT_URL + OVERRIDE;
 
  public void handleMethodGET(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException {
    String path = uri.getPath();
   
    if (!path.startsWith(ROOT_URL)) {
      // we should never get any other path anyway
      return;
    }
    try {
      path = path.substring(ROOT_URL.length());
    } catch (IndexOutOfBoundsException ioobe) {
      this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathNotFound"));
      return;
    }
   
    // be very strict about what characters we allow in the path, since
    if (!path.matches("^[A-Za-z0-9\\._\\/\\-]*$") || (path.indexOf("..") != -1)) {
      this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathInvalidChars"));
      return;
    }
   
    if(path.startsWith(OVERRIDE)) {
      File f = this.container.getOverrideFile();
      if(f == null || (!f.exists()) || (f.isDirectory()) || (!f.isFile())) {
        this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathInvalidChars"));
        return;
      }
      f = f.getAbsoluteFile();
      if(f == null || (!f.exists()) || (f.isDirectory()) || (!f.isFile())) {
        this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathInvalidChars"));
        return;
      }
      File parent = f.getParentFile();
      // Basic sanity check.
      // Prevents user from specifying root dir.
      // They can still shoot themselves in the foot, but only when developing themes/using custom themes.
      // Because of the .. check above, any malicious thing cannot break out of the dir anyway.
      if(parent.getParentFile() == null) {
        this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathInvalidChars"));
        return;
      }
      File from = new File(parent, path.substring(OVERRIDE.length()));
      if((!from.exists()) && (!from.isFile())) {
        this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathInvalidChars"));
        return;
      }
      try {
        FileBucket fb = new FileBucket(from, true, false, false, false);
        ctx.sendReplyHeadersStatic(200, "OK", null, DefaultMIMETypes.guessMIMEType(path, false), fb.size(), new Date(System.currentTimeMillis() - 1000)); // Already expired, we want it to reload it.
        ctx.writeData(fb);
        return;
      } catch (IOException e) {
        // Not strictly accurate but close enough
        this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathNotFound"));
        return;
      }
    }
   
    InputStream strm = getClass().getResourceAsStream(ROOT_PATH+path);
    if (strm == null) {
      this.sendErrorPage(ctx, 404, l10n("pathNotFoundTitle"), l10n("pathNotFound"));
      return;
    }
    Bucket data = ctx.getBucketFactory().makeBucket(strm.available());
    OutputStream os = data.getOutputStream();
    try {
    byte[] cbuf = new byte[4096];
    while(true) {
      int r = strm.read(cbuf);
      if(r == -1) break;
      os.write(cbuf, 0, r);
    }
    } finally {
      strm.close();
      os.close();
    }
   
    URL url = getClass().getResource(ROOT_PATH+path);
    Date mTime = getUrlMTime(url);
   
    ctx.sendReplyHeadersStatic(200, "OK", null, DefaultMIMETypes.guessMIMEType(path, false), data.size(), mTime);

    ctx.writeData(data);
  }
 
  /**
   * Try to find the modification time for a URL, or return null if not possible
   * We usually load our resources from the JAR, or possibly from a file in some setups, so we check the modification time of
   * the JAR for resources in a jar and the mtime for files.
   */
  private Date getUrlMTime(URL url) {
    if (url.getProtocol().equals("jar")) {
      File f = new File(url.getPath().substring(0, url.getPath().indexOf('!')));
      return new Date(f.lastModified());
    } else if (url.getProtocol().equals("file")) {
      File f = new File(url.getPath());
      return new Date(f.lastModified());
    } else {
      return null;
    }
  }
 
  private String l10n(String key) {
    return NodeL10n.getBase().getString("StaticToadlet."+key);
  }

  @Override
  public String path() {
    return ROOT_URL;
  }

  /** Do we have a specific static file? Note that override files are not
   * supported here as it is a static method.
   * @param The path to the file, relative to the staticfiles directory.
   */
  public static boolean haveFile(String path) {
    URL url = StaticToadlet.class.getResource(ROOT_PATH+path);
    return url != null;
  }

}
TOP

Related Classes of freenet.clients.http.StaticToadlet

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.