void TSAppSrvFun::GetFldValSet(const TStrKdV& FldNmValPrV, const TStr& FldNm, TStrSet& FldValSet) { FldValSet.Clr(); int ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, "")); while (ValN != -1) { FldValSet.AddKey(FldNmValPrV[ValN].Dat); ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, ""), ValN + 1); } }
bool TSAppSrvFun::IsFldNmVal(const TStrKdV& FldNmValPrV, const TStr& FldNm, const TStr& FldVal) { int ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, "")); while (ValN != -1) { if (FldNmValPrV[ValN].Dat == FldVal) { return true; } ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, ""), ValN + 1); } return false; }
// replay a particular http request void TReplaySrv::ReplayHttpRq(const PHttpRq& HttpRq) { PUrl HttpRqUrl = HttpRq->GetUrl(); // extract function name TStr FunNm = HttpRqUrl->GetPathSeg(0); // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // processed requested function if (!FunNm.Empty()) { // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, TUInt64::Mx, HttpRq, FunNmToFunH); // retrieve function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); // call function SrvFun->Exec(FldNmValPrV, RqEnv); } }
////////////////////////////////////// // URL-Redirect-Function TSASFunRedirect::TSASFunRedirect(const TStr& FunNm, const TStr& SettingFNm): TSAppSrvFun(FunNm, saotUndef) { printf("Loading redirects %s\n", FunNm.CStr()); TFIn FIn(SettingFNm); TStr LnStr, OrgFunNm; while (FIn.GetNextLn(LnStr)) { TStrV PartV; LnStr.SplitOnAllCh('\t', PartV, false); if (PartV.Empty()) { continue; } if (PartV[0].Empty()) { // parameters EAssert(PartV.Len() >= 3); TStr FldNm = PartV[1]; TStr FldVal = PartV[2]; if (FldVal.StartsWith("$")) { MapH.GetDat(OrgFunNm).FldNmMapH.AddDat(FldVal.Right(1), FldNm); } else { MapH.GetDat(OrgFunNm).FldNmValPrV.Add(TStrKd(FldNm, FldVal)); } } else { // new function EAssert(PartV.Len() >= 2); OrgFunNm = PartV[0]; MapH.AddDat(OrgFunNm).FunNm = PartV[1]; printf(" %s - %s\n", PartV[0].CStr(), PartV[1].CStr()); } } printf("Done\n"); }
// if one or more items with FldNm already exist remove them first // add to FldNmValPrV pair (FldNm, FldVal) void TSAppSrvFun::SetFldNmVal(TStrKdV& FldNmValPrV, const TStr& FldNm, const TStr& FldVal) { for (int N = FldNmValPrV.Len() - 1; N >= 0; N--) { if (FldNmValPrV[N].Key == FldNm) FldNmValPrV.Del(N); } FldNmValPrV.Add(TStrKd(FldNm, FldVal)); }
void TSASFunRedirect::Exec(const TStrKdV& FldNmValPrV, const PSAppSrvRqEnv& RqEnv) { PUrl Url = RqEnv->GetHttpRq()->GetUrl(); TStr FunNm = (Url->GetPathSegs() > 1) ? Url->GetPathSeg(1) : ""; EAssert(MapH.IsKey(FunNm)); const TRedirect& Redirect = MapH.GetDat(FunNm); TStrKdV _FldNmValPrV = Redirect.FldNmValPrV; for (int FldN = 0; FldN < FldNmValPrV.Len(); FldN++) { TStr OrgFldNm = FldNmValPrV[FldN].Key; if (Redirect.FldNmMapH.IsKey(OrgFldNm)) { _FldNmValPrV.Add(TStrKd(Redirect.FldNmMapH.GetDat(OrgFldNm), FldNmValPrV[FldN].Dat)); } } RqEnv->ExecFun(Redirect.FunNm, _FldNmValPrV); }
TStr TRegKey::GetVal(const PRegKey& Key, const TStr& SubKeyNm, const TStr& ValNm){ PRegKey RegKey=TRegKey::GetKey(Key, SubKeyNm); if (RegKey->IsOk()){ TStrKdV ValNmStrKdV; RegKey->GetValV(ValNmStrKdV); int ValN; if (ValNmStrKdV.IsIn(TStrKd(ValNm), ValN)){ return ValNmStrKdV[ValN].Dat; } else { return ""; } } else { return ""; } }
void THtmlLx::GetTag(){ if (Ch=='/'){Sym=hsyETag; GetCh();} else {Sym=hsyBTag;} UcChA.AddCh('<'); while (ChDef.IsAlNum(Ch)||(Ch==':')){ UcChA.AddCh(ChDef.GetUc(Ch)); GetCh();} UcChA.AddCh('>'); ChA=UcChA; if (DoParseArg){ while ((Ch!='>')&&(Ch!=TCh::EofCh)){ while ((!ChDef.IsAlpha(Ch))&&(Ch!='>')&&(Ch!=TCh::EofCh)){GetCh();} if (ChDef.IsAlpha(Ch)){ ArgNm.Clr(); ArgVal.Clr(); while (ChDef.IsAlNum(Ch)||(Ch=='-')){ArgNm.AddCh(ChDef.GetUc(Ch)); GetCh();} while (ChDef.IsWs(Ch)){GetCh();} if (Ch=='='){ GetCh(); while (ChDef.IsWs(Ch)){GetCh();} if (Ch=='"'){ GetCh(); while ((Ch!=TCh::EofCh)&&(Ch!='"')&&(Ch!='>')){ if (!ChDef.IsEoln(Ch)){ArgVal.AddCh(Ch);} GetCh();} if (Ch=='"'){GetCh();} } else if (Ch=='\''){ GetCh(); while ((Ch!=TCh::EofCh)&&(Ch!='\'')&&(Ch!='>')){ if (!ChDef.IsEoln(Ch)){ArgVal.AddCh(Ch);} GetCh();} if (Ch=='\''){GetCh();} } else { while ((!ChDef.IsWs(Ch))&&(Ch!='>')&&(Ch!=TCh::EofCh)){ ArgVal.AddCh(Ch); GetCh();} } ArgNmValV.Add(TStrKd(ArgNm, ArgVal)); } } } } else { while ((Ch!='>')&&(Ch!=TCh::EofCh)){GetCh();} } if (Ch!=TCh::EofCh){GetEscCh();} }
TStr TSAppSrvFun::GetFldVal(const TStrKdV& FldNmValPrV, const TStr& FldNm, const TStr& DefFldVal) { const int ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, "")); return (ValN == -1) ? DefFldVal : FldNmValPrV[ValN].Dat; }
////////////////////////////////////// // Simple-App-Server-Function bool TSAppSrvFun::IsFldNm(const TStrKdV& FldNmValPrV, const TStr& FldNm) { const int ValN = FldNmValPrV.SearchForw(TStrKd(FldNm, "")); return (ValN != -1); }
///////////////////////////////////////////////// // EuProjects-Web-Fetch void TCordisEuProjWebFetch::OnFetch(const int&, const PWebPg& WebPg){ // print url of downloaded page printf("%s\n", WebPg->GetUrlStr().CStr()); printf("-----------------------\n"); //printf("%s", WebPg->GetHttpHdStr().CStr()); //printf("%s", WebPg->GetHttpBodyAsStr().CStr()); // get current page url & set of outgoing urls with descriptions TStr WebPgUrlStr=WebPg->GetUrlStr(); TStrKdV DescUrlStrKdV; WebPg->GetOutDescUrlStrKdV(DescUrlStrKdV); // check current page type and react accordingly if (WebPgUrlStr.IsPrefix("http://dbs.cordis.lu/fep-cgi/srchidadb?ACTION=D&")){ // if the page represents project description (ACTION=D) // save the document TStr HtmlStr=WebPg->GetHttpBodyAsStr(); WebPgUrlStr.Save(*EuProjSOut); HtmlStr.Save(*EuProjSOut); EuProjSOut->Flush(); int DescUrlStrKdN=DescUrlStrKdV.SearchForw(TStrKd("NEXT RECORD")); if (DescUrlStrKdN!=-1){ // fetch next document FetchDocN++; FetchUrlStr= TStr("http://dbs.cordis.lu/fep-cgi/srchidadb?ACTION=D&SESSION=")+ FetchSesIdStr+"&DOC="+TInt::GetStr(FetchDocN); FetchRetries=0; FetchUrl(FetchUrlStr); } else { printf("*** No forward pointer.\n"); TSysMsg::Quit(); } // search for forward pointer (to the next project description) /*int DescUrlStrKdN=DescUrlStrKdV.SearchForw(TStrKd("NEXT RECORD")); if (DescUrlStrKdN!=-1){ // fetch next project description (usual, most frequent case) FetchUrlStr=DescUrlStrKdV[DescUrlStrKdN].Dat; FetchRetries=0; FetchUrl(FetchUrlStr); } else { // last project description doesn't include forward pointer printf("*** No forward pointer.\n"); TSysMsg::Quit(); }*/ } else if (WebPgUrlStr.IsPrefix("http://dbs.cordis.lu/fep-cgi/srchidadb?ACTION=R&")){ // if the page represents project record-set (ACTION=R) // take session id FetchSesIdStr=WebPgUrlStr.GetWcMatch("*SESSION=*&*", 1); FetchDocN=1; FetchUrlStr= TStr("http://dbs.cordis.lu/fep-cgi/srchidadb?ACTION=D&SESSION=")+ FetchSesIdStr+"&DOC="+TInt::GetStr(FetchDocN); FetchRetries=0; FetchUrl(FetchUrlStr); // move to the first project-description-url (first record-set only) /*int DescUrlStrKdN=0; while (DescUrlStrKdN<DescUrlStrKdV.Len()){ TStr UrlStr=DescUrlStrKdV[DescUrlStrKdN].Dat; DescUrlStrKdN++; if (UrlStr.IsPrefix("http://dbs.cordis.lu/fep-cgi/srchidadb?ACTION=D&")){ // fetch first project-description only FetchUrl(UrlStr); } } if (DescUrlStrKdN>=DescUrlStrKdV.Len()){ // quit downloading if no project descriptions printf("*** No project descriptions.\n"); TSysMsg::Quit(); }*/ // fetch next index page /*int DescUrlStrKdN=DescUrlStrKdV.SearchForw(TStrKd("NEXT 20 RECORDS")); if (DescUrlStrKdN!=-1){ FetchUrlStr=DescUrlStrKdV[DescUrlStrKdN].Dat; FetchRetries=0; FetchUrl(FetchUrlStr); } else { printf("*** No next 20 records.\n"); }*/ } else { // get forward pointer to the first project record-set (start only) int DescUrlStrKdN=DescUrlStrKdV.SearchForw(TStrKd("NEXT 20 RECORDS")); if (DescUrlStrKdN!=-1){ FetchUrl(DescUrlStrKdV[DescUrlStrKdN].Dat);} } }
void TSAppSrv::OnHttpRq(const uint64& SockId, const PHttpRq& HttpRq) { // last appropriate error code, start with bad request int ErrStatusCd = THttp::BadRqStatusCd; try { // check http-request correctness - return if error EAssertR(HttpRq->IsOk(), "Bad HTTP request!"); // check url correctness - return if error PUrl RqUrl = HttpRq->GetUrl(); EAssertR(RqUrl->IsOk(), "Bad request URL!"); // extract function name PUrl HttpRqUrl = HttpRq->GetUrl(); TStr FunNm = HttpRqUrl->GetPathSeg(0); // check if we have the function registered if (FunNm == "favicon.ico") { PHttpResp HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::ImageIcoFldVal, false, Favicon.GetSIn()); SendHttpResp(SockId, HttpResp); return; } else if (!FunNm.Empty() && !FunNmToFunH.IsKey(FunNm)) { ErrStatusCd = THttp::ErrNotFoundStatusCd; GetNotify()->OnStatusFmt("[AppSrv] Unknown function '%s'!", FunNm.CStr()); TExcept::Throw("Unknown function '" + FunNm + "'!"); } // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // report call if (ShowParamP) { GetNotify()->OnStatus(" " + HttpRq->GetUrl()->GetUrlStr()); } // request parsed well, from now on it's internal error ErrStatusCd = THttp::InternalErrStatusCd; // processed requested function if (!FunNm.Empty()) { // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, SockId, HttpRq, FunNmToFunH); // retrieve function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); // call function SrvFun->Exec(FldNmValPrV, RqEnv); } else { // internal SAppSrv call if (!ListFunP) { // we are not allowed to list functions ErrStatusCd = THttp::ErrNotFoundStatusCd; TExcept::Throw("Unknown page"); } // prepare a list of registered functions PXmlTok TopTok = TXmlTok::New("registered-functions"); int KeyId = FunNmToFunH.FFirstKeyId(); while (FunNmToFunH.FNextKeyId(KeyId)) { PXmlTok FunTok = TXmlTok::New("function"); FunTok->AddArg("name", FunNmToFunH.GetKey(KeyId)); TopTok->AddSubTok(FunTok); } TStr ResXmlStr; TXmlDoc::New(TopTok)->SaveStr(ResXmlStr); PSIn BodySIn = TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextXmlFldVal, false, BodySIn); // send response SendHttpResp(SockId, HttpResp); } } catch (PExcept Except) { // known internal error PXmlTok TopTok = TXmlTok::New("error"); TopTok->AddSubTok(TXmlTok::New("message", Except->GetMsgStr())); TopTok->AddSubTok(TXmlTok::New("location", Except->GetLocStr())); PXmlDoc ErrorXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr)); // send response SendHttpResp(SockId, HttpResp); } catch (...) { // unknown internal error PXmlDoc ErrorXmlDoc = TXmlDoc::New(TXmlTok::New("error")); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); // prepare response PHttpResp HttpResp = THttpResp::New(ErrStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(TSAppSrvFun::XmlHdStr + ResXmlStr)); // send response SendHttpResp(SockId, HttpResp); } }
void TSAppSrv::OnHttpRq(const int& SockId, const PHttpRq& HttpRq) { PHttpResp HttpResp; try { // check http-request correctness - return if error EAssertR(HttpRq->IsOk(), "Bad HTTP request!"); // check url correctness - return if error PUrl RqUrl = HttpRq->GetUrl(); EAssertR(RqUrl->IsOk(), "Bad request URL!"); // extract function name PUrl HttpRqUrl = HttpRq->GetUrl(); TStr FunNm = HttpRqUrl->GetPathSeg(0); EAssertR(FunNmToFunH.IsKey(FunNm) || FunNm.Empty(), "Unknown function '" + FunNm + "' !"); // extract parameters TStrKdV FldNmValPrV; PUrlEnv HttpRqUrlEnv = HttpRq->GetUrlEnv(); const int Keys = HttpRqUrlEnv->GetKeys(); for (int KeyN = 0; KeyN < Keys; KeyN++) { TStr KeyNm = HttpRqUrlEnv->GetKeyNm(KeyN); const int Vals = HttpRqUrlEnv->GetVals(KeyN); for (int ValN = 0; ValN < Vals; ValN++) { TStr Val = HttpRqUrlEnv->GetVal(KeyN, ValN); FldNmValPrV.Add(TStrKd(KeyNm, Val)); } } // log the call TStr TimeNow = TTm::GetCurLocTm().GetWebLogDateTimeStr(true); GetNotify()->OnStatus(TStr::Fmt("[%s] Request %s", TimeNow.CStr(), FunNm.CStr())); // prepare request environment PSAppSrvRqEnv RqEnv = TSAppSrvRqEnv::New(this, SockId, HttpRq); PSIn BodySIn; TStr ContTypeVal; if (!FunNm.Empty()) { // call function PSAppSrvFun SrvFun = FunNmToFunH.GetDat(FunNm); if (SrvFun->GetFunOutType() == saotXml) { PXmlDoc ResXmlDoc = SrvFun->Exec(FldNmValPrV, RqEnv); TStr ResXmlStr; ResXmlDoc->SaveStr(ResXmlStr); //ResXmlDoc->SaveTxt(TFile::GetUniqueFNm("test.xml")); BodySIn = TMIn::New(XmlHdStr + ResXmlStr); ContTypeVal = THttp::TextXmlFldVal; } else if (SrvFun->GetFunOutType() == saotJSon) { TStr ResStr = SrvFun->ExecJSon(FldNmValPrV, RqEnv); BodySIn = TMIn::New(ResStr); //ContTypeVal = THttp::TextHtmlFldVal; ContTypeVal = THttp::AppJSonFldVal; } else { BodySIn = SrvFun->ExecCustom(FldNmValPrV, RqEnv, ContTypeVal); } } else { PXmlTok TopTok = TXmlTok::New("registered-functions"); int KeyId = FunNmToFunH.FFirstKeyId(); while (FunNmToFunH.FNextKeyId(KeyId)) { PXmlTok FunTok = TXmlTok::New("function"); FunTok->AddArg("name", FunNmToFunH.GetKey(KeyId)); TopTok->AddSubTok(FunTok); } PXmlDoc ResXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ResXmlDoc->SaveStr(ResXmlStr); BodySIn = TMIn::New(XmlHdStr + ResXmlStr); ContTypeVal = THttp::TextXmlFldVal; } // prepare response HttpResp = THttpResp::New(THttp::OkStatusCd, ContTypeVal, false, BodySIn); // send response } catch (PExcept Except) { PXmlTok TopTok = TXmlTok::New("error"); TopTok->AddSubTok(TXmlTok::New("message", Except->GetMsgStr())); TopTok->AddSubTok(TXmlTok::New("location", Except->GetLocStr())); PXmlDoc ErrorXmlDoc = TXmlDoc::New(TopTok); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(XmlHdStr + ResXmlStr)); } catch (...) { PXmlDoc ErrorXmlDoc = TXmlDoc::New(TXmlTok::New("error")); TStr ResXmlStr; ErrorXmlDoc->SaveStr(ResXmlStr); HttpResp = THttpResp::New(THttp::OkStatusCd, THttp::TextHtmlFldVal, false, TMIn::New(XmlHdStr + ResXmlStr)); } SendHttpResp(SockId, HttpResp); }