Warning: session_start(): open(/var/lib/php/sessions/sess_m7jdjc3jpvqh0836lcudkk6oeb, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
// for sub-bots
please include function serveRedirect.
please include function serve403.
please include function serve404.
please include function serve500.
please include function serveFile.
please include function serveFileWithName.
please include function serveFile_maxCache.
please include function serveByteArray.
please include function serveByteArray_maxCache.
please include function serveInputStream.
sclass WebSocketWithWebRequest extends WebSocket {
WebRequest request;
*(NanoHTTPD.IHTTPSession session, WebRequest *request) {
super(session);
}
IWebRequest webRequest() { ret request; }
}
sclass WebRequest implements IWebRequest {
NanoHTTPD.IHTTPSession httpSession;
S uri, subURI;
SS params, files;
S cookie, clientIP;
Session session;
bool isHttps, noSpam;
*(NanoHTTPD.IHTTPSession *httpSession, S *uri, SS *params) {
files = httpSession.getFiles();
clientIP = getClientIPFromHeaders(httpSession.getHeaders());
}
public S uri() { ret uri; }
public SS params() { ret params; }
public SS files() { ret files; }
public SS headers() { ret httpSession.getHeaders(); }
public S cookie() { ret cookie; }
public bool isHttps() { ret isHttps; }
User loggedInUser() {
ret session == null ? null : session.user();
}
S googleClientID() {
S domain = lower(domain());
File jsonFile = googleClientSecretFileForDomain(domain);
if (!fileExists(jsonFile)) null;
Map map = decodeJSONMap(loadTextFile(jsonFile));
map = (Map) map.get("web");
ret (S) map.get("client_id");
}
public void noSpam {
if (noSpam) ret;
set noSpam;
//print("noSpam count: " + simpleSpamClientDetect2_markNoSpam(clientIP, uri) + " (" + clientIP + "/" + uri + ")");
}
}
concept User > ConceptWithGlobalID {
long lastSeen;
}
concept CookieUser > User {
S cookie;
toString { ret "[cookieUser " + md5(cookie) + "]"; }
}
concept GoogleUser > User {
long googleLogInDate;
S googleEmail, googleFirstName, googleLastName;
bool googleEmailVerified;
toString { ret googleFirstName + " " + googleLastName; }
}
concept Session {
S cookie;
User user;
long accesses;
User user() {
if (user == null)
cset(this, user := uniq CookieUser(+cookie));
ret user;
}
}
abstract sclass DynEleuMultiIP extends DynPrintLogAndEnabled {
transient autoDispose Set httpServers = syncLinkedHashSet();
switchable int httpPort = 8000;
double clearSessionsInterval = 60.0;
double clearSessionsTimeout = 300.0;
switchable double maxModuleReloadWait = 20.0;
switchable double strayWebSocketDelay = 5.0;
// Eleu-wide sessions... I don't think anyone uses these anymore
switchable bool useSessions;
void start {
super.start();
dbIndexing(Session, 'cookie, CookieUser, 'cookie, GoogleUser, 'googleEmail);
dm_restartOnFieldChange enabled();
if (!enabled) ret;
dm_startThread("Start Web Servers", r {
start_webServers(ipsToBindTo());
});
dm_doEvery(clearSessionsInterval, r clearSessions);
//ownResource(serverSocketFactory_autoUpdate());
}
void clearSessions {
Cl l = filter(list(Session),
s -> s.accesses <= 1 && elapsedSeconds_timestamp(s.created) >= clearSessionsTimeout);
if (nempty(l)) {
print("Dropping " + nSessions(l));
deleteConcepts(l);
}
}
WebSocket newWebSocket(NanoHTTPD.IHTTPSession handshake) enter {
vmBus_send haveNewWebSocket(module(), handshake);
S domain = mapGet(handshake.getHeaders(), "host");
S uri = handshake.getUri();
SS params = handshake.getParms();
print("Making WebSocket. domain: " + domain + ", uri: " + uri);
WebRequest req = new(handshake, uri, params);
WebSocket ws = new WebSocketWithWebRequest(handshake, req);
S module = moduleForDomainAndURI(domain, uri);
if (nempty(module) && !dm_moduleIsStartingOrReloading(module)) pcall {
dm_callOpt(module, 'handleWebSocket, ws);
} else {
sleepSeconds(strayWebSocketDelay);
ws.close(); // Hopefully just a reload
}
ret ws;
}
O webServe(S uri, SS params) {
WebRequest req = new(NanoHTTPD.currentSession!, uri, params);
print("IP: " + req.clientIP);
/*Pair spamCheck = spamBlocker.checkRequest(req.uri, req.clientIP);
if (spamCheck.b) {
print("Request from blocked IP: " + req.clientIP);
sleepSeconds(60.0);
ret print("go away");
}*/
// fill more fields of WebRequest
fillWebRequest(req);
// log some
printVars("webServe", +uri, userAgent := req.userAgent());
// Serve Let's encrypt challenges
if (startsWith(uri, "/.well-known/")) {
S fileName = "validation.txt";
/*if (swic(req.domain(), "www."))
fileName = "validation-www.txt";*/
ret loadTextFile(userDir(fileName));
}
S module = moduleForDomainAndURI(req.domain(), uri);
if (nempty(module)) {
if (sleepWhile(() -> dm_moduleIsStartingOrReloading(module), max := maxModuleReloadWait))
ret subBot_serve500("Reload taking too long");
ret eleu_callModuleHTMLMethod(module, req);
}
ret subBot_serve404();
}
// override me
S moduleForDomain(S domain) { null; }
// or me
S moduleForDomainAndURI(S domain, S uri) { ret moduleForDomain(domain); }
ServeHttp_CookieHandler makeCookieHandler() {
ret nu ServeHttp_CookieHandler(verbose := true);
}
void fillWebRequest(WebRequest req) {
req.cookie = makeCookieHandler().handle();
req.isHttps = false;
// Get session
req.session = nempty(req.cookie) && useSessions ? uniq Session(cookie := req.cookie) : null;
if (req.session != null)
cset(req.session, accesses := req.session.accesses+1);
print(session := req.session);
}
/*void enhanceFrame(Container c) {
super.enhanceFrame(c);
internalFrameMenuItem(c, "Show blocked IPs", rEnterThread {
print("Blocked IPs: " + spamBlocker.blockedIPs);
});
}*/
LS ipsToBindTo() {
ret myLocalIPs();
}
void start_webServers(LS ips) {
forEach_pcall(ips, ip -> {
var httpd = new WebSocketHTTPD(ip, httpPort, lambda1 newWebSocket);
ctex { httpd.start(); }
httpServers.add(httpd);
print("Web server started at http://" + ip + ":" + httpd.getPort());
});
}
} // end of module