package org.freertr.serv;
import java.util.ArrayList;
import java.util.List;
import org.freertr.cfg.cfgAll;
import org.freertr.cfg.cfgProxy;
import org.freertr.clnt.clntProxy;
import org.freertr.pipe.pipeLine;
import org.freertr.pipe.pipeSide;
import org.freertr.prt.prtGenConn;
import org.freertr.prt.prtServS;
import org.freertr.enc.encUrl;
import org.freertr.sec.secInfoUtl;
import org.freertr.tab.tabGen;
import org.freertr.user.userFilter;
import org.freertr.user.userFormat;
import org.freertr.user.userHelp;
import org.freertr.util.bits;
import org.freertr.util.cmds;
/**
* hypertext transfer protocol (rfc2616) server
*
* @author matecsaba
*/
public class servHttp extends servGeneric implements prtServS {
/**
* create instance
*/
public servHttp() {
}
/**
* port number
*/
public final static int clearPort = 80;
/**
* secure port
*/
public final static int securePort = 443;
/**
* html 401 transitive
*/
public final static String htmlHead = "
";
/**
* list of hosts
*/
protected tabGen hosts = new tabGen();
/**
* list of bots
*/
protected List bots = new ArrayList();
/**
* proxy to use
*/
protected clntProxy proxy;
/**
* second port to use
*/
protected int secondPort = -1;
/**
* error message
*/
protected String error;
/**
* single request
*/
protected boolean singleRequest;
/**
* default server path
*/
protected String defPath = defHostPat;
/**
* default subconnect
*/
protected int defSubcon;
/**
* buffer size
*/
protected int bufSiz = 65536;
/**
* default host path
*/
public final static String defHostPat = "/data/notfound/";
/**
* defaults text
*/
public final static userFilter[] defaultF = {
new userFilter("server http .*", cmds.tabulator + "port " + clearPort, null),
new userFilter("server http .*", cmds.tabulator + "protocol " + proto2string(protoAllStrm), null),
new userFilter("server http .*", cmds.tabulator + cmds.negated + cmds.tabulator + "proxy", null),
new userFilter("server http .*", cmds.tabulator + cmds.negated + cmds.tabulator + "error", null),
new userFilter("server http .*", cmds.tabulator + cmds.negated + cmds.tabulator + "single-request", null),
new userFilter("server http .*", cmds.tabulator + "def-path " + defHostPat, null),
new userFilter("server http .*", cmds.tabulator + "def-subconn", null),
new userFilter("server http .*", cmds.tabulator + "buffer 65536", null),
new userFilter("server http .*", cmds.tabulator + cmds.negated + cmds.tabulator + "second-port", null)
};
/**
* get defaults filter
*
* @return filter
*/
public userFilter[] srvDefFlt() {
return defaultF;
}
/**
* find one host
*
* @param s agent name
* @return true if found
*/
protected boolean findBot(String s) {
for (int i = 0; i < bots.size(); i++) {
String a = bots.get(i);
if (s.matches(a)) {
return true;
}
}
return false;
}
/**
* find one host
*
* @param s host name
* @return host descriptor, null if not found
*/
protected servHttpHost findHost(String s) {
servHttpHost ntry = new servHttpHost(this, s);
ntry = hosts.find(ntry);
if (ntry != null) {
return ntry;
}
for (int i = hosts.size() - 1; i >= 0; i--) {
ntry = hosts.get(i);
if (!ntry.host.startsWith("*")) {
continue;
}
if (!s.endsWith(ntry.host.substring(1, ntry.host.length()))) {
continue;
}
return ntry;
}
return null;
}
/**
* start connection
*
* @param pipe pipeline
* @param id connection
* @return false on success, true on error
*/
public boolean srvAccept(pipeSide pipe, prtGenConn id) {
pipe.setTime(120000);
new servHttpConn(this, pipe, id);
return false;
}
/**
* get config
*
* @param beg beginning
* @param l list
* @param filter default filter
*/
public void srvShRun(String beg, List l, int filter) {
if (proxy == null) {
l.add(beg + "no proxy");
} else {
l.add(beg + "proxy " + proxy.name);
}
if (error == null) {
l.add(beg + "no error");
} else {
l.add(beg + "error " + error);
}
cmds.cfgLine(l, secondPort < 0, beg, "second-port", "" + secondPort);
l.add(beg + "buffer " + bufSiz);
l.add(beg + "def-path " + defPath);
l.add(beg + "def-subconn" + servHttpUtil.subconn2string(defSubcon));
cmds.cfgLine(l, !singleRequest, beg, "single-request", "");
for (int i = 0; i < bots.size(); i++) {
l.add(beg + "bad-agent " + bots.get(i));
}
for (int hn = 0; hn < hosts.size(); hn++) {
servHttpHost ntry = hosts.get(hn);
if (ntry == null) {
continue;
}
ntry.getConfig(beg, l, filter);
}
}
/**
* configure
*
* @param cmd command
* @return false on success, true on error
*/
public boolean srvCfgStr(cmds cmd) {
String a = cmd.word();
boolean negated = false;
if (a.equals(cmds.negated)) {
negated = true;
a = cmd.word();
}
if (a.equals("bad-agent")) {
a = cmd.getRemaining();
if (negated) {
bots.remove(a);
return false;
}
if (bots.indexOf(a) >= 0) {
return false;
}
bots.add(a);
return false;
}
if (a.equals("second-port")) {
srvDeinit();
if (negated) {
secondPort = -1;
srvInit();
return false;
}
secondPort = bits.str2num(cmd.word());
srvInit();
return false;
}
if (a.equals("buffer")) {
bufSiz = bits.str2num(cmd.word());
return false;
}
if (a.equals("single-request")) {
singleRequest = !negated;
return false;
}
if (a.equals("def-path")) {
if (negated) {
defPath = defHostPat;
} else {
defPath = cmd.word();
}
return false;
}
if (a.equals("def-subconn")) {
defSubcon = servHttpUtil.string2subconn(negated, cmd);
return false;
}
if (a.equals("proxy")) {
if (negated) {
proxy = null;
return false;
}
cfgProxy prx = cfgAll.proxyFind(cmd.word(), false);
if (prx == null) {
cmd.error("no such proxy");
return false;
}
proxy = prx.proxy;
return false;
}
if (a.equals("error")) {
error = cmd.getRemaining();
if (negated) {
error = null;
return false;
}
return false;
}
if (!a.equals("host")) {
return true;
}
servHttpHost ntry = new servHttpHost(this, cmd.word());
servHttpHost old = hosts.add(ntry);
if (old != null) {
ntry = old;
}
a = cmd.word();
if (a.length() < 1) {
return false;
}
if (a.equals("path")) {
if (negated) {
hosts.del(ntry);
return false;
}
ntry.path = "/" + encUrl.normalizePath(cmd.word() + "/");
return false;
}
if (ntry.path == null) {
ntry.path = defPath;
ntry.subconn = defSubcon;
}
return ntry.doConfig(negated, a, cmd);
}
private final static void getSubconnHelp(int b, userHelp l) {
l.add(null, false, b, new int[]{b, -1}, "strip-path", "strip path");
l.add(null, false, b, new int[]{b, -1}, "strip-name", "strip filename");
l.add(null, false, b, new int[]{b, -1}, "strip-ext", "strip extension");
l.add(null, false, b, new int[]{b, -1}, "strip-param", "strip parameters");
l.add(null, false, b, new int[]{b, -1}, "keep-cred", "keep credentinals");
l.add(null, false, b, new int[]{b, -1}, "keep-host", "keep hostname");
l.add(null, false, b, new int[]{b, -1}, "keep-path", "append path");
}
/**
* get help
*
* @param l list
*/
public void srvHelp(userHelp l) {
l.add(null, false, 1, new int[]{-1}, "single-request", "one request per connection");
l.add(null, false, 1, new int[]{2}, "buffer", "set buffer size on connection");
l.add(null, false, 2, new int[]{-1}, "", "buffer in bytes");
l.add(null, false, 1, new int[]{2}, "proxy", "enable proxy support");
l.add(null, false, 2, new int[]{-1}, "", "proxy profile");
l.add(null, false, 1, new int[]{2}, "second-port", "enable dual binding");
l.add(null, false, 2, new int[]{-1}, "", "secure port");
l.add(null, false, 1, new int[]{2}, "bad-agent", "set host default path");
l.add(null, false, 2, new int[]{2, -1}, "", "user agent to deny");
l.add(null, false, 1, new int[]{2}, "def-path", "set host default path");
l.add(null, false, 2, new int[]{-1}, "", "path on the disk");
l.add(null, false, 1, new int[]{2}, "def-subconn", "set host default subconnect");
getSubconnHelp(2, l);
l.add(null, false, 1, new int[]{2}, "error", "set error message");
l.add(null, false, 2, new int[]{2, -1}, "", "error message");
l.add(null, false, 1, new int[]{2}, "host", "define one virtual server");
List lst = new ArrayList();
for (int i = 0; i < hosts.size(); i++) {
lst.add(hosts.get(i).host);
}
l.add(lst, false, 2, new int[]{3}, "", "name of server, * for any");
l.add(null, false, 3, new int[]{4}, "path", "set server root");
l.add(null, false, 4, new int[]{-1}, "", "root directory of server");
l.add(null, false, 3, new int[]{4}, "redir", "set redirect path");
l.add(null, false, 4, new int[]{-1}, "", "url to redirect to");
l.add(null, false, 3, new int[]{4}, "webring", "set redirect file");
l.add(null, false, 4, new int[]{-1}, "", "path to redirect list");
l.add(null, false, 3, new int[]{-1}, "logging", "log to syslog");
l.add(null, false, 3, new int[]{4}, "reconn", "reconnect to server");
l.add(null, false, 4, new int[]{5}, "", "proxy profile");
l.add(null, false, 5, new int[]{-1}, "", "server to redirect to");
l.add(null, false, 3, new int[]{4}, "translate", "translate the url");
l.add(null, false, 4, new int[]{4, -1}, "", "translation rule to use");
l.add(null, false, 3, new int[]{4}, "subconn", "reconnect only to the url");
getSubconnHelp(4, l);
l.add(null, false, 3, new int[]{4}, "stream", "stream from server");
l.add(null, false, 4, new int[]{5}, "", "content type");
l.add(null, false, 5, new int[]{6}, "", "proxy profile");
l.add(null, false, 6, new int[]{-1}, "", "server to stream from");
l.add(null, false, 3, new int[]{4}, "multiacc", "access multiple servers");
l.add(null, false, 4, new int[]{5}, "", "proxy profile");
l.add(null, false, 5, new int[]{5, -1}, "", "server to access");
l.add(null, false, 3, new int[]{-1}, "markdown", "allow markdown conversion");
l.add(null, false, 3, new int[]{-1}, "noindex", "disallow index for directory");
l.add(null, false, 3, new int[]{4}, "speed-limit", "limit download speeds");
l.add(null, false, 4, new int[]{-1}, "", "bytes per second");
l.add(null, false, 3, new int[]{4, -1}, "dirlist", "allow directory listing");
l.add(null, false, 4, new int[]{4, -1}, "readme", "put readme in front of listing");
l.add(null, false, 4, new int[]{4, -1}, "stats", "put statistics after listing");
l.add(null, false, 3, new int[]{4, -1}, "script", "allow script running");
l.add(null, false, 4, new int[]{4, -1}, "exec", "allow exec commands");
l.add(null, false, 4, new int[]{4, -1}, "config", "allow config commands");
l.add(null, false, 3, new int[]{4, -1}, "api", "allow api calls");
l.add(null, false, 4, new int[]{4, -1}, "exec", "allow exec commands");
l.add(null, false, 4, new int[]{4, -1}, "show", "allow show commands");
l.add(null, false, 4, new int[]{4, -1}, "script", "allow script commands");
l.add(null, false, 4, new int[]{4, -1}, "config", "allow config commands");
l.add(null, false, 4, new int[]{4, -1}, "ipinfo", "allow ip info commands");
secInfoUtl.getHelp(l, 3, "ipinfo", "allow ipinfo api");
l.add(null, false, 3, new int[]{4}, "search-script", "allow scripts defined in configuration");
l.add(null, false, 4, new int[]{-1}, "", "prefix");
l.add(null, false, 3, new int[]{-1}, "imagemap", "allow image map processing");
l.add(null, false, 3, new int[]{-1}, "websock", "allow websocket processing");
l.add(null, false, 3, new int[]{-1}, "webdav", "allow webdav processing");
l.add(null, false, 3, new int[]{-1}, "mediastream", "allow media streaming");
l.add(null, false, 3, new int[]{-1}, "class", "allow class running");
l.add(null, false, 3, new int[]{-1}, "upload", "allow upload files");
l.add(null, false, 3, new int[]{4}, "backup", "backup uploaded files");
l.add(null, false, 4, new int[]{5}, "", "number of backups to keep");
l.add(null, false, 5, new int[]{-1}, "", "root directory of backup");
l.add(null, false, 3, new int[]{4}, "sstp", "allow sstp clients");
l.add(null, false, 4, new int[]{-1}, "", "name of interface");
l.add(null, false, 3, new int[]{4}, "anyconn", "allow anyconnect clients");
l.add(null, false, 4, new int[]{-1}, "", "name of interface");
l.add(null, false, 3, new int[]{4}, "forti", "allow fortinet clients");
l.add(null, false, 4, new int[]{-1}, "", "name of interface");
l.add(null, false, 3, new int[]{4}, "authentication", "require authentication to access");
l.add(null, false, 4, new int[]{-1}, "", "authentication list");
l.add(null, false, 3, new int[]{4}, "style", "set page style tags");
l.add(null, false, 4, new int[]{4, -1}, "", "text to send");
secInfoUtl.getHelp(l, 2, "access-", null);
}
/**
* get name
*
* @return name
*/
public String srvName() {
return "http";
}
/**
* get port
*
* @return port
*/
public int srvPort() {
return clearPort;
}
/**
* get protocol
*
* @return protocol
*/
public int srvProto() {
return protoAllStrm;
}
/**
* initialize
*
* @return false on success, true on error
*/
public boolean srvInit() {
if (secondPort > 0) {
if (genStrmStart(this, new pipeLine(bufSiz, false), secondPort)) {
return true;
}
}
return genStrmStart(this, new pipeLine(bufSiz, false), 0);
}
/**
* deinitialize
*
* @return false on success, true on error
*/
public boolean srvDeinit() {
if (secondPort > 0) {
if (genericStop(secondPort)) {
return true;
}
}
return genericStop(0);
}
/**
* get show
*
* @return result
*/
public userFormat getShStat() {
userFormat res = new userFormat("|", "host|hit|last");
for (int i = 0; i < hosts.size(); i++) {
servHttpHost ntry = hosts.get(i);
res.add(ntry.host + "|" + ntry.askNum + "|" + bits.timePast(ntry.askTim));
}
return res;
}
/**
* get show
*
* @param s host to use
* @return result
*/
public List getShZone(String s) {
List res = new ArrayList();
for (int i = 0; i < hosts.size(); i++) {
servHttpHost ntry = hosts.get(i);
String a = ntry.host;
String b = "rr " + a + " cname " + s;
int o = a.indexOf(".");
if (o > 0) {
b = "zone " + a.substring(o + 1, a.length()) + " " + b;
}
res.add(b);
}
return res;
}
}