CGI Perl Use of uninitialized value $user in string - perl

I have a problem checking if the variables I retrieve with CGI are right.
HTML:
<label for="name">Nombre de Usuario:</label>
<input type="text" id="name" name="user_name" />
<label for="password">Contraseña:</label>
<input type="password" id="password" name="user_password" />
CGI/Perl code:
my $c = CGI->new;
.
.
.
my $user = $c->param('user_name');
my $password = $c->param('user_password');
if($user eq "" || $password eq "") {
printf "Error";
exit;
}
The main problem is that if I just do:
print $user;
The output is correct and it prints the value, but in apache error.log, it still says that the variable is uninitialized and then goes into the "if" and exits.
I also tried with "$user" and comparing the strings to undef but nothing.

To test whether a variable has a defined value, you should use the 'defined' function:
if (!defined($user) || !defined($password)) { ... }

If those parameters have not been passed in by the form then they will be undefined, and you will receive a warning if enabled by "use warnings;". You can ensure they are defined by providing fallback values for the assignments:
my $user = $c->param('user_name') // "";
my $password = $c->param('user_password') // "";

Related

Secure SQL update in PHP

As part of a job I want to update a database using a form. Since the database is large and is used by many users, I hope that this manipulation is at least secure for more safety.
HTML script :
<form action="http://localhost/modifier_infos_signaletique.php" method=POST >
<div class="id_sign">
<h5>Id "Signalétique" :</h5>
<input type="text" name="id_sign" id="id_sign"/><br>
</div>
<h5>Infos "Signalétique" : </h5>
<input class="comment" type="text" id="maj_infos" name="maj_infos" required maxlength='140'/><br>
<input type="submit" value="Submit" />
</form>
PHP script:
<?php
$user = 'xxxx';
$pass = 'xxxx';
try{
$dbconn = new PDO('pgsql:host=localhost;port=5432;dbname=xxxx',$user, $pass);
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$maj = $_POST['maj_infos'];
$id = $_POST['id_sign'];
$query = $dbconn->prepare("UPDATE signaletique SET infos = ':infos' WHERE id = ':id'");
$query->bindParam(':infos', $maj, PDO::PARAM_STR);
$query->bindParam(':id', $id, PDO::PARAM_INT);
$query->execute();
echo 'Données mises à jour';
}
catch(PDOException $e){
echo "Erreur : " . $e->getMessage();
}
?>
However, when I use this script this error appears:
**Erreur : SQLSTATE[HY093]: Invalid parameter number: :infos **
The error would be due to the parameter used for the bindParam function.
However, I have in the properties of my PostgreSQL database, info in "character varying". I tried to change this parameter to "text", but the error remains the same.
Forgive me for this question but I am new to PHP and my SQL skills are thin since I use pgAdmin and its tools a lot to build and interact with my databases.
Here is a screenshot of my database :
The info parameter is in "text" on the screenshot but basic this property was in "character varying" (140).
Thank you for your help.
In your query string you put single quotes around your placeholders. This makes them strings, not placeholders. You do not need quotes when using placeholders.
This should work:
$query = $dbconn->prepare("UPDATE signaletique SET infos = :infos WHERE id = :id");
See https://stackoverflow.com/questions/10966251/sqlstatehy093-invalid-parameter-number-parameter-was-not-defined for more information.

How to repost a webpage?

I am creating a simple perl script to create a web page to register users. This is just a learning program for me. It is very simple. I will display a page on the browser. The user enters name, user name, and password. After the user presses submit, I will check the user name against the database. If the user name exists in the database, I just want to display an error and bring up the register page again. I am using the cgi->redirect function. I am not sure if that is how I should use the redirection function. It does not work like I thought. It display "The document has moved here". Please point me to the right way. Thanks.
Here is the scripts
registeruser.pl
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print <<PAGE;
<html>
<head>
<link rel="stylesheet" type="text/css" href="tracker.css"/>
</head>
<body>
<div id="header">
<h1> Register New User</h1>
</div>
<div id="content">
<form action="adduser.pl" method="POST">
<b>Name:</b> <input type="text" name="name"><br>
<b>UserName:</b> <input type="text" name="username"><br>
<b>Password:</b> <input type="password" name="password"><br>
<input type="submit">
</div>
</body>
<html>
PAGE
adduser.pl
#!/usr/bin/perl
use CGI;
use DBI;
$cgiObj = CGI->new;
print $cgiObj->header ('text/html');
# get post data
$newUser = $cgiObj->param('username');
$newName = $cgiObj->param('name');
$newPass = $cgiObj->param('password');
# set up sql connection
$param = 'DBI:mysql:Tracker:localhost';
$user = 'madison';
$pass = 'qwerty';
$connect = DBI->connect ($param, $user, $pass);
$sql = 'select user from users where user = "' . $newUser . '"';
$query = $connect->prepare ($sql);
$query->execute;
$found = 0;
while (#row = $query->fetchrow_array)
{
$found = 1;
}
if ($found == 0)
{
# no user found add new user
$sql = 'insert into users (user, name, passwd) values (?, ?, ?)';
$insert = $connect->prepare ($sql);
$insert->execute ($newUser, $newName, $newPass);
}
else
{
# user already exists, get new user name
# What do I do here ????
print $cgiObj->redirect ("registerusr.pl");
}
One thing to look out for, SQL Injection. For an illustrated example, Little Bobby Tables.
As it stands your code is inescure, and can allow people to do bad things to your database. DBI provides placeholders as a secure way of querying a database with user input. Example http://bobby-tables.com/perl.html
Also, in this day and age even the CGI module warns you not to use it:
The rational for this decision is that CGI.pm is no longer considered good practice for developing web applications, including quick prototyping and small web scripts. There are far better, cleaner, quicker, easier, safer, more scalable, more extensible, more modern alternatives available at this point in time. These will be documented with CGI::Alternatives.
I suggest you use Dancer to make your life easier.
Three things
Include use strict; and use warnings; in EVERY perl script. No exceptions.
This is the #1 thing that you can do to be a better perl programmer. It will save you an incalculable amount of time during both development and testing.
Don't use redirects to switch between form processing and form display
Keep your form display and form processing in the same script. This enables you to display error messages in the form and only move on to a new step upon a successfully processed form.
You simply need to test the request_method to determine if the form is needing to be processed or just displayed.
CGI works for learning perl, but look at CGI::Alternatives for live code.
The following is your form refactored with the first 2 guidelines in mind:
register.pl:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $name = $q->param('name') // '';
my $username = $q->param('username') // '';
my $password = $q->param('password') // '';
# Process Form
my #errors;
if ( $q->request_method() eq 'POST' ) {
if ( $username =~ /^\s*$/ ) {
push #errors, "No username specified.";
}
if ( $password =~ /^\s*$/ ) {
push #errors, "No password specified.";
}
# Successful Processing
if ( !#errors ) {
# Obfuscate for display
$password =~ s/./*/g;
print $q->header();
print <<"END_PAGE";
<html>
<head><title>Success</title></head>
<body>
<p>Name = $name</p>
<p>Username = $username</p>
<p>Password = $password</p>
</body>
</html>
END_PAGE
exit;
}
}
# Display Form
print $q->header();
print <<"END_PAGE";
<html>
<head>
<link rel="stylesheet" type="text/css" href="tracker.css"/>
</head>
<body>
<div id="header">
<h1>Register New User</h1>
</div>
#{[ #errors ? join("\n", map "<p>Error: $_</p>", #errors) : '' ]}
<div id="content">
<form action="register.pl" method="POST">
<b>Name:</b> #{[ $q->textfield( -name => 'name' ) ]}<br>
<b>UserName:</b> #{[ $q->textfield( -name => 'username' ) ]}<br>
<b>Password:</b> #{[ $q->password_field( -name => 'password' ) ]}<br>
<input type="submit">
</div>
</body>
<html>
END_PAGE
__DATA__

multiple instances of Singleton CGI Object in perl

i hava a cgi page index.cgi and one template of login form as
index.cgi
use Singleton::CGI;
use Singleton::Session;
$q = new Singleton::CGI();
$session = new Singleton::Session();
$template = HTML::Template->new(filename => 'login.tmpl');
print $q->header;
print $q->start_html("hello perl");
print $q; # printing hash of CGI Object.
print $session;
print $template->output;
print $q->end_html;
if($q->param('submit')){
print $q->header;
print $q->start_html("hello user");
print $q; # printing hash of CGI Object.
print $session;
print $q->param('text');
print $q->end_html;
}
login.tmpl:
<form action="/" method="post">
<input type="text" name="text"/>
<input type="submit" name="submit" value="submit"/>
</form>
here is the output when i get the index.cgi
CGI=HASH(0xbe0510)
SingletonSession=HASH(0x1e67ee60)
along with form
next when i submit the form then
CGI=HASH(0xe2ac500) alnog with form input value.
SingletonSession=HASH(0x115dc7a0)
as per my requirement i should only get one session Object.
how should i maintain only one query and session Object through out the application?
Your web server executes your script for each request it receives, so you're asking to share a variable across two processes that aren't even running at the same time. Impossible. That's why sessions are used, to provide persistence of information.

Strange behaviour with Zend_Element 'belongsTo' property

I've seen other threads and bug reports to do with the belongsTo property of an Zend_Element but nothing that relates directly to what i'm experiencing..
Here is my (simplified) Zend_Form:
$form = new Zend_Form();
$form->addElement('text', 'fname', array('belongsTo' => 'user'));
$form->addElement('text', 'sname', array('belongsTo' => 'user'));
Which is fine and the elements render like so:
<input type="text" name="user[fname]" />
<input type="text" name="user[sname]" />
...which is exactly what i want.
However, when the form is submitted, the element values are only accessible if you call
$form->getValue('fname') or $form->getValue('sname')
NOT, if you call...
$form->getValue('user');
What i'm expecting to see when you call $form->getValues('user') is an array of the values.
The array of values is clearly visible if you call
$form->getValues();
If this is the expected behaviour, then whats the point of putting them in an array? Because there would be no distinction between "user[fname]" and "client[fname]" - in fact adding another element with name "fname", even though it belongs to another item, would overwrite the previous.
I've tried adding a sub form which does result in what i want, but that way all the sub-form elements get rendered together, what i really want is to lay the 'array' elements in random places, like this...
<input type="text" name="user[fname]" />
<input type="text" name="some-other-field" />
<input type="text" name="some-other-field2" />
<input type="text" name="user[sname]" />
<input type="text" name="another-field-too" />
$form->getValue('fname') or $form->getValue('sname')
works this way because getValue() is just looking for the name of the element, and the names of your elemnts are fname and sname.
Excerpt: Zend/Form.php
public function getValue($name)
{
if ($element = $this->getElement($name)) {
return $element->getValue();
}
the way to access your belongsTo data from what I've seen should be:
$data = $form->getValues();
$user=$data['user'];
this should do what you want. Based on this:
Excerpt: Zend/Form.php
public function getValues($suppressArrayNotation = false)
{
$values = array();
$eBelongTo = null;
if ($this->isArray()) {
$eBelongTo = $this->getElementsBelongTo();
}
foreach ($this->getElements() as $key => $element) {
if (!$element->getIgnore()) {
$merge = array();
if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
if ('' !== (string)$belongsTo) {
$key = $belongsTo . '[' . $key . ']';
}
}
$merge = $this->_attachToArray($element->getValue(), $key);
$values = $this->_array_replace_recursive($values, $merge);
}
}
//...Code continues
return $values;
Hope this helps.

How to check the HTML element is a end node?

I am building a HTML parser in Perl. I would like to know if the HTML element is an element without any sibilings.
Here is the HTML, I would like to parse :
<span class="bold1">A:</span> ELementA<br />
<span class="bold1">B:</span> mailto:admin<br />
<span class="bold1">C </span> 01/12<br />
<span class="bold1">D:</span> ELementC<br />
<span class="bold1">E:</span> ElementD<br />
<span class="bold1">F:</span> ElementE<br />
How to check if the element is the end element.
I am getting the error :
Can't call method "as_text" without a package or object reference at
Any idea what could be wrong ?
Here is the code snippet in Perl,
my $mech = WWW::Mechanize->new( autocheck => 1 );
eval
{
$mech->get($url);
};
if ($#)
{
print "Error connecting to URL $url \n";
exit(0);
}
my $root = HTML::TreeBuilder->new_from_content(decode_utf8($mech->content));
my #PageSections = $root->look_down(
sub {
return (
($_[0]->tag() eq 'span' ) and
($_[0]->attr('class') =~ m/bold1/i) )
});
my $temp2;
my $temp3;
for my $ps (#PageSections)
{
# my $temp1= $ps->right()->as_text;
$temp2= $ps->as_text;
my $temp3=ref $ps->right();
#
print defined $temp3 ? "defined \n" : "not defined\n";
}
Thanks
It's hard to tell without knowing more of your code, but I'm guessing #PageSections contains objects of some home brewed module, and that something happens there to make $_ point to something completely different. I'd go with
for my $ps (#PageSections)
{
my $temp1= $ps->right()->as_text;
my $temp2= $ps->as_text;
print "$temp2 " . $temp1 . " \n";
}
instead.