package cn.aprilsoft.TinyAppServer.reqNrep;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.aprilsoft.TinyAppServer.configuare.Configuare;
import cn.aprilsoft.TinyAppServer.exception.ServerException;
import cn.aprilsoft.TinyAppServer.processor.MainProcessor;
import cn.aprilsoft.TinyAppServer.session.Session;
import cn.aprilsoft.conf4j.Conf4j;
import cn.aprilsoft.http.URIUtil;
import cn.aprilsoft.io.FileUtil;
import cn.aprilsoft.lang.Pair;
import cn.aprilsoft.lang.StringUtil;
public final class RequestUtil {
private static final List<String> DEFAULT_INDEXS = Conf4j.getSemicolonSplitedTrimProperties(MainProcessor.class,
"indexs");
public static Request createRequest(Socket in) throws IOException {
Request request = new Request();
InputStream is = in.getInputStream();
List<String> headers = new ArrayList<String>();
StringBuilder line = new StringBuilder();
while (true) {
int i = is.read();
if (i < 0) {
break;
}
char c = (char) i;
if (c == '\r') {
continue;
}
if (c == '\n') {
if (line.length() == 0) {
break;
}
headers.add(line.toString());
line = new StringBuilder();
continue;
}
line.append(c);
}
Map<String, String> header = createHeader(request, headers);
request.setHeader(header);
request.setOrientHeaders(headers);
if ("POST".equals(request.getMethod())) {
StringBuilder postData = new StringBuilder();
long postDataSize = Integer.parseInt(request.getHeaderParameter("Content-Length"));
for (long i = 0; i < postDataSize; i++) {
postData.append((char) is.read());
}
header.put("Form", postData.toString());
}
// get charset form request
String query = request.getQuery();
String form = request.getForm();
String encodingFromQuery = getCharset(query);
if (encodingFromQuery != null) {
request.setCharset(encodingFromQuery);
}
String encodingFromForm = getCharset(form);
if ((encodingFromQuery == null) && (encodingFromForm != null)) {
request.setCharset(encodingFromForm);
}
request.setQuerys(createQuerys(query, request.getCharset()));
request.setForms(createForms(form, request.getCharset()));
return request;
}
private static Map<String, String> createHeader(Request request, List<String> headers) {
Map<String, String> header = new HashMap<String, String>();
for (int i = 0; i < headers.size(); i++) {
String line = headers.get(i);
if (i == 0) {
line = line.trim();
int firstBlank = line.indexOf(' ');
int lastBlank = line.lastIndexOf(' ');
String method = line.substring(0, firstBlank);
header.put("Method", method);
String url = line.substring(firstBlank + 1, lastBlank);
int firstQuestionMark = url.indexOf('?');
if (firstQuestionMark >= 0) {
String query = url.substring(firstQuestionMark + 1);
url = url.substring(0, firstQuestionMark);
header.put("Query", query);
}
header.put("OriUrl", url);
if ((url != null) && url.endsWith("/")) {
String path = FileUtil.combilePath(Configuare.BASE_PATH, url);
File file = new File(path);
if (file.exists() && file.isDirectory()) {
String indexFile = findIndex(path);
if (indexFile != null) {
url += indexFile;
}
}
}
url = URIUtil.decodeURI(request.getCharset(), url);
header.put("Url", url);
int lastSlash = line.lastIndexOf('/');
String http = line.substring(lastSlash + 1);
header.put("Http", http);
} else {
int indexOfCommma = line.indexOf(':');
String key = line.substring(0, indexOfCommma);
String value = line.substring(indexOfCommma + 1);
if (value.startsWith(" ")) {
value = value.substring(1);
}
header.put(key, value);
}
}
return header;
}
private static List<Pair<String, String>> createQuerys(String query, String encoding) {
return createPairs(query, encoding);
}
private static List<Pair<String, String>> createForms(String form, String encoding) {
return createPairs(form, encoding);
}
private static List<Pair<String, String>> createPairs(String pairString, String encoding) {
List<Pair<String, String>> pairs = new ArrayList<Pair<String, String>>();
if (pairString != null) {
String[] pairss = pairString.split("&");
for (int i = 0; i < pairss.length; i++) {
String key = pairss[i];
String value = "";
int equal = key.indexOf('=');
if (equal >= 0) {
value = key.substring(equal + 1);
key = key.substring(0, equal);
}
try {
key = URLDecoder.decode(key, encoding);
value = URLDecoder.decode(value, encoding);
} catch (UnsupportedEncodingException e) {
throw new ServerException(e);
}
pairs.add(new Pair<String, String>(key, value));
}
}
return pairs;
}
public static String getCharset(String s) {
if (StringUtil.isEmpty(s)) {
return null;
}
s = s.replace("?", "&");
int charset = s.startsWith("charset=") ? 0 : s.indexOf("&charset=");
if (charset >= 0) {
String cs = s.substring(charset + (charset == 0 ? 0 : 1) + "charset=".length());
int and = cs.indexOf("&");
if (and >= 0) {
return cs.substring(0, and);
} else {
return cs;
}
} else {
return null;
}
}
public static void fillSession(Request request, Session session) {
request.setSession(session);
}
private static String findIndex(String path) {
for (int i = 0; i < DEFAULT_INDEXS.size(); i++) {
File file = new File(path + File.separator + DEFAULT_INDEXS.get(i));
if (file.exists()) {
return DEFAULT_INDEXS.get(i);
}
}
return null;
}
}