Accessing database from custom modules - sugarcrm

I'm trying to create a custom module and I'm trying to get MY SQL access.
But i keep getting
mysql_query() [function.mysql-query]: Access denied for user
'scripts'#'localhost' (using password: NO) in
/home/scripts/public_html/crm/modules/PcPal/book-engineer.php on line
14
How do I access the data on the database when making a sugar module?
<?php if(!defined('sugarEntry') || !sugarEntry) die ('Not A valid Entry point'); ?>
<h2>Book an Engineer</h2>
<form method="POST" >
Search Last Name : <input type="text" name="frm_last_name_search" value="<?php echo $_POST['frm_last_name_search']; ?>" />
<input type="submit" value="Search"/>
</form>
<?php
$sql = 'SELECT first_name, last_name, primary_address_street FROM contacts WHERE last_name = \''.$_POST['frm_last_name_search'].'\'';
$results = mysql_query($sql);
while($this_result = mysql_fetch_array($result))
{
print_r($this_result);
}
?>

You should look into using the bean methods for very common queries like this, as it's easier and more portable.
http://developers.sugarcrm.com/wordpress/2012/03/23/howto-using-the-bean-instead-of-sql-all-the-time/

Use the global object $db for doing the database actions.
If you have the module bean eg: $bean = new Contact();, you can use $bean->db instead of global $db.
Also while fetching from a table always use deleted = 0, as deleted items are marked as 1.
global $db;
$sql = "SELECT first_name, last_name, primary_address_street FROM contacts
WHERE last_name = '{$db->quote($_POST['frm_last_name_search']}' AND deleted = 0";
$rs = $db->query($sql);
while($row = $db->fetchByAssoc($rs))
{
print_r($row);
}

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__

PHP: If value is empty, to not sumbit target filepath to database

I have a very slight problem where I am not able to figure out how to get my target filepath not submit to the mysql database when the field value is empty. Right now, if I leave the image field empty, it still submits the filepath ($folder) to the database. I would like for when the field is left empty, to not send the filepath to mysql.
Form.php
<form enctype="multipart/form-data" action="add.php" method="POST">
HAZARD: <input name="haz1" value="hazard1" type="text" /><br>
<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
IMAGE: <input type="file" name="photo"><br>
<input type="submit" name="action" value="Load">
</form>
Add.php
<?php
$folder = "images/";
$target1 = $folder . basename( $_FILES['photo']['name']);
$photo = $target1;
require("../db.php");
$haz1 = $_POST['haz1'];
mysql_query("INSERT INTO testimg VALUES (null,'$haz1','$photo')") ;
move_uploaded_file($_FILES['photo']['tmp_name'], $target1);
?>
I've tried
if (isset($_POST['photo']) ? $_POST['photo'] : null) echo $target1 == null);
I've tried other ways of isset as well but doesn't seem to work. Is there any other way i can accomplish this? Appreciate any help please. Thank you!
(Just a note, I have removed excess code above just to keep it short. I am taking care of SQL injection)
I would strongly suggest JavaScript, then users do not need to reload the page if it is empty. The JavaScript will check if it is empty for you. If it is you can make it so they cannot submit at all.
function validateForm()
{
var x=document.forms["myForm"]["fname"].value;
if (x==null || x=="")
{
alert("First name must be filled out");
return false;
}
}
This is an example above, if you would like better walk through go here
JQuery has libraries that you can use to do fancy things if it is left blank, just search for JQuery form validation for more tools.
Hope this helps!
Try using the inbuild HTTP_POST_FILE in PHP:
if (isset($_FILES['photo']) ? $_FILES['photo'] : null)
You could wrap the mysql code inside of an if function too:
if (isset($_FILES['photo']) {
//Do mySQL processing in here
}
A couple of points:
Require is at the top of a PHP script. It's nicer to see all requires
first.
I have used an inline if statement to determine what to set $photo
(elimintating need for $target1)
I have also moved the apostrophes into the assignment of $photo as
returning 'null' comapred to null (without the quotation marks) is
very different in SQL.
If $photo is not null at the end of the script then it moves the
updated file.
Please see the corrected code below:
<?php
require("../db.php");
$folder = "images/";
$photo = (isset($_FILES['photo']) ? "'" . $folder . basename( $_FILES['photo']['name']) . "'" : null);
$haz1 = $_POST['haz1'];
mysql_query("INSERT INTO testimg VALUES (null,'$haz1',$photo)") ;
if ($photo != null) { move_uploaded_file($_FILES['photo']['tmp_name'], $photo); }
?>

md5 to sha1 password hash changing

Basically I've got a game server in which had the password hash as sha1 and another as md5 for when new users registered an account. I decided to stick with sha1, however I want to be able for my users to change their password which will create them into sha1 from md5.
I've got the below code I've written up but it doesn't seem to work.
Basically, I want it to when they change their password it replaces the md5 with the sha1 hash password.
<?php
if(isSet($_POST['submit']))
{
$changePW = true;
}
?>
<?php
public function hashed($password)
{
return sha1($password . "xCg532%#%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");
}
?>
<?php
if(isset($changePW))
{
//host, username, password, dbName
$con=mysqli_connect("localhost","root","password","dbName");
$username = $_POST['username'];
$password = $_POST['passwordOld'];
$passwordNew1 = $_POST['passwordNew1'];
$passwordNew2 = $_POST['passwordNew2'];
$passwordHash = md5($password);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$cmd = "SELECT COUNT(*) FROM users WHERE username = '" . $username . "' AND password = '" . $passwordHash . "'";
$result = mysqli_query($con,$cmd);
$row = mysqli_fetch_row($result);
if($row[0] == 1)
{
if($passwordNew1 == $passwordNew2)
{
$newHash = hashed($passwordNew1);
$cmd = "UPDATE users SET password = '$newHash' WHERE username = '$username'";
mysqli_query($con,$cmd);
}
else{
$passwordMatch = true;
}
}
else {
$detailsError = true;
}
//$hash = md5($password);
//mysqli_query($con,"INSERT INTO tutorials_tbl (name, hash) VALUES ('" . $username . "','" . $hash . "')");
mysqli_close($con);
}
?>
<head>
<style type="text/css">
.lblLabel{
width:165px;
display: inline-block;
}
</style>
</head>
<form name="login" method="post" action="change.php">
<fieldset style="width:350px;"><legend>Change Password Form</legend>
<label class="lblLabel">Username</label><input id="name" type="text" name="username" value=""><br />
<label class="lblLabel">Old Password</label><input type="password" name="passwordOld"><br />
<?php
if(isset($detailsError))
{ ?>
<span style="color: #F00; font-weight: bold;">Username or Password Incorrect</span>
<?php }
?>
<label class="lblLabel">New Password</label><input type="password" name="passwordNew1"><br />
<label class="lblLabel">Repeated New Password</label><input type="password" name="passwordNew2"><br />
<?php
if(isset($passwordMatch))
{ ?>
<span style="color: #F00; font-weight: bold;">Password's do not match</span>
<?php }
?>
<label class="lblLabel"> </label><input id="submit" type="submit" name="submit" value="Change Password"><br />
</fieldset>
</form>
It's calling to change the password under the password column to sha1, in the users table. All current passwords in the users table are md5 and need to be converted into sha1.
Sorry if this doesn't make sense.
Every password-storing-system must have the option to switch to a better hash algorithm, your problem is not a one-time migration problem. Good password hash algorithms like BCrypt have a cost factor, from time to time you have to increase this cost factor (because of faster hardware), then you need the exact same procedure as you need for the migration.
That leads to your biggest problem, SHA-1 is not appropriate to hash passwords, especially if it is salted with a constant salt. It is ways too fast and makes it easy to brute-force (3 Giga hashes per second with common hardware in 2013). That's why one should use a slow key-derivation function like BCrypt. If you take the effort to migrate your hashes, then better switch straight to BCrypt.
The usual way to switch to a better hash algorithm is to wait until the user logs in the next time (in contrast to your example, the user doesn't need to change the password then). Then you take this steps:
First try to verify the entered password with the new algorithm. New passwords and already converted passwords will not take longer for verification then.
If it does not match, compare it with the old hash algorithm.
Should the old hash value match, then you can calculate and store the new hash, since you know the password then.
This system can be extended to more than one migration. Just make sure that you first check for the newest algorithm, and afterwards for older algorithms. Then the login will take longer only the next time the user logs in, and new users are not affected by backwards compatibility issues.
That leaves the question of how to use BCrypt. PHP 5.5 will have it's own functions password_hash() and password_verify() ready. I recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
➽ Keep in mind, that you need a database field with 60 characters in length, to store such hash-values.
As explained in my comment, what you'd want to do to make the transition in password storage as smooth as possible for the user is to hash everyone's password against SHA1 while leaving it MD5-hashed. Then, in your normal login logic, you'd MD5-hash the password, then SHA1-hash that.
As an aside, I'd use SHA2 for a hashing algorithm (just as fast, more secure, etc.)
<?php
public function hashSpecial($password)
{
return sha1($password . "xCg532%#%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");
}
public function hashForLogin($password)
{
return sha1(md5($password)
. "xCg532%#%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");
}
public function hashAllPasswords()
{
$con = mysqli_connect("localhost", "root", "password", "dbName");
$query = 'SELECT username, password FROM users';
if(mysqli_connect_errno() > 0)
{
echo 'Failed to connect to database.';
break;
}
else
{
$result = mysqli_query($con, $query);
while(($row = mysqli_fetch_row($result)) != null)
{
$query = 'UPDATE users SET password=\''
. hashSpecial($row['password']) . '\' WHERE username=\''
. $row['username'] . '\'';
$r2 = mysqli_query($con, $query);
}
}
}
?>

How to filter New WP Query by Custom Field Value?

I am creating new pages for each of my categories in wordpress. The post editor has a custom field that allows the selection of a sector type, this gets applied to the post on update. The custom field key is: sector, for custom field meta value options lets use SectorA, SectorB and SectorC. I am using a custom post type called projects.
I followed the advice at this link http://weblogtoolscollection.com/archives/2008/04/13/how-to-only-retrieve-posts-with-custom-fields/
How can I change the query line in the code below so that it filters the loop by a Sector name, lets use SectorA. I'll then reuse the code on each template page changing the value to SectorB and SectorC on the other pages.
I think this needs changing somehow:
$customPosts->query('showposts=5&sector=sectorA&post_type=projects' );
Currently it echos the sector value and description value successfully but is showing all the posts. So my attempt to limit it to sectorA using sector=sectorA doesn't seem to work?
This code is in functions.php:
function get_custom_field_posts_join($join) {
global $wpdb, $customFields;
return $join . " JOIN $wpdb->postmeta postmeta ON (postmeta.post_id = $wpdb->posts.ID and postmeta.meta_key in ($customFields)) ";
}
function get_custom_field_posts_group($group) {
global $wpdb;
$group .= " $wpdb->posts.ID ";
return $group;
}
And this code is on the Template Page:
<?php /* Begin Custom Field Posts */ ?>
<h2>Custom Posts</h2>
<ul>
<?php
global $customFields;
$customFields = "'sector', 'description'";
$customPosts = new WP_Query();
add_filter('posts_join', 'get_custom_field_posts_join');
add_filter('posts_groupby', 'get_custom_field_posts_group');
$customPosts->query('showposts=5&sector=sectorA&post_type=projects' );//Uses same parameters as query_posts
remove_filter('posts_join', 'get_custom_field_posts_join');
remove_filter('posts_groupby', 'get_custom_field_posts_group');
while ($customPosts->have_posts()) : $customPosts->the_post();
$sector = get_post_custom_values("sector");
$description= get_post_custom_values("description");?>
<li><?php echo $sector[0]; ?></li>
<li><?php echo $description[0]; ?></li><br />
<?php endwhile; ?>
</ul>
<?php /* End Custom Field Posts */ ?>
Thanks for your help
May be this what you want
function get_custom_field_posts_join($join) {
global $wpdb, $customSector;
return $join . " JOIN $wpdb->postmeta postmeta ON (postmeta.post_id = $wpdb->posts.ID and postmeta.meta_key = 'sector' and postmeta.value = '$customSector') ";
}
and modification of page
$customSector='sectorA';//<--- insert this
add_filter('posts_join', 'get_custom_field_posts_join');
Try using this code.
<?php
$sector = get_post_meta($post->ID, "sector", false);
if ($sector[0]=="") { ?>
<!-- If there are no custom fields, show nothing -->
<?php } else { ?>
<div class="sector">
<h3>Title</h3>
<?php foreach($sector as $sector) {
echo '<blockquote><p>'.$sector.'</p></blockquote>';
} ?>
</div>
<?php } ?>