CWebSock::EPageReqResult CWebSock::OnPageRequestInternal(const CString& sURI, CString& sPageRet) { if (GetSession()->GetIP() != GetRemoteIP()) { PrintErrorPage(403, "Access denied", "This session does not belong to your IP."); return PAGE_DONE; } // Check that they really POSTed from one our forms by checking if they // know the "secret" CSRF check value. Don't do this for login since // CSRF against the login form makes no sense and the login form does a // cookies-enabled check which would break otherwise. if (IsPost() && GetParam("_CSRF_Check") != GetCSRFCheck() && sURI != "/login") { PrintErrorPage(403, "Access denied", "POST requests need to send " "a secret token to prevent cross-site request forgery attacks."); return PAGE_DONE; } SendCookie("SessionId", GetSession()->GetId()); if (GetSession()->IsLoggedIn()) { m_sUser = GetSession()->GetUser()->GetUserName(); m_bLoggedIn = true; } // Handle the static pages that don't require a login if (sURI == "/") { if(!m_bLoggedIn && GetParam("cookie_check", false).ToBool() && GetRequestCookie("SessionId").empty()) { GetSession()->AddError("Your browser does not have cookies enabled for this site!"); } return PrintTemplate("index", sPageRet); } else if (sURI == "/favicon.ico") { return PrintStaticFile("/pub/favicon.ico", sPageRet); } else if (sURI == "/robots.txt") { return PrintStaticFile("/pub/robots.txt", sPageRet); } else if (sURI == "/logout") { GetSession()->SetUser(NULL); SetLoggedIn(false); Redirect("/"); // We already sent a reply return PAGE_DONE; } else if (sURI == "/login") { if (GetParam("submitted").ToBool()) { m_sUser = GetParam("user"); m_sPass = GetParam("pass"); m_bLoggedIn = OnLogin(m_sUser, m_sPass); // AcceptedLogin()/RefusedLogin() will call Redirect() return PAGE_DEFERRED; } Redirect("/"); // the login form is here return PAGE_DONE; } else if (sURI.Left(5) == "/pub/") { return PrintStaticFile(sURI, sPageRet); } else if (sURI.Left(11) == "/skinfiles/") { CString sSkinName = sURI.substr(11); CString::size_type uPathStart = sSkinName.find("/"); if (uPathStart != CString::npos) { CString sFilePath = sSkinName.substr(uPathStart + 1); sSkinName.erase(uPathStart); m_Template.ClearPaths(); m_Template.AppendPath(GetSkinPath(sSkinName) + "pub"); if (PrintFile(m_Template.ExpandFile(sFilePath))) { return PAGE_DONE; } else { return PAGE_NOTFOUND; } } return PAGE_NOTFOUND; } else if (sURI.Left(6) == "/mods/" || sURI.Left(10) == "/modfiles/") { ParsePath(); // Make sure modules are treated as directories if (sURI.Right(1) != "/" && sURI.find(".") == CString::npos && sURI.TrimLeft_n("/mods/").TrimLeft_n("/").find("/") == CString::npos) { Redirect(sURI + "/"); return PAGE_DONE; } CModule *pModule = CZNC::Get().GetModules().FindModule(m_sModName); if (!pModule) { // Check if GetSession()->GetUser() is NULL and display // an error in that case if (!ForceLogin()) return PAGE_DONE; pModule = GetSession()->GetUser()->GetModules().FindModule(m_sModName); } if (!pModule) { return PAGE_NOTFOUND; } else if (pModule->WebRequiresLogin() && !ForceLogin()) { return PAGE_PRINT; } else if (pModule->WebRequiresAdmin() && !GetSession()->IsAdmin()) { PrintErrorPage(403, "Forbidden", "You need to be an admin to access this module"); return PAGE_DONE; } else if (!pModule->IsGlobal() && pModule->GetUser() != GetSession()->GetUser()) { PrintErrorPage(403, "Forbidden", "You must login as " + pModule->GetUser()->GetUserName() + " in order to view this page"); return PAGE_DONE; } else if (pModule->OnWebPreRequest(*this, m_sPage)) { return PAGE_DEFERRED; } VWebSubPages& vSubPages = pModule->GetSubPages(); for (unsigned int a = 0; a < vSubPages.size(); a++) { TWebSubPage& SubPage = vSubPages[a]; bool bActive = (m_sModName == pModule->GetModName() && m_sPage == SubPage->GetName()); if (bActive && SubPage->RequiresAdmin() && !GetSession()->IsAdmin()) { PrintErrorPage(403, "Forbidden", "You need to be an admin to access this page"); return PAGE_DONE; } } if (pModule && !pModule->IsGlobal() && (!IsLoggedIn() || pModule->GetUser() != GetSession()->GetUser())) { AddModLoop("UserModLoop", *pModule); } if (sURI.Left(10) == "/modfiles/") { m_Template.AppendPath(GetSkinPath(GetSkinName()) + "/mods/" + m_sModName + "/files/"); m_Template.AppendPath(pModule->GetModDataDir() + "/files/"); if (PrintFile(m_Template.ExpandFile(m_sPage.TrimLeft_n("/")))) { return PAGE_PRINT; } else { return PAGE_NOTFOUND; } } else { SetPaths(pModule, true); /* if a module returns false from OnWebRequest, it does not want the template to be printed, usually because it did a redirect. */ if (pModule->OnWebRequest(*this, m_sPage, m_Template)) { // If they already sent a reply, let's assume // they did what they wanted to do. if (SentHeader()) { return PAGE_DONE; } return PrintTemplate(m_sPage, sPageRet, pModule); } if (!SentHeader()) { PrintErrorPage(404, "Not Implemented", "The requested module does not acknowledge web requests"); } return PAGE_DONE; } } else { CString sPage(sURI.Trim_n("/")); if (sPage.length() < 32) { for (unsigned int a = 0; a < sPage.length(); a++) { unsigned char c = sPage[a]; if ((c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') { return PAGE_NOTFOUND; } } return PrintTemplate(sPage, sPageRet); } } return PAGE_NOTFOUND; }
TextFileWidget::TextFileWidget(Vector2n Position, std::string Path, TypingModule & TypingModule) : FlowLayoutWidget(Position, { std::shared_ptr<Widget>(new FlowLayoutWidget(Vector2n::ZERO, { std::shared_ptr<Widget>(m_FileMinimizeToggle = new ToggleWidget(Vector2n::ZERO, Vector2n(12, 12), [](bool State) { if (!State) g_InputManager->RequestTypingPointer(*static_cast<GestureRecognizer *>(nullptr)); }, true)), std::shared_ptr<Widget>(new LabelWidget(Vector2n(0, -lineHeight - 2), Path, LabelWidget::Background::Normal)) }, {})), std::shared_ptr<Widget>(m_TextFieldWidget = new TextFieldWidget(Vector2n::ZERO, TypingModule)) }, { std::shared_ptr<Behavior>(new DraggablePositionBehavior(*this)) }, FlowLayoutWidget::LayoutType::Vertical), m_Path(Path) { m_TextFieldWidget->SetContent(FromFileToString(Path)); m_OnChange = [=]() // Saving takes place in TextFileWidget when it gets its NotifyChange() from the contained TextFieldWidget { //PlayBeep(); //printf("Saving '%s'.\n", Path.c_str()); // Write to file WriteToFile(Path, m_TextFieldWidget->GetContent()); }; const std::string Folder = ParsePath(Path, 0); const std::string Filename = ParsePath(Path, 1); auto CopyPath = [this, &TypingModule]() { #if DECISION_USE_CLIPBOARD_INSTEAD_OF_TypingModule glfwSetClipboardString(this->m_Path); #else TypingModule.SetString(this->m_Path); #endif }; ModifyGestureRecognizer().AddShortcut(GestureRecognizer::ShortcutEntry('I', PointerState::Modifiers::Super, CopyPath, "Copy Path")); // TEST: Line Gutters #if 0 //if ("./Gen/5086673/gistfile1.go" == Path) m_TextFieldWidget->m_GetLineGutters = [=](uint32 LineNumber) -> std::string { #if 0 std::string x = "."; Ls(x); return std::to_string(LineNumber + 1); #endif // HACK: Pass file folder and name info if (0 == LineNumber) return Folder; else if (1 == LineNumber) return Filename; else throw 0; }; #endif if (IsFileTrackedByGit(Path)) { auto GitDiff = new GitDiffWidget(Vector2n::ZERO, TypingModule, this); GitDiff->RemoveAllBehaviors(); AddWidget(GitDiff); auto GitCommit = new ButtonWidget(Vector2n(-160, -350), [=, &TypingModule]() { auto Shell = std::unique_ptr<ShellWidget>(new ShellWidget(Vector2n::ZERO, TypingModule)); std::string Command = "cd \'" + Folder + "\'\ngit commit --allow-empty-message -m '' -- \'" + Filename + "\'"; Command += "\ngit push origin master"; Shell->m_CommandWidget->SetContent(Command); Shell->m_ExecuteWidget->GetAction()(); this->NotifyExternalChange(); // Do this to triger potential GitDiffWidget, GitStatusWidget, etc. //std::cerr << "Commit & Push: '" << Folder << "' folder and '" << Filename << "' file.\n"; std::cerr << Shell->m_OutputWidget->GetContent() << endl; }, "Commit & Push"); AddWidget(GitCommit); } m_TextFieldWidget->m_MinimizeToggle = m_FileMinimizeToggle; }