How to send html ready to display from perl script? - javascript

#!/usr/bin/perl
# perl cgi script products2.cgi
use DBI;
print <<END_HTML;
Content-type: text/html
END_HTML
my $host = "xxx.xxx.xxx";
my $port = "xxxx";
my $database = "proj4";
my $username = "xxxxxx";
my $password = "xxxxx";
my $database_source = "dbi:mysql:$database:$host:$port";
my $dbh = DBI->connect($database_source, $username, $password)
or die 'Cannot connect to db';
my $sth = $dbh->prepare("SELECT distinct category FROM products");
$sth->execute();
#getting the categories and displaying them
while(my #row=$sth->fetchrow_array()) {
my $data =$row[0];
my #values = split(' ',$data);
my $pic = "/~xxxx/proj4/images/".$values[0].".jpg";
print <<END_HTML;
<div class="view view-first">
END_HTML
print"<img src=\"$pic\" alt=\"$row[0]\"/>";
print "<h2 class=\"choc\"><span>$row[0]</span></h2>";
print "<div class=\"mask\">";
print "<h2 class=\"eff\">\"$row[0]\"</h2>";
print <<END_HTML;
<p>One of Our best sellers</p>
Discover
</div>
</div>
END_HTML
}
$sth->finish();
$dbh->disconnect();
I am trying to replace the contents of
<div id="content"></div>
in my proj.html to the output of the above perl script when clicked on "products" link in the navigation bar.
//navigation bar for product
<li>
<a href="/perl/xxxxx/products2.cgi" id="productit">
Products
</a>
</li>
I know I have to use javascript and ajax, but not sure how to do it.
$('#productit').bind('click', function() {
var handle = document.getElementById('content');
var req = new HttpRequest('/perl/xxxxx/products2.cgi', callback);
//i know this ajax call only expects string to be returned from server
req.send();
handle.innerHTML= //not sure how to populate this
});
Could someone please guide me as to how to send html ready to display from the perl script

All you have to do is print the HTML and it gets sent to the client/browser.
However...
I notice one minor detail in your Perl code which would cause the web server to throw a 500 Internal Server Error: You forgot to print a blank line after your HTTP headers. The code posted would send the output
Content-type: text/html
<div class="view view-first">
...
which is not a valid HTTP response because <div is not a recognized HTTP header. It needs to send
Content-type: text/html
<div class="view view-first">
...
instead, with a blank line to indicate the end of headers before the content starts.
This is one of the reasons why it's generally a good idea to use a web framework (such as Dancer, Mojolicious, or Catalyst) or even the arcane CGI.pm instead of handling these things manually: there are so many minor details and strange edge cases that you need to get just right or else it will fail to work for no apparent reason. If this is a learning exercise, rolling your own is fine and it's good to learn where all those pitfalls are, but you're better off using a widely-used and well-tested module to deal with them in code whose purpose is to do something useful or important.

You can use the $.ajax() method since you are using jquery
$('#productit').bind('click', function(e) {
var handle = document.getElementById('content');
e.preventDefault();
$.ajax({
dataType : 'text', /* the datatype you are returning */
url: '/perl/xxxxx/products2.cgi',
success:function (data){ /* data is the data returned from the ajax call */
handle.innerHTML = data;
}
});
});

Related

Storing information from php script

I m working on an html page that contains a form allowing users to enter their informations and upload files. all informations will be inserted in Mysql database.
in Javascript, im using XMLHttpRequest to send the files to the server and "upload.php" to rename (to avoid dupplicated names) and move them in the upload directory.
For better user experience, this will be done before submitting the whole form.
My question is : How can i store the new filenames (defined in upload.php)to use them in the form submission "submit.php"?
the reason for this is that in "submit.php", i insert first the user informations in "user" table and then select the "user_id" (auto increment) that will be inserted with filenames in the "files" table.
Could php sessions be an approach to do this ? is there another way? Thanks for your help
html:
<form action="submit.php" method="post" id="submitform">
<div>
<--!user info part1-->
</div>
<div id="filesContainer" class="eltContainer">
<input type="file" id="filesList" multiple>
</div>
<div>
<--!user info part2-->
</div>
javascript:
var fd = new FormData()
var xhr = new XMLHttpRequest()
for (var i=0,nb = fichiers.length; i<nb; i++) {
var fichier = fichiers[i]
fd.append(fichier.name,fichier)
}
xhr.open('POST', 'upload.php', true)
upload.php :
<?php
foreach($_FILES as $file){
$filename = date('Y') . date('m') . date('d') . date('H') . date('i') . basename($_FILES[$file]['name']);
move_uploaded_file( $file['tmp_name'],"../upload_dir/" .$filename);
}
exit;
I would consider using something like md5 for unique filenames.
Nevertheless you can push filenames into some array, and than return those filenames, as a result of post request, and put them back into some input field.
To retrieve the response simply add this lines to your code below open
xhr.onreadystatechange = function {
// If the request completed and status is OK
if (req.readyState == 4 && req.status == 200) {
// keep in mind that fileNames here are JSON string
// as you should call json_encode($arrayOfFilenames)
// in your php script (upload.php)
var fileNames = xhr.responseText;
}
}
If you'd like consider using a simple library for AJAX requests, like axios. It's promise based HTTP client for the browser, really simple to use and saves you some time and effort cause you don't have to memorize all this stuff you and I have just written.
This is one approach, but I think you can use $_SESSION as well, and it's perfectly valid. My guess is you don't have logged in user at this point, so my idea is as follows:
put filenames into the $_SESSION
use db transactions - as #Marc B suggested - to connect files with
user
if there were no errors just remove filenames from $_SESSION, if there was some, just redirect the user back to the form (possibly with some info what went wrong), and this way he doesn't have to reupload files, cause you have filenames still in $_SESSION

POST Slim Route not working

I'm using Slim for development. All my GET routes are working just fine, but whenever I use POST, I get "unexpected result". Please have a look at how I've implemented slim and that "unexpected error".
index-routes.php (index root file)
<?php
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim(array(
'debug' => true
));
require_once 'site-index.php';
require_once 'routes/default-routes.php';
$app->contentType('application/json');
$app->run();
?>
routes/default-routes.php
<?php
$app->post('/login',function(){
echo 'AllHailSuccess!';
})
?>
origin of POST request called via AJAX
function try1()
{
var value1 = "afsfesa";
API.call('/login','text','POST',function(data){console.log(data)},{var1:value1});
}
AJAX Call API
var API = {
call:function(url,returnType,reqType,callback,data){
var data = (!!data) ? data : {};
var callback = (!!callback) ? callback : function(){};
$.ajax({
dataType: returnType,
type:reqType,
crossDomain: true,
xhrFields: { withCredentials: true },
url: url,
data:data,
success:callback,
error:function(data){
console.log("Error!");
console.log(data);
}
});
}
}
"Unexpected error": When I execute try1(), THE POST ROUTE DOES GETS EXECUTED SUCCESSFULLY but the contents (The entire code in plain-text) of site-index.php (Which I called in root index-routes.php file) also gets logged along with it. The reason why I imported site-index.php in the first place, is because it acts like a "main stage" for my site. It's the only page I want to load and user navigates within it.
I want to know:
Why I'm getting this type of output?
Is my approach alright? I think importing my main-stage file from index- routes is causing this. Is there any other way of doing this?
Any help is appreciated. Thank you.
Your Slim calls are going to return anything that is displayed on the page.
There are a few ways to work around this:
Nest all of your page renders inside the route and don't render full pages for AJAX routes.
Modify your AJAX calls to search the returned DOM to find the relevant information.
In your example shown, AllHailSuccess! will be displayed after all of the content in site-index.php
Many people use templating software to render their pages and then use a service to render their page via the template. For more basic sites, I would recommend you create a simple service to display content.
Here's a simple example of a Viewer class I use in my project(s)
class Viewer {
/**
* Display the specified filename using the main template
* #param string $filepath The full path of the file to display
*/
public function display($filepath) {
//set a default value for $body so the template doesn't get angry when $body is not assigned.
$body = "";
if (file_exists($filepath)) {
$body = get_include_contents($filepath);
} else {
//You want to also return a HTTP Status Code 404 here.
$body = get_include_contents('404.html');
}
//render the page in the layout
include('layout.php');
}
}
/**
* Gets the contents of a file and 'pre-renders' it.
* Basically, this is an include() that saves the output to variable instead of displaying it.
*/
function get_include_contents($filepath, $params = array()) {
if (is_file($filepath)) {
ob_start();
include $filepath;
$ret = ob_get_contents();
ob_end_clean();
return $ret;
}
return false;
}
Your routes that you want to display the page layout to the user should look something like this now:
$app->get('/', function() {
(new Viewer())->display('home.html');
});
This is by no means a comprehensive solution because it does not address proper HTTP status codes and files are referenced directly in your code which can get messy, but it's a good starting point and its quick to mock something like this up.
If you want to continue in this direction, I would recommend you take a look at the Slim v2 Response Documentation and create a class that constructs and returns Response objects. This would give you much more flexibility and power to set HTTP status codes and HTTP Return headers.
I highly recommend checking out Slim v3 Responses as well because Slim 3 uses PSR-7 Response objects which are standard across multiple frameworks.

Download javascript output using file_get_content

Is it possible to download the resulting HTML code after the JavaScript code on the page has been run using PHP.
For example, when the page has this jQuery code $("p").html("Hello world"); and I use file_get_content('website.com') I don't get the string "Hello world" because the JavaScript runs after the page load.
use cURL:
function get_data($url)
{
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
Then do :
<?php echo get_data('http://theURLhere.com'); ?>
Hope that helped
Please refer to similar questions and share your research you have done so far:
Get the content (text) of an URL after Javascript has run with PHP
Get Document source After AJAX or js Action With PHP
How to get content of a javascript/ajax -loaded div on a site?
Get HTML code after javascript execution using CURL PHP
One way to achieve this would be to use Selenium, and write a custom script to gather the output from it... But I'm sure that falls far beyond the scope of what you're attempting to do.
The way I would go would be to invert the responsibility. Have the JS send the output to a PHP endpoint, and use that output however you see fit.
Here's an example.
Javascript
<script>
var outputElement = 'html';
var HTML = $(outputElement).html();
var endpoint = 'myEndpoint.php';
$.post(endpoint, { html: HTML }, function(data) {
alert('Output sent');
});
</script>
One caveat here is that you will not get the DOCTYPE declaration, or any attributes on your HTML tag, if this isn't acceptable, you may reconstruct them in the PHP file below.
PHP
<?php
$html = $_POST['html']; // Be VERY CAREFUL with what you do with this...
// If you need to have the doctype and html tag... Use your own doctype.
// $html = sprintf('<DOCTYPE html><html class="my-class">%s</html>', $html);
// Do something with the HTML.
You have to be very careful when sending HTML over POST. If you're using this HTML to output on your website, it can easily be spoofed to reveal sensitive data on your website.
Reference
jQuery.post()

Yii: best practices to pass data from php to JS

My question is, what are the best practices of passing the data from my server side to my client side?
For example, I have a cartId on my server side which I need to pass on to the client side.
How do I best do that? Right now it's done via the main layout:
<script type='text/javascript'>
(function() {
if (window.cart) {
cart.id = <?php echo Yii::app()->getUser()->getCartId() ?>;
}
})();
</script>
However, that seems like a bad thing to do. Will appreciate any feedback.
In php file write this YII code
YII Code
Yii::app()->clientScript->registerScript("cartid",Yii::app()->getUser()->getCartId());
SCRIPT
(function() {
if (window.cart) {
cart.id = cartid;
}
})();
Use AJAX to get the data you need from the server.
Echo the data into the page somewhere, and use JavaScript to get the
information from the DOM.
Echo the data directly to JavaScript.
With AJAX, you need two pages, one is where PHP generates the output, and the second is where JavaScript gets that output:
get-data.php
/* Do some operation here, like talk to the database, the file-session
* The world beyond, limbo, the city of shimmers, and Canada.
*
* AJAX generally uses strings, but you can output JSON, HTML and XML as well.
* It all depends on the Content-type header that you send with your AJAX
* request. */
echo json_encode(42); //In the end, you need to echo the result.
//All data should be json_encoded.
index.php (or whatever the actual page is named like)
<script>
function reqListener () {
console.log(this.responseText);
}
var oReq = new XMLHttpRequest(); //New request object
oReq.onload = function() {
//This is where you handle what to do with the response.
//The actual data is found on this.responseText
alert(this.responseText); //Will alert: 42
};
oReq.open("get", "get-data.php", true);
// ^ Don't block the rest of the execution.
// Don't wait until the request finishes to
// continue.
oReq.send();
</script>
The above combination of the two files will alert 42 when the file finishes loading.
It's best practice to not write PHP in your JavaScript for one. Instead, take the data from PHP and pass it to json_encode (http://php.net/json_encode) and echo it out. You can read that straight into a variable if you like but it would be better to use ajax so it's asynchronous thus better page load.
The best option is to make AJAX calls to a PHP page which performs some action, and returns data. Once that PHP has all the data it needs to return, I echo the data (as an array) in JSON format.
Eg:
info.php
die (
json_encode(
array(
"id" => "27"
"name" => "rogin",
)
)
);
Then, you can use javascript to fetch the data into a json object.
JS
$.getJSON(
'info.php?',
function(jsonObject) {
alert(jsonObject.name);
});
If you just want to prevent javascript syntax highlighting error, quoting would do just fine.
(function() {
var the_id = +'<?php echo Yii::app()->getUser()->getCartId() ?>';
// ^ + to convert back to integer
if (window.cart) {
cart.id = the_id;
}
})();
Or if you like you could add it to an element:
<div id='foo' style='display:none'><?php echo Yii::app()->getUser()->getCartId() ?></div>
Then parse it later
<script>
(function() {
var the_id = +($('#foo').html()); // or parseInt
// or JSON.parse if its a JSON
if (window.cart) {
cart.id = the_id;
}
})();
</script>

Connecting to a server-side SQL database via php with jquery

I have been trying to look over an example to figure out how to connect to a server's SQL database from a client using JQuery, AJAX, and PHP, and though it is old it seems well done and straight forward: Example Link.A single folder contains all of my php files as well as the product version of jQuery (javascript-1.10.2.min.js).
Problem 3 - Fixed
JS console shows [Object, "parsererror", SyntaxError] at
var id = data.data[0]; //get id, data['data'][0] works here as well
in client.php. Object responseText shows ..."No Database Selected"... I have updated my client.php based on Daedalus' response and am still getting the same error.
Error was in mislabeling a variable ($link instead of $con) in server-api.php
-- Code --
db-connect.php:
<?php
//--------------------------------------------------------------------------
// Example php script for fetching data from mysql database
//--------------------------------------------------------------------------
$host = "localhost";
$user = "root";
$pass = "password";
$databaseName = "server-db";
$tableName = "inventory";
?>
server-api.php:
<?php
//--------------------------------------------------------------------------
// 1) Connect to mysql database
//--------------------------------------------------------------------------
include 'db-connect-99k.php';
$con = mysql_connect($host,$user,$pass);
$db_selected = mysql_select_db('zgc7009_99k_db', $con);
$array = array('mysql' => array('errno' => mysql_errno($con), 'errtxt' =>mysql_error($con)));
//--------------------------------------------------------------------------
// 2) Query database for data
//--------------------------------------------------------------------------
$result = mysql_query("SELECT * FROM $tableName"); //query
$array['mysql'][] = array('errno' => mysql_errno($con), 'errtxt' =>mysql_error($con));
$array['data'] = mysql_fetch_row($result); //fetch result
//--------------------------------------------------------------------------
// 3) echo result as json
//--------------------------------------------------------------------------
echo json_encode($array);
?>
client.php
<html>
<head>
<script language="javascript" type="text/javascript" src="jquery-1.10.2.min.js"></script>
</head>
<body>
<!-------------------------------------------------------------------------
1) Create some html content that can be accessed by jquery
-------------------------------------------------------------------------->
<h2> Client example </h2>
<h3>Output: </h3>
<div id="output">this element will be accessed by jquery and this text replaced</div>
<script id="source" language="javascript" type="text/javascript">
$(function ()
{
//-----------------------------------------------------------------------
// 2) Send a http request with AJAX http://api.jquery.com/jQuery.ajax/
//-----------------------------------------------------------------------
$.ajax({
url: 'server-api.php', //the script to call to get data
data: "", //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
//dataType: 'json', //data format (comment out or get parsererror)
// Successful network connection
// Successful network connection
success: function(data) //on recieve of reply
{
var id = data.data[0]; //get id, data['data'][0] works here as well
var vname = data.data[1]; //get name
//--------------------------------------------------------------------
// 3) Update html content
//--------------------------------------------------------------------
$('#output').html("<b>id: </b>"+id+"<b> name: </b>"+vname); //Set output element html
$('#error_code').html("Success!");
},
error: function() {
console.log(arguments);
}
});
});
</script>
</body>
</html>
Problem 1 - Fixed
Thanks to user help, I have managed to get rid of my original error of:
OPTIONS file:///C:/Users/zgc7009/Desktop/Code/Web/php/server-api.php No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. jquery.js:8706
XMLHttpRequest cannot load file:///C:/Users/zgc7009/Desktop/Code/Web/php/server-api.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
Problem 2 - Fixed [now running on temporary web server (see link at bottom)]
Now I am running WAMP (including phpmyadmin and apache) as my webserver. I can run my php page with script (client.php) no problem, it runs, can't seem to find any errors in my logs. However, I still never seem to hit the success function of my script. I am assuming that I have inappropriately set something somewhere (eg localhost/"my site".php) but I am not sure where.
I also tried changing my AJAX function a bit, to include .done:
$.ajax({
url: 'localhost/server-api.php', //the script to call to get data
data: "", //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
// Successful network connection
success: function(data) //on recieve of reply
{
var id = data[0]; //get id
var vname = data[1]; //get name
//--------------------------------------------------------------------
// 3) Update html content
//--------------------------------------------------------------------
$('#output').html("<b>id: </b>"+id+"<b> name: </b>"+vname); //Set output element html
}
}).done(function() {
$('#output').html("AJAX complete");
});
but my output value never gets changed within the ajax call. I could be implementing .done incorrectly, but I just can't seem to figure out why I am not hitting anything and can't seem to find a log that is a help in finding the next step.
On previous edit I removed localhost from php calls ('localhost/server-api.php' returned a 404) and now I am stuck again. I get a 304 Not Modified from my jQuery call, but I thought that, as of jQuery 1.5 ajax handled this as a success so I should still be hitting my html text update (correct?) and I don't.
WAMP access Log:
127.0.0.1 - - [14/Jan/2014:14:22:45 -0500] "GET /client.php HTTP/1.1" 200 2146
127.0.0.1 - - [14/Jan/2014:14:22:45 -0500] "GET /jquery.js HTTP/1.1" 304 -
127.0.0.1 - - [14/Jan/2014:14:22:45 -0500] "GET /server-api.php HTTP/1.1" 200 38
Note - this is the only log that updates when I refresh client.php in my browser. my js console stays blank. I have uploaded this to a temp site: zgc7009.99k.org/client-99k.php
Forgive me if the following is drawn out, but I wish to explain all that I can;
Firstly, as noted in comments, the error method of the jQuery .ajax() method only gets called if there is an error when the method attempts to load the requisite php page you(or it(if you don't specify a url, it uses the current page)) has specified. An error in this regard would be something like a 404(page not found), 500(server error), or what-have-you.
The current error you are experiencing is two-fold:
You are not running a server on your computer(or you are and aren't accessing the page via the correct url in your browser(it should be localhost/path/to/file.extension)
Same origin policy is preventing your page from even being loaded
In regards to problem #1, a php page needs to be processed by your php interpreter, which you need to have installed on your system. I would recommend something like xampp to suit this case, though there are plenty others available.
When accessing a server which is running on your machine, one uses the localhost url in the address bar, no protocol(http://,https://,ftp://,etc), and never a file:/// protocol. For example, if I were to visit the folder test's index.php file, it would be localhost/test/index.php.
In regards to problem #2, browsers have various restrictions in place in order to prevent malicious code from executing.. One of these restrictions is the Same Origin policy, a policy which restricts documents of a differing origin than the originating request from accepting that request. For example..
If we have a server at domain.website.com, and it makes a request to otherdomain.website.com, the request will fail as the endpoint of the request is on a different domain.
Likewise, the same exists for any requests made in regards to a file:/// protocol.. It is always1 treated as a different origin, and it will always1 fail. This behavior can be changed, but it is not recommended, as it is a security hole.
I also recommend you check out MDN's article on SOP.
Of course, to fix all this.. install a web server(like xampp or wamp) on your machine(depending on your OS) or use a hosted web server, never open your html file by double clicking it, but by visiting its url(according to your webserver's directory(it differs per server)), and always make sure your domains and ports match.
1: Except in certain cases, such as here
Edit 1:
Don't know why I didn't see this before; we could have avoided headaches.. anyway, firstly, change the error catching you do here:
$dbs = mysql_select_db($databaseName, $con);
echo mysql_errno($con) . ": " . mysql_error($con). "\n";
To:
$array = array('mysql' => array('errno' => mysql_errno($con), 'errtxt' =>mysql_error($con)));
And then, change your array set after your db handling to this:
$result = mysql_query("SELECT * FROM $tableName"); //query
$array['mysql'][] = array('errno' => mysql_errno($con), 'errtxt' =>mysql_error($con));
$array['data'] = mysql_fetch_row($result);
To explain what I've changed, and why.. Your first echo was causing the json parser to fail when parsing your echoed json. If you didn't have your console open during your refresh, you wouldn't have seen that it did in fact execute the ajax request. You also do not define an error handler, so you would have never known. In order to parse the new json I just created above, modify your success handler's variable declarations above into this:
var id = data.data[0]; //get id, data['data'][0] works here as well
var vname = data.data[1]; //get name
Of course, if your mysql causes any errors, you can then access those errors with the following:
console.log(data.mysql);
Again, in your success function. To see if you have any errors with the actual .ajax() method or such, you can just do this for your error handler:
error: function() {
console.log(arguments);
}
please you should start learning to PDO or Mysqli real fast, mysql_* will soon be depreciated, that is soonest, let me rewrite your query for you using PDO and prepared statements, you can kick it off from there.
$connectionStr = 'mysql:host='.$host.';dbname='.$databaseName.'';
$driverOptions = array();
$dbh = new PDO($connectionStr, $user, $pass, $driverOptions);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$query = $dbh->prepare("SELECT * FROM $tableName");
$query->execute();
$array = fetch(PDO::FETCH_OBJ);
echo json_encode($array);

Categories

Resources