std::pair<PExprNode, FilePath> FileCompiler::loadCode(ExprLocation loc, ConstStrA name) { FilePath p = loc.getFileName(); if (p.getPath().empty()) p = FilePath(ConstStrW(L"."), true); for (ConstStrA::SplitIterator iter = name.split('/'); iter.hasItems();) { ConstStrA part = iter.getNext(); if (part.empty()) { continue; } else if (part == "..") { p = p / parent; } else { p = p / part; } } const PExprNode *code = codeCache.find(p); PExprNode out; if (code) out = *code; else { out = compileFile(p); codeCache(p, out); } return std::make_pair(out, p); }
void HttpClient::proxyConnect(PNetworkStream stream, ConstStrA host, ConstStrA authorization) { if (host.find(':') == naturalNull) { return proxyConnect(stream,StringA(host+ConstStrA(":443")),authorization); } PNetworkStream nstream = new BufferedNetworkStream(stream); HttpRequest req(stream.get(), host, mCONNECT, !useHTTP10); if (!authorization.empty()) { req.setHeader(fldProxyAuthorization,authorization); } req.closeOutput(); class ResponseResult: public IHttpResponseCB { public: virtual void storeStatus(natural statusCode, ConstStrA statusMessage) { status = statusCode; statusMsg.append(statusMessage); } virtual void storeHeaderLine(ConstStrA, ConstStrA) { } natural status; AutoArray<char, SmallAlloc<32> > statusMsg; }; ResponseResult res; HttpResponse resp(stream.get(),res,HttpResponse::readHeadersNow); if (status != 200) throw HttpStatusException(THISLOCATION,host,res.status, res.statusMsg); }
LightSpeed::JSON::PNode createArrayFromSet(LightSpeed::JSON::IFactory &factory, ConstStrA text, char sep) { LightSpeed::JSON::PNode arr = factory.newArray(); if (text.empty()) return arr; for (ConstStrA::SplitIterator iter = text.split(sep);iter.hasItems();) { ConstStrA name = iter.getNext(); if (!name.empty()) { arr->add(factory.newValue(name)); } } return arr; }
IniConfigT::Iterator::Iterator(const FieldMap &container, ConstStrA section, ConstStrA prefix) :innerIter(container.seek(SectionField(section,ConstStrA()))) { if (innerIter.hasItems()) { const FieldMap::Entity &e = innerIter.peek(); if (e.key.section == section) { this->section = e.key.section; if (e.key.field.head(prefix.length()) == prefix) { prefix = e.key.field.head(prefix.length()); } } } }
static ConstStrA findInAllowedSet(ConstStrA field, ConstStrA allowedSet) { using namespace LightSpeed; for (ConstStrA::SplitIterator iter = allowedSet.split(',');iter.hasItems();) { ConstStrA value = iter.getNext(); natural eq = value.find('='); if (eq == naturalNull) { if (value == field) return value; } else { if (value.head(eq) == field) { return value.offset(eq+1); } } } return ConstStrA(); }
integer ServiceApp::postMessage(ConstStrA command, const Args & args, SeqFileOutput output) { if (instance->imOwner()) return onMessage(command,args,output); AutoArrayStream<char, StaticAlloc<65536> > buffer; if (args.length() > 127) return onCommandLineError(args); buffer.write((char)(args.length())); buffer.copy(command.getFwIter()); buffer.write(0); for(natural i = 0, cnt = args.length();i < cnt;i++){ buffer.copy(WideToUtf8Reader<ConstStrW::Iterator>(args[i].getFwIter())); buffer.write(0); } AutoArray<byte,SmallAlloc<4096> > replybuff; replybuff.resize(instance->getReplyMaxSize()); natural sz = instance->request(buffer.data(), buffer.length(), replybuff.data(), replybuff.length(), timeout); if (sz < sizeof(integer)) throw ErrorMessageException(THISLOCATION,String("Invalid reply")); else { integer res = *reinterpret_cast<integer *>(replybuff.data()); ConstStrA msg(reinterpret_cast<char *>(replybuff.data()+sizeof(integer)),sz - sizeof(integer)); output.copy(msg.getFwIter()); return res; } }
natural Server::onGET(BredyHttpSrv::IHttpRequest& req, ConstStrA vpath) { if (vpath.empty() && req.getHeaderField(req.fldUpgrade) == "websocket" ) { if (!wsenabled) return stForbidden; else return req.forwardRequestTo(&wsHandler,vpath); } else { return HttpHandler::onGET(req,vpath); } }
LightSpeed::StringA dbOrderFromJSON(const LightSpeed::JSON::INode &nd) { using namespace LightSpeed; AutoArray<char, SmallAlloc<256> > buff; for (natural i = 0; i < nd.getEntryCount();i++) { ConstStrA fld = nd[i].getStringUtf8(); if (fld.empty() || fld == ConstStrA('^') || fld.find('`') != naturalNull) throw ErrorMessageException(THISLOCATION, "Unacceptable field name"); if (i) buff.append(ConstStrA(", ")); if (fld[0] == '^') { buff.add('`');buff.append(fld.offset(1));buff.add('`'); buff.append(ConstStrA(" DESC")); } else { buff.add('`');buff.append(fld);buff.add('`'); buff.append(ConstStrA(" ASC")); } } return ConstStrA(buff); }
void HttpReqImpl::status(natural code, ConstStrA msg) { if (bHeaderSent) throw ErrorMessageException(THISLOCATION, "Headers already sent"); statusCode = code; if (msg.empty()) msg = getStatusMessage(statusCode); statusMsg = responseHdrPool.add(msg); }
SeqFileInput HttpClient::send(ConstStrA body) { if (request == null) { try { sendRequest(body.length(), psoAvoid100); request->writeAll(body.data(), body.length()); request->closeOutput(); loadResponse(); return SeqFileInput(response.get()); } catch (NetworkException &) { if (connectionReused) { closeConnection(); return send(body); } throw; } } else { return send(); } }
SourceIndex::WordID getLocaseWordId(ConstStrA word) { Crc32 crc32; TypeConvWriter<Crc32 &, char> crc32chr(crc32); WideToUtf8Writer<TypeConvWriter<Crc32 &, char> &> crc32wchr(crc32chr); Utf8ToWideReader<ConstStrA::Iterator> wideChars(word.getFwIter()); while (wideChars.hasItems()) crc32wchr.write(towupper(wideChars.getNext())); return crc32.getCrc32(); }
void HttpReqImpl::errorPage(natural code, ConstStrA msg, ConstStrA expl) { if (!bHeaderSent) { if (msg.empty()) msg = getStatusMessage(code); SeqFileOutput f(this); if (msg.empty()) msg = getStatusMessage(code); PrintTextA print(f); //clear some headers - they can damage output //delete content length - because we will show different page responseHdrs.erase(getHeaderFieldName(fldContentLength)); //delete transfer encoding - because we need simplest encoding responseHdrs.erase(getHeaderFieldName(fldTransferEncoding)); //delete content type - because we will set to text/html responseHdrs.erase(getHeaderFieldName(fldContentType)); //delete eTag - don't store eTag with an error page responseHdrs.erase(getHeaderFieldName(fldETag)); //delete lastModified - don't store error page responseHdrs.erase(getHeaderFieldName(fldLastModified)); status(code,msg); //set new content type header(fldContentType,"text/html"); if (code == 204 || code == 304) { //set ContentLength to zero even if it is not necesery, some clients can have issue header(fldContentLength,"0"); sendHeaders(); return; } else { closeConn = true; } print("<html><head><title>%1 %2</title></head><body><h1>%1 %2</h1>") << code << msg; if (!expl.empty()) print("<pre>%1</pre>")<< expl; print("<hr>"); print("<small><em>Powered by Bredy's JsonRpcServer - C++ http & jsonrpc server - <a href=\"https://github.com/ondra-novak/jsonrpcserver\">sources available</a></em></small>"); print("</body></html>"); } else { closeConn = true; } }
static ConstStrA getStatusMessage(natural status) { char buff[3]; if (status >= 100 && status <= 999) { buff[0] = status / 100 + '0'; buff[1] = (status / 10) % 10 + '0'; buff[2] = status % 10 + '0'; ConstStrA srchText(buff, 3); natural l = 0, h = countof(statusMessages); while (l < h) { natural m = (l + h) / 2; ConstStrA msg = statusMessages[m]; ConstStrA code = msg.head(3); if (code > srchText) h = m; else if (code < srchText) l = m + 1; else return msg.offset(4); } } return ConstStrA("Unknown status code"); }
static void loadSomeDataThread3(ConstStrA locId) { CouchDB db(getTestCouch()); db.use(DATABASENAME); for (natural i = 0; i < 3; i++) { Changeset chset = db.createChangeset(); Document doc; doc.edit(chset.json)("_id",locId)("aaa",100); chset.update(doc); chset.commit(db); locId = locId.offset(1); Thread::sleep(nil); } }
void HttpReqImpl::redirect(ConstStrA url, int code) { if (code == 0) { if (url.head(1) == ConstStrA('+')) code = 301; else code = 307; } TextParser<char> parser; if (parser("%[a-z]0://%",url)) { header(fldLocation, url); } else { StringA absurl = getAbsoluteUrl(url); header(fldLocation, absurl); } header(fldContentLength, "0"); status(code); sendHeaders(); }
void HttpClient::createRequest(ConstStrA url, Method method) { connectionReused = false; TextParser<char, SmallAlloc<1024> > parser; if (parser("http%(?)[s]1://%(*)*2%%[a-zA-Z0-9-_.:]3/%(*)4",url)) { ConstStrA s = parser[1].str(); ConstStrA auth = parser[2].str(); ConstStrA domain_port = parser[3].str(); ConstStrA path = parser[4].str(); path = url.tail(path.length()+1); if (!s.empty() && s != "s") throw InvalidUrlException(THISLOCATION,url,"unknown protocol"); if (!auth.empty() && s.tail(1)[0] != '@') throw InvalidUrlException(THISLOCATION,url,"auth need '@' as separator"); if (domain_port.tail(1)[0] == ':') throw InvalidUrlException(THISLOCATION,url,"missing port number"); bool tls = !s.empty(); IHttpProxyProvider::Result proxyInfo; if (proxyProvider) { proxyInfo = proxyProvider->getProxy(domain_port); } if (canReuseConnection(domain_port, tls)) { try { response->skipRemainBody(); connectionReused = true; } catch (const NetworkException &) { response = nil; nstream = nil; } } if (!connectionReused) { if (tls) { if (httpsProvider == 0) { throw InvalidUrlException(THISLOCATION,url,"Https is not configured"); } PNetworkStream stream; if (proxyInfo.defined) { stream = connectSite(proxyInfo.proxyAddr,8080); proxyConnect(stream, domain_port, proxyInfo.authorization); } else { stream = connectSite(domain_port, 443); } stream = httpsProvider->connectTLS(stream,domain_port); nstream = new BufferedNetworkStream(stream); currentDomain = domain_port; currentTls = true; } else { if (proxyInfo.defined) { PNetworkStream stream; stream = connectSite(proxyInfo.proxyAddr,8080); nstream = new BufferedNetworkStream(stream); path = url; currentDomain = proxyInfo.proxyAddr; } else { PNetworkStream stream; stream = connectSite(domain_port,80); nstream = new BufferedNetworkStream(stream); currentDomain = domain_port; } } } response = nil; request = new(pool) HttpRequest(nstream.get(),path,method,!useHTTP10); if (proxyInfo.defined && !tls && !proxyInfo.authorization.empty()) { request->setHeader(fldProxyAuthorization, proxyInfo.authorization); } request->setHeader(fldHost, domain_port); request->setHeader(fldUserAgent, userAgent); if (keepAlive == false) { request->setHeader(fldConnection,"close"); } else if (useHTTP10) { request->setHeader(fldConnection,"keep-alive"); } } else { throw InvalidUrlException(THISLOCATION,url,"Parser rejected"); } }
ITCPServerConnHandler::Command HttpReqImpl::finishReadHeader() { TextParser<char,StaticAlloc<256> > parser; //open output and input, we need stream to show error pages outputClosed = false; inputClosed = false; isHeadMethod = ConstStrA(method) == "HEAD"; closeConn = httpMinVer == 0; //check connection HeaderValue strconn = getHeaderField(fldConnection); if (strconn.defined) { if (strconn == "close") closeConn = true; } //check content length HeaderValue strsize = getHeaderField(fldContentLength); if (strsize.defined && parser(" %u1 ", strsize)) { remainPostData = parser[1]; } else { remainPostData = 0; } //check chunked POST HeaderValue strchunked = getHeaderField(fldTransferEncoding); if (strchunked.defined != 0 && strchunked == "chunked") { chunkedPost = true; remainPostData = 0; //remainPostData is used to count chunks } else { chunkedPost = false; } //check expectation for 100-continue HeaderValue strexpect = getHeaderField(fldExpect); if (strexpect.defined != 0) { if (strexpect == "100-continue" || strexpect == "100-Continue") { bNeedContinue = true; } else { return errorPageKA(417); } } else { bNeedContinue = false; } //check host ConstStrA vpath = path; host = getHeaderField(fldHost); if (!mapHost(host, vpath)) { return errorPageKA(404); } if (vpath.empty()) { redirect("+/"); return processHandlerResponse(0); } //find handler IHttpHandler *h; curHandler = nil; natural res = callHandler( vpath, &h); if (h == 0) return errorPageKA(404); if (curHandler == nil) curHandler = h; //need this to correctly handle forward function return processHandlerResponse(res); }
ITCPServerConnHandler::Command HttpReqImpl::readHeader() { try { AutoArray<char, SmallAlloc<8192> > linebuff; NStream::Buffer &buffer = inout->getBuffer(); natural fetched = buffer.fetch(); if (fetched == 0) { errorPage(413,ConstStrA(),"Header is too large"); return ITCPServerConnHandler::cmdRemove; } natural pos = buffer.lookup(ConstBin("\r\n"),fetched); while (pos != naturalNull) { linebuff.resize(pos+2); buffer.read(linebuff.data(),pos+2); ConstStrA line = linebuff.head(pos); if (method.empty()) { if (pos == 0) return ITCPServerConnHandler::cmdWaitRead; reqBeginTime = TimeStamp::now(); reportDuration = true; cropWhite(line); ConstStrA::SplitIterator splt = line.split(' '); method = hdrPool.add(ConstStrA(splt.getNext())); path = hdrPool.add(ConstStrA(splt.getNext())); while (path.empty()) path = hdrPool.add(ConstStrA(splt.getNext())); protocol = hdrPool.add(ConstStrA(splt.getNext())); while (protocol.empty()) protocol = hdrPool.add(ConstStrA(splt.getNext())); //parse some fields TextParser<char,StaticAlloc<256> > parser; //check http version if (parser("HTTP/%u1.%u2",protocol)) { httpMajVer = (unsigned short)((natural)parser[1]); httpMinVer = (unsigned short)((natural)parser[2]); if (httpMajVer != 1 || (httpMinVer != 0 && httpMinVer != 1)) return errorPageKA(505); useHTTP11(httpMinVer == 1); } else { return errorPageKA(400,StringA(ConstStrA("Unknown protocol: ")+ protocol)); } } else if (line.empty()) { return finishReadHeader(); } else { natural dblcolon = line.find(':'); if (dblcolon == naturalNull) { errorPage(400,ConstStrA(),"line"); return ITCPServerConnHandler::cmdRemove; } ConstStrA field = line.head(dblcolon); ConstStrA value = line.offset(dblcolon+1); cropWhite(field); cropWhite(value); requestHdrs.insert(hdrPool.add(field),hdrPool.add(value)); } pos = buffer.lookup(ConstBin("\r\n")); } return ITCPServerConnHandler::cmdWaitRead; } catch (AllocatorLimitException &) { errorPage(413,ConstStrA(),"Header is too large (4096 bytes)"); return ITCPServerConnHandler::cmdRemove; } }
void HttpReqImpl::sendHeaders() { if (bHeaderSent) return; if (bNeedContinue) { remainPostData = 0; chunkedPost = false; } bNeedContinue = false; bool hasServer = false; bool hasContentType = false; bool hasTransfEnc = false; bool hasConnection = false; bool hasLength = false; bool hasDate = false; static ConstStrA contentTypeKey = getHeaderFieldName(fldContentType); static ConstStrA serverKey = getHeaderFieldName(fldServer); static ConstStrA transfEnc = getHeaderFieldName(fldTransferEncoding); static ConstStrA connectionStr = getHeaderFieldName(fldConnection); static ConstStrA contenLenStr = getHeaderFieldName(fldContentLength); static ConstStrA dateStr = getHeaderFieldName(fldDate); ConstStrA statusMsgStr = this->statusMsg; if (statusMsgStr.empty()) statusMsgStr = getStatusMessage(statusCode); PrintTextA print(*inout); print.setNL("\r\n"); print("HTTP/%1.%2 %3 %4\n") << httpMajVer << httpMinVer << statusCode << statusMsgStr; if (statusCode == 101) { hasTransfEnc = hasConnection = hasContentType = true; useChunked = false; remainPostData = naturalNull; switchedProtocol = true; TimeStamp reqEndTime = TimeStamp::now(); natural reqTime = (reqEndTime - reqBeginTime).getMilis(); logRequest(reqTime); } for (HeaderMap::Iterator iter = responseHdrs.getFwIter(); iter.hasItems();) { const HeaderMap::Entity hdrPair = iter.getNext(); if (!hasContentType && hdrPair.key == contentTypeKey) hasContentType = true; if (!hasServer && hdrPair.key == serverKey) hasServer = true; if (!hasTransfEnc && hdrPair.key == transfEnc) hasTransfEnc = !(useChunked && hdrPair.value == ConstStrA("chunked")); if (!hasConnection && hdrPair.key == connectionStr) hasConnection = true; if (!hasDate && hdrPair.key == dateStr) hasDate = true; if (!hasLength && hdrPair.key == contenLenStr) { hasLength = true; } print("%1: %2\n") << ConstStrA(hdrPair.key) << ConstStrA(hdrPair.value); } if (!hasContentType) print("%1: %2\n") << contentTypeKey << "text/html;charset=UTF-8"; if (!hasServer) print("%1: %2\n") << serverKey << serverIdent; if (hasLength) { useChunked = false; } if (!hasDate) { TimeStamp::RFC1123Time datenow = TimeStamp::now().asRFC1123Time(); print("%1: %2\n") << dateStr << ConstStrA(datenow); } if (!hasTransfEnc && useChunked && !closeConn) print("%1: %2\n") << transfEnc << "chunked"; else useChunked = false; if (!hasConnection && closeConn) print("%1: %2\n") << connectionStr << "close"; print("\n"); /* LogObject(THISLOCATION).progress("%7 - %3 %4 HTTP/%1.%2 %5 %6") << httpMajVer << httpMajVer << ConstStrA(method) << ConstStrA(path) << statusCode << statusMsgStr << getIfc<IHttpPeerInfo>().getPeerRealAddr();*/ responseHdrs.clear(); //for code 100 or 101, additional header will be next if (statusCode == 100) { //set status code 200 to simply processing reply (handler don't need to reset 100 status statusCode = 200; //unset message this->statusMsg = HdrStr(); //now, handler can exit function with status 100 - when data arrives, onData will be called } else { //header sent, prevent sending new headers bHeaderSent = true; } }
WordID getWordId(ConstStrA word) { Crc32 crc32; crc32.blockWrite(reinterpret_cast<const byte *>(word.data()), word.length()); return crc32.getCrc32(); }