I’m adding private messaging to my site. In the Recipient text field in my form, I want to suggest valid usernames when someone starts typing. After reading tutorials and studying some scripts I made the following code for suggesting usernames from my database table named users. It works but I’m not certain how correct and secure it is.
Jquery (using the Jquery UI autocomplete plugin):
$(function() {
$( "#username" ).autocomplete({ //the recipient text field with id #username
source: function( request, response ) {
$.ajax({
url: "http://localhost/mysite/index.php/my_controller/search_username",
dataType: "json",
data: request,
success: function(data){
if(data.response == 'true') {
response(data.message);
}
}
});
},
minLength: 1,
select: function( event, ui ) {
//Do something extra on select... Perhaps add user id to hidden input
},
});
});
Controller (for simplicity I did not use a model although I plan to)
function search_username()
{
$username = trim($this->input->get('term')); //get term parameter sent via text field. Not sure how secure get() is
$this->db->select('id, username');
$this->db->from('users');
$this->db->like('username', $username);
$this->db->limit('5');
$query = $this->db->get();
if ($query->num_rows() > 0)
{
$data['response'] = 'true'; //If username exists set true
$data['message'] = array();
foreach ($query->result() as $row)
{
$data['message'][] = array(
'label' => $row->username,
'value' => $row->username,
'user_id' => $row->id
);
}
}
else
{
$data['response'] = 'false'; //Set false if user not valid
}
echo json_encode($data);
}
There is one edit that I would recommend making...
I would enable XSS protection by passing a second argument TRUE to get()
$username = trim($this->input->get('term', TRUE));
You can also add more exception, if you wish that function will works only for ajax calls :
if($this->input->is_ajax_request())
{
//... process the input
}
else
{
show_404();
}
Codeigniter active record database should make your code clean of any SQL injections. And if you're not posting anything you don't need to worry about XSS.
Using this someone could get a list of all possible usernames.. but other than that I would say it's "secure" (it looks very similar to what i'm using for my site =p)
EDIT:
And if you're not posting anything you don't need to worry about XSS.
I should clarify, IF you are posting anything (displaying anything that the user enters) then you should XSS filter (which johndavidjohn's answer below me explains [just pass TRUE as 2nd param]).. I didn't quite understand what u meant in your explanation of what "term" is... If all you are doing is searching, then you do not need to XSS filter, but if a user can send/write a message (generate content that your site stores [to be displayed]) then you should XSS filter on iput.
Related
This may be a longshot but I am struggling to find help online and I am genuinely lost ..
I am building a CodeIgniter Web App where users can sign in, and create email templates, then send them to contacts..
I am using the Trumbowyg Editor for creating the email templates which I have found quite good and flexible, i have pre-made templates the users can select and edit if they please..
what i want however is for a user to create their own template, or make edits to an existing one, and save it to be able to come back at a later date.. I think it is possible to save it to my database, I have a template table setup correctly with foreign keys etc and i have the 'templatestyle' field type set as 'blob', in order to save the content here..
I am able to get the contents of the wysiwyg as when I test out this code of clicking the saveContent button I get the current content in the console.log;
$("#saveContent").click(function(){
console.log($("#trumbowyg-demo").html());
});
so what i need is this content saved to my database template table which has 3 columns; 'an id, a foreign key id for the user, and the template style..
I realise there is a lot in here and any code provided in order to help me set this up to save my database will be massively appreciated
thanks in advance!
Generally speaking you just have to send a simple post with one var to a controller method that receives the post var and inputs it in the database.
JS:
$("#saveContent").click(function () {
var content = $("#trumbowyg-demo").html();
$.ajax({
type: 'POST',
url: '/somecontroller/add',
data: {
content: content
},
dataType: 'json',
success: function (data) {
if (data.status == 'error') {
alert('An error occured: ' + data.msg);
} else {
alert('Success: ' + data.msg)
}
}
});
});
PHP:
class Somecontroller extends CI_Controller {
public function add() {
$content = $this->input->post('content');
if (empty($content)) {
echo json_encode(array('status' => 'error', 'msg' => 'Content field cannot be empty!'));
exit;
}
// db functions should be move to a model
// probably would be a good idea to filter $content somehow
// all the db insert does is escape
$this->db->insert('sometable', array('somefield' => $content));
echo json_encode(array('status' => 'success', 'msg' => 'Item added with id: ' . $this->db->insert_id()));
exit;
}
}
I had created basic custom module. in that i just filled information form and that information will stored into the database. and that data i am showing into table format. now i want to edit and delete records from clicking links.
I want to call php function on clicking following links
links are:
while($data = $result->fetchObject()){
$rows[] = array(
$data->id,
$data->name,
$data->address,
$data->mob,
$data->gen,
$data->email,
$data->hob,
l('Edit' .$data->id,'/table', array('query' => array('edi'=>$data- >id))),
l('Delete' .$data->id, '/table', array('query' => array('del'=>$data->id))),
);
}
and the functions are as follows:
function form_values_edit($id){
$id_val = $id;
$my_object = db_select('demo_forms','n')
->fields('n')
->condition('id', $id_val )
->execute()
->fetchAssoc();
return drupal_get_form('demo_form', $my_object);
}
function delete_confirm($form, &$form_state, $id){
$form['delete'] = array(
'#type' => 'value',
'#value' => $id,
);
return confirm_form(
$form,
t('Are you sure you want to delete this?',
'/table',
t('This action cannot be undone'),
t('Delete'),
t('Cancel')
));
}
function delete_confirm_submit($form, &$form_state) {
$record = $form_state['values']['delete'];
if ($record ) {
$num_deleted = db_delete('demo_forms')
->condition('id', $record )
->execute();
drupal_set_message('The record has been deleted!');
}
$form_state['redirect'] = "/table";
}
Thanks
You cannot call a PHP function dynamically by clicking a link, as PHP is a server side language. HOWEVER if you load another page, before loading the page you can execute PHP code.
EDIT
if you need a PHP function dynamically, what I usually do (and this may be wrong according to some people) is call that function in an AJAX call. Note: I would generally use POST for this.
$.ajax(
url: 'url/to/php/function',
type: 'POST/GET',
data: {'data' : data},
success: function(res) {
// use the result stored in res
},
error: function(res) {
// use res to get the error result
}
);
Just add check for id field or another unique value in your php code and update or delete rows where id = ... With out unique value you can't do that. Describe your usability and post your html for more...
This is my first attempt at trying to update a database with ajax & wordpress. I am trying to set a field to a status of 'complete' when a link is clicked. Everything seems to go fine, I get a "200 ok" response from the console, and the jQuery even shows the success actions that I'm taking. However the php doesn't update the database. The proper variables are being echoed out to the console, so I know those are being set correctly. I don't know if it's my MySQL query that I'm trying or if there's something that I'm overlooking. Any help or suggestions would be greatly appreciated.
Here's my jQuery:
// Click to Complete Activity Functionality
jQuery(".complete-activity").click( function( e ) {
e.preventDefault();
nonce = jQuery(this).attr("data-nonce")
wp_user_id = jQuery(this).attr("wp_user_id")
activity_post_id = jQuery(this).attr("activity_post_id")
wp_user_id = parseInt(wp_user_id);
activity_post_id = parseInt(activity_post_id);
console.log('My wp user id is: ' + wp_user_id);
console.log('My Activity id is: ' + activity_post_id);
jQuery.ajax({
type : "post",
url : myAjax.ajaxurl,
data : {
action: "gw_complete_activity",
"wp_user_id" : wp_user_id,
"activity_post_id" : activity_post_id,
"nonce" : nonce
},
success: function(response) {
console.log('Your field has been set as completed');
jQuery('li#active-'+ activity_post_id).css('display', 'none');
}
})
}) // End click to complete activity
Here's my php code:
<?php
//Complete Activity in Database (AJAX)
add_action("wp_ajax_gw_complete_activity", "gw_complete_activity");
add_action("wp_ajax_nopriv_gw_complete_activity", "my_must_login_to_complete");
function gw_complete_activity() {
if ( !wp_verify_nonce( $_REQUEST['nonce'], "gw_complete_activity")) {
exit("No naughty business please");
}
$wp_user_id = $_REQUEST['wp_user_id'];
$activity_post_id_complete = $_REQUEST['activity_post_id'];
$date_completed = current_time('mysql', 1);
global $wpdb;
$wpdb->update (
'wp_gwactivities',
array( 'date_completed' => $date_completed, 'activity_status' => 'complete'),
array( 'wp_user_id' => $wp_user_id)
);
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result_add = json_encode($result_add);
echo $result_add;
}
else {
header("Location: ".$_SERVER["HTTP_REFERER"]);
}
die();
}
function my_must_login_to_complete() {
echo "You must be logged in to complete your activities.";
die();
}
?>
Just because you get a 200 (OK) from the requested page, doesn't mean the requested page didn't error out :) Secondly, it looks like this is going to be used in Wordpress... with that said, you can't use add_action without having wordpress loaded.
For files outside the normal wordpress install, you need to include wp-load.php include "/path/to/wordpress/wp-load.php", for example. Then you can use its functions.
After your update query ,put below code and check query in mysql directly.
print_r($wpdb->last_query);
provide your query here also if its not work.
I am able to the js file to fire which does do the first alert but i cannot get the 2nd alert to happen, php file is there and working returning 0 but the alert('finished post'); is not coming up. I think its some syntax I am missing.
$(function () {
$("#login_form").submit(function () {
alert('started js');
//get the username and password
var username = $('#username').val();
var password = $('#password').val();
//use ajax to run the check
$.post("../php/checklogin.php", { username: username, password: password },
function (result) {
alert('finished post');
//if the result is not 1
if (result == 0) {
//Alert username and password are wrong
$('#login').html('Credentials wrong');
alert('got 0');
}
});
});
});
Here is the php
session_start();
include 'anonconnect.php';
// username and password sent from form
$myusername= $_POST['username'];
$mypassword= $_POST['password'];
$sql = $dbh->prepare("SELECT * FROM Users WHERE UserLogin= :login");
$sql->execute(array(':login' => $myusername));
$sql = $sql->fetch();
$admin = $sql['admin'];
$password_hash = $sql['UserPass'];
$salt = $sql['salt'];
/*** close the database connection ***/
$dbh = null;
if(crypt($mypassword, $salt) == $password_hash){
// Register $myusername, $mypassword and redirect to file
$_SESSION['myusername'] = $myusername;
$_SESSION['loggedin'];
$_SESSION['loggedin'] = 1;
if($admin == 1){
$_SESSION['admin'] = 1;
}
header("location:search.php");
}
else {
$_SESSION['loggedin'];
$_SESSION['loggedin'] = 0;
echo 0;
}
Ok so I'll take a stab at this, see if we can work this out. First, let's clean up your code a little bit - clean code is always easiest to debug:
$(function () {
$("#login_form").on('submit', function(){
console.log('form submitted');
// get the username and password
var login_info = { username: $('#username').val(), password: $('#password').val() }
// use ajax to run the check
$.ajax({
url: '../php/checklogin.php',
type: 'POST',
data: login_info,
success: loginHandler
error: function(xhr, status, err){ console.log(xhr, status, err); }
});
return false;
});
function loginHandler(loggedIn){
if (!loggedIn) {
console.log('login incorrect');
} else {
console.log('logged in');
}
}
});
...ok great, we're looking a little better now. Let's go over the changes made quickly.
First, swapped alerts for console.logs - much less annoying. Open up your console to check this out -- command + optn + J if you're using Chrome.
Second, we compressed the login info a bit - this is just aesthetics and makes our code a little cleaner. Really you should be using variables when they need to be used again, and in this case you only use them once.
Next, we swapped the $.post function for $.ajax. This gives us two things -- one is a little finer control over the request details, and the second is an error callback, which in this case is especially important since you almost certainly are getting a server error which is your original problem. Here are the docs for $.ajax for any further clarification.
We're also pointing the success handler to a function to minimize the nesting here. You can see the function declared down below, and it will receive the data returned by the server.
Finally we're returning false so that the page doesn't refresh.
Now, let's get to the issue. When you use this code, you should see a couple things in your console. The first will probably be a red message with something like 500 internal server error, and the second should be the results of the error callback for the ajax function. You can get even more details on this in Chrome specifically if you click over to the Network Tab and look through the details of the request and response.
I can't fix your PHP because you didn't post it, but I'll assume you'll either follow up with an edit or figure that out yourself. Once you have the server issue ironed out, you should get back a clean console.log with the response you sent back, and you can move ahead.
Alternately, this will work because of the lack of page refresh in which case you can ignore the previous 2 paragraphs and declare victory : )
Hope this helps!
Ah, so damned obvious. You aren't cancelling the default submit action so the form is submitting normally. Add this
$("#login_form").submit(function (e) {
e.preventDefault();
// and so on
See http://api.jquery.com/event.preventDefault/
you need to change 2nd line and add the e.preventDefault to prevent the form from refreshing the whole page.
$("#login_form").submit(function (e) {
e.preventDefault();
Also I would change the AJAX request to use GET and change the code in PHP to read variables from GET so you can easily test the PHP page is working by running it in the browser like this
checklogin.php?username=x&password=y
try this:
$("#login_form").submit(function () {
alert('started js');
//get the username and password
var username = $('#username').val();
var password = $('#password').val();
//use ajax to run the check
$.post("../php/checklogin.php", { username: username, password: password }, function (result) {
alert('finished post');
//if the result is not 1
if (result == '0') {
//Alert username and password are wrong
$('#login').html('Credentials wrong');
alert('got 0');
}
}, 'text');
});
}, 'text');
maybe the server does not give the right data format. for example, if you request for json, and the jQuery cannot convert result sting to json. then the function would not be executed and then you would not able to get 'alert('got 0');' thing.
My website is dependent on unique content provided by the user's input.
So they type in, "sports," they will receive content based on sports. That is simple enough. However, once I start adding more keywords to it, it gets a bit more complicated, at least in the way I'm doing it.
I need to start constantly checking whether the user inputted data is an array or not, and manipulate the data different.
I am currently storing the user's selection using Codeigniter's session class, then retrieving and manipulating the data based on its value.
So they submit the form and my JS runs:
$('#topics_form').submit(function() {
var topic = document.getElementById('topics_filter').value
$.ajax({
type: "POST",
url: 'ajax/update_session_topic',
dataType: 'json',
data: { topic: topic },
success: function(){
load_custom_topics()
}
});
return false;
});
Then update_session_topic runs in my AJAX model
public function update_session_topic()
{
if ($this->session->userdata('active_topic') == FALSE)
{
$array['active_topic'] = $this->input->post('topic');
$this->session->set_userdata($array);
return true;
} else {
$this->page_model->add_session_topic($this->input->post('topic'));
return true;
}
}
When theres only 1 value, its no big deal.
However, when trying to add a second value...I am forced to check whether its an array or not, or make it one.
public function add_session_topic($current_filter)
{
$session = $this->session->userdata('active_topic');
if (is_array($session) == false)
{
$session = array($this->session->userdata('active_topic'));
}
foreach ($session as $keyword)
{
if ($keyword == $current_filter)
{
return false;
}
}
$session[] = $current_filter;
$active['active_topic'] = $session;
$this->session->set_userdata($active);
return true;
}
This occurs in my views as well.
Its kind of annoying, and I was hoping there was a better way to do this. Im still new to PHP/codeigniter, so I am open to anything.
Thanks!