package org.openintents.wifiserver.requesthandler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.openintents.wifiserver.preference.OiWiFiPreferences_;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.googlecode.androidannotations.annotations.EBean;
import com.googlecode.androidannotations.annotations.RootContext;
import com.googlecode.androidannotations.annotations.sharedpreferences.Pref;
/**
* The FileHandler interprets the request URL as a path to a file and tries to
* return this.
* An object must not be constructed using this class' constructor but the
* <code>FileHandler_</code>'s one.
* This is necessary because of the injection mechanism.
*
* @author Stanley Förster
*
*/
@EBean
public class FileHandler implements HttpRequestHandler {
private final static String TAG = FileHandler.class.getSimpleName();
/**
* Context which is used to access the app's assets.
*/
@RootContext protected Context mContext;
@Pref protected OiWiFiPreferences_ prefs;
/**
* This map is used to map file extensions to mime types.
*/
private final static Map<String, String> mimeMapping = new HashMap<String, String>() {
private static final long serialVersionUID = -439543272217048417L;
{
put("js", "text/javascript");
put("htm", "text/html");
put("html", "text/html");
put("png", "image/png");
put("css", "text/css");
put("gif", "image/gif");
}
};
/**
* <p>
* {@inheritDoc}
* </p>
* Every URL is interpreted as path to a file. This file is returned with
* the appropriate mime type and status code 200.
* If a file does not exists the response will be empty and status code is
* 404.
* There are three exception of this:
* <ul>
* <li>If the URL is just "/", a redirection to index.html is returned
* (status code 301)</li>
* <li>If "index.html" is requested, the authentication attribute of the
* current context is checked. If it is set to true, the requested
* index.html file is returned (status code 200), otherwise the response
* will be a redirect to login.html (status code 301)
* <li>If "login.html" is requested, the appropriate file will be loaded and
* a salt will be injected before the page is returned (status code 200).
*/
@Override
public void handle(final HttpRequest request, final HttpResponse response, HttpContext context) throws HttpException, IOException {
if (!"GET".equals(request.getRequestLine().getMethod())) {
response.setStatusCode(405);
return;
}
String path = Uri.parse(request.getRequestLine().getUri()).getPath();
AbstractHttpEntity entity;
if (path.endsWith("favicon.png")) {
path = path.replace("favicon.png", "wifiserver.png");
}
if ("/".equals(path)) {
response.setStatusCode(301);
response.setHeader("Location", request.getRequestLine().getUri()+"index.html");
return;
}
if ("/index.html".equals(path)) {
Object authAttribute = context.getAttribute("authenticated");
if (!(authAttribute == null || (authAttribute instanceof Boolean && ((Boolean) authAttribute).booleanValue()))) {
response.setStatusCode(301);
response.setHeader("Location", request.getRequestLine().getUri().replace("index.html","login.html"));
return;
}
}
if ("/login.html".equals(path)){
final InputStream input = mContext.getAssets().open("webinterface"+path);
String password = prefs.customPassword().get();
String salt = password.substring(password.length()-8);
StringBuilder result = new StringBuilder();
String line = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
while (null != (line=reader.readLine())) {
result.append(line.replace("$SALT$", salt));
result.append('\n');
}
entity = new StringEntity(result.toString());
entity.setContentType("text/html");
response.setEntity(entity);
response.setStatusCode(200);
return;
}
try {
InputStream input = mContext.getAssets().open("webinterface"+path);
entity = new InputStreamEntity(input, -1);
response.setEntity(entity);
String ending = path.substring(path.lastIndexOf(".")+1);
if (ending != null && ending.length() > 0) {
String mime = mimeMapping.get(ending);
if (mime != null) {
entity.setContentType(mime);
}
}
response.setStatusCode(200);
return;
} catch (IOException e) {
Log.e(TAG, e.getMessage());
entity = new StringEntity("404 Not Found");
entity.setContentType("text/plain");
response.setEntity(entity);
response.setStatusCode(404);
}
}
}