Perl Catalyst - Page not found when using href to link to page on the same site - html

I am creating a Catalyst application, currently I have a simple login page that also contains a 'Forgotten Password' link. It is all working perfectly, except when I click the 'Forgotten Password' link it should take me to a brand new html page that simply contains the words "Unlucky, you should have remembered it". Instead I get a 'Page not found' error.
What I am doing:
I have a Controller called Login.pm containing the following:
sub default : Private {
my ( $self, $c ) = #_;
$c->forward('login');
}
sub login : Path('/login') {
my ( $self, $c ) = #_;
$c->stash->{title} = "Login page";
$c->stash->{page} = "html";
$c->stash->{template} = "login.html";
}
All of the above works correctly and produces the login page.
In the Catalyst root/login.html file (along with all the other bits like buttons) I have the following piece of code that should allow me to link to the 'Forgotten Password' html page.
<p>Forgot Password?</p>
The root/forgotpassword.html file it is referencing contains the following:
<!DOCTYPE html>
<html>
<body>
<h1>Unlucky, you should have remembered it</h1>
</body>
</html>
However, when I click the 'Forgotten Password' link on the login page it goes to 'mydomainname/forgotpassword.html' and says 'Page not found'.
Do I need to create a Controller for the forgotpassword page? and if so what would it need to contain? Or is there something obvious I am overlooking?
I am new to Catalyst.

Finally worked out the issue, thanks to 'mikew' for referring me to the 'Serving static content' section of the cookbook on CPAN.
What the problem was:
Using the html5 code below I was referencing a simple html page that required no interaction with Catalyst to work.
<p>Forgot Password?</p>
However, as mentioned in the Cookbook and Catalyst::Plugin::Static::Simple
"By default, the following extensions are not served (that is, they will be processed by Catalyst): tmpl, tt, tt2, html, xhtml."
and
"There are some file types you may not wish to serve as static files. Most important in this category are your raw template files. By default, files with the extensions tmpl, tt, tt2, html, and xhtml will be ignored by Static::Simple in the interest of security."
To prevent the 'Page not found' error (as the html page is ignored by default) you need to do add the following to the MyApp.pm file ensuring that you remove the extension/s you do not want to be ignored (in my case html files).
MyApp->config(
static => {
ignore_extensions => [
qw/tmpl tt tt2 xhtml/
],
},
);

I believe what you want to do is make sure that file is served up statically. Look at the cookbook for making sure you are configured to serve up static files instead of sending that request through catalyst.

Related

Add CodeMirror to a MediaWiki page

I know how to implement CodeMirror to a regular page but I have no idea how to do it on a MediaWiki webpage. I've tried adding the "codemirror.js" file the same way I added other scripts that I am using on the page but I get the error that "CodeMirror" is not defined when it is being initialized. In the code below shows how I added my previous scripts and the "codemirror.js".
$wgResourceModules['ext.SpecialRobotExp'] = array('scripts' => array(
'module/PID.js', 'module/grid.js', 'module/saveFile.js', 'module/codemirror.js'
),
What I need is to know where to save the codemirror.js file and how to load it to the page on a MediaWiki webpage.

Send head before the controller completes rendering

How can one send <head> contents before the controller finishes? The idea is to start loading CSS as soon as possible (don't wait for controller action).
Sample scenario:
// in the controller
sleep(5);
This gives:
blank page for 5 seconds -> display the head -> start loading CSS -> body
The flow I want to get is:
Send head -> start loading CSS -> wait for the controller -> send rest of the page (body)
The <head> is now in layout.phtml, which later includes the index controller script (index.phtml).
Maybe I could have <head> as a partial and send it somehow before the whole layout?
One approach is to create an abstract controller that all controllers extend, and in the onDispatch function render the head template and flush:
public function onDispatch(MvcEvent $e) {
$renderer = $this->getServiceLocator()->get('ViewRenderer');
$content = new ViewModel();
$content->setTemplate('path/to/head.phtml');
$content = $renderer->render($content);
echo $content;
flush();
parent::onDispatch($e);
}
Drawbacks to this approach:
You have no access to the headTitle, headMeta, headLink, headScript and other view helpers elsewhere in your application (it is possible in a controller or viewscript to add a style sheet and js plugin for just that page).
You will be unable to perform redirects as a response has already been sent
You can't gzip the content as well as flushing it
Some versions of Microsoft Internet Explorer will only start to display the page after they have received 256 bytes of output, so you may need to send extra whitespace before flushing to get those browsers to display the page.
In theory, you could use this approach to load all static content in the layout before echoing $this->content - such as logo, navigation, search bar, etc etc.
As I've stated, this breaks redirects meaning helpers and plugins such a PostRedirectGet will not work.

Trouble rendering MathJax with Jekyll on github pages [duplicate]

I built a random sentence generator -- when you click an HTML button, a random sentence is generated beneath it. The generation is powered by a simple script and jQuery.
It works fine on my local machine: When I open index.html in a browser, everything goes smoothly.
But once I upload to GiHub and visit the GitHub pages URL, the generator stops working. Clicking the button does nothing.
Here's the script (it's all contained within the index.html file):
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
and
<script> function sentenceLoad() {
//declare arrays
var nouns = ['Mulder, Scully, and'];
var names = ['Assistant Director Skinner', 'the Cigarette Smoking Man', 'Alex Krycek'];
var actions = ['are running from alien bounty hunters', 'are tracking a shapeshifter', 'are hunting a mutant serial killer'];
var places = ['in the woods of New Jersey', 'in a government bunker', 'in Olympic National Forest'];
//shuffle through contents of each array, picking one entry per array
var randNoun = nouns[Math.floor(Math.random() * nouns.length)];
var randName = names[Math.floor(Math.random() * names.length)];
var randAction = actions[Math.floor(Math.random() * actions.length)];
var randPlace = places[Math.floor(Math.random() * places.length)];
//place the random entry into the appropriate place in the HTML
jQuery("h5").html("");
jQuery("h5").append(randNoun + " ");
jQuery("h5").append(randName + " ");
jQuery("h5").append(randAction + " ");
jQuery("h5").append(randPlace);
}
What would cause this to work locally, but not work on Github Pages?
If you open up your Developer Tools pane (in Chrome, right-click on the page and choose Inspect), you'll see this error in the Network console:
Mixed Content: The page at 'https://bobbyfestgenerator.github.io/' was loaded over HTTPS, but requested an insecure script 'http://code.jquery.com/jquery-1.10.1.min.js'. This request has been blocked; the content must be served over HTTPS.
You need to load your script over HTTPS instead of HTTP.
The reason this works locally is because you're using the file:// scheme on your local machine (or http:// if you have a local development server). The browser doesn't have a problem loading an external script over HTTP in this case.
However, Github Pages is hosting your file over HTTPS (a secure connection) for you. For security reasons, the browser won't load a script over HTTP if the page is hosted on HTTPS.
Just change the code in your <head> tag to load the script over HTTPS:
<script src="https://code.jquery.com/jquery-1.10.1.min.js"></script>
Today I saw a similar problem, but not because of HTTP/HTTPS: when I published to GitHub pages, all of the CR/LF characters were removed in the source HTML. Perhaps not a big deal for HTML with closing tags, but when the entire source page is on one line, including JavaScript, well - any embedded comments in JavaScript caused all code afterwards (until the JavaScript closing tag) to be unexpectedly also commented out.
In this case some more code is treated like a comment:
code...
// a comment
some more code...
Here's an example. Before, as viewed in editor:
After push to GitHub, CR/LF apparently removed by GH-Pages actions:
Note how all the remaining JavaScript ends up disabled after the comment::
The (somewhat undesired) solution would be to remove the comment or better: use /* and */ comment wrappers instead of // at the beginning of the line.
edit: the root cause seems to be the layout: compress; see https://github.com/jekyll/jekyll/issues/8660

Hiding download links in HTML

I am offering a pdf document in the form of a download from my website via a landing page.
I want to hide the URL/link that displays in the address bar and when i hover over the download button on the web page so that the link cant be shared.
What is the best way to do this? Please explain carefully.
Thanks
Ok, you cannot do that with plain HTML. You can use all kind of tricks but they can be a problem to the user experience, you are to use a server side language.
What you can do is create a php page, name it the way you want (let's say download.php), and link to that one. The page should be something like this:
// Path to the file
$path = '/home/folder/yourfile.pdf';
// This is based on file type of $path, but not always needed
$mm_type = "application/octet-stream";
//Set headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");
// Outputs the content of the file
readfile($path);
exit();
This way you just link to your download.php page and it downloads/opens the PDF, like so:
Download
Edited based on BenjaminC suggestions
The other chance you have is to connect this to a database. The database has a table named downloads_table and inside you have 2 fields:
secret: char(32)
downloaded: int(1) dafault 0
Then you create an md5 string
$secret = md5(rand(1000, 9999999));
Place it inside the secret field, create the link:
Download
The user receives/sees a link, when pressed you are to edit the first line of the above code to check in the db if downloaded field = to 0 than procede to download, otherwise the person sees an error page.
This is so that it can be downloaded only once.
(Edit)
If in the future, this gets useful for anyone, the functionality can be seen in this fiddle: https://jsfiddle.net/aznjr87g/
It downloads 2.1.3 jquery.min.js from google.
(Edit end)
This can be achieved using Html5 's Download attribute.
Download PDF
If you hover your mouse over that, it simply shows yoursite.com/#
Place this somewhere in the body of the webpage:
And place this somewhere in the webpage:
<script>
function download() {
document.getElementById("download").src = "/path/to/download";
}
<script>
Then, on the element of the button (In the example of a div) do this in the tag:
<div onclick="download()"> </div>
However if it's a link you will want to do:
An element needs a href to work properly.

Assigning tags for uploaded HTML files in Concrete5

We are planning to load a number of HTML files as they are in the site using Concrete5.
We had to do this since the number of files is too big to load them via editor.
(We are going to generate the html files with madcap flare)
However, I need to use the tag feature of concrete5 for the contents loaded by this method.
I am told by my developers that this is impossible.
Does anyone know how to use tags for files loaded without going through the C5 editor?
i.e. I want the contents in the manually linked html files to be searched and filtered within the site with the search feature and filter feature provided by C5
HELP!!
I recommend creating a very simple template consisting of the standard C5 header/footer code, with one big block as the contents of the body tag.
You can then import the pages by something along the lines of (pseudo-code):
$parent = Page::getByCollectionPath('/');
$ct = CollectionType::getByHandle('template_name');
$data = array(
'cName' => 'The page title',
'cHandle' => 'The trailing path component'
);
$page = $parent->add($ct, $data);
$blocks = $page->getBlocks('Main');
// Gross hack because the template has one block, and that a 'content' block
$blocks[0]->update('content', 'IMPORTED HTML BODY CONTENT');
After that, you can add tags either via the API or the Dashboard.