-1

I've built mini content management system. In my page add form i'm using ckeditor. for text are named content

<textarea id="content" style="width:100%" name="content"></textarea>

Adding all data from form into db table with following php code. (Function filter used for sanitizing data)

<?php
require '../../core/includes/common.php';

$name=filter($_POST['name'], $db);
$title=filter($_POST['title'], $db);
$parentcheck=filter($_POST['parentcheck'],$db);
if(isset ($_POST['parent'])) $parent=filter($_POST['parent'],$db);
else $parent=$parentcheck;  
$menu=filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);

if(isset($_POST['submit'])&&$_POST['submit']=='ok'){
$result=$db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')") or die($db->error);
$new_id = $db->insert_id;
$result2=$db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')") or die($db->error);  
header("location:".$wsurl."admin/?page=add");       
}
?>

FUNCTION FILTER (data sanitization)

function filter($data, $db)
{
    $data = trim(htmlentities(strip_tags($data)));
    if (get_magic_quotes_gpc())
    $data = stripslashes($data);
    $data = $db->escape_string($data);
    return $data;
}

I got questions about it. (I'm newbie to ajax.)


  1. Currently i'm submitting data with standart php (page refreshes every time). How to modify code for ajax submission?
  2. I have only one button for submitting data. I want to create second button "save" which will update db fields via ajax
  3. How can i create autosave function (which periodically saves form in the background and informss user about it, just like on Stackoverflow) via ajax?

Thx in advance

demonoid
  • 318
  • 3
  • 13
  • 40
  • 1
    -1, I seriously doubt the SQL-injection escapeing in the code will actually work. – Johan Oct 02 '11 at 11:59
  • @Johan Don't u see "(Function filter used for sanitizing data)"?? upvote question please – demonoid Oct 02 '11 at 12:00
  • You should not code assuming that `get_magic_quotes_gpc` is switched on. That's a deprecated and insecure feature, better configure the server the script is running on. – hakre Oct 02 '11 at 12:08
  • Feel free to browse for any AJAX tutorial which should give you the hints you need, there are numerous similar questions here on SO even while yours is very limited to your needs and pretty broad. – hakre Oct 02 '11 at 12:10
  • well, thx for advises but my question is not about security holes. – demonoid Oct 02 '11 at 12:10
  • 1
    @TT13, In the `[php]+[mysql]` space security is a vital issue, not optional and not open for negotiation. – Johan Oct 02 '11 at 12:15
  • 1
    @Johan I still don't see how that is worthy of a downvote on a *question*. Why not simply point out what is wrong with the sanitation function? Plus, what it does is strip out way too *much*, but it looks pretty secure – Pekka Oct 02 '11 at 12:20
  • @Johan don't you see my `filter` function still? – demonoid Oct 02 '11 at 12:22
  • downvoter trolls. i don't understand what's wrong with my question – demonoid Oct 02 '11 at 12:22
  • @TT13, I'm the troll and your `filter` function does not do anything useful. See my answer below. I'm trolling you because I would like you to understand the issue of escaping. Please read this question: http://stackoverflow.com/questions/332365/xkcd-sql-injection-please-explain – Johan Oct 02 '11 at 12:26
  • I think it's silly to downvote a question because it has a broken sanitation function. However, honestly, if it hadn't two downvotes already, I would consider downvoting too because it's essentially a "write my code for me" question with no visible effort of your own. It's not what Stack Overflow is there for, and there are way too many of these every day. – Pekka Oct 02 '11 at 12:36
  • @pekka Removed the downvote I just wanted to poke tt13 a bit because i' ve seen this code before somewhere. -2 seems too harsh for this question though – Johan Oct 02 '11 at 12:42
  • @Johan Yeah. I think [this](http://stackoverflow.com/questions/7615545/inserting-values-into-multiple-mysql-tables-at-once) is where you saw the code first :) – Pekka Oct 02 '11 at 12:43

3 Answers3

3

Let's suppose you want to use jQuery to do the ajax business for you, you need to setup a periodic POST of the data in the textarea (note that in some browsers GET requests have a limit).

On the first POST, you need to tell the PHP script "this is the first POST" so that it knows to INSERT the data, it should then return to you some identifying characteristic. Every other time you POST data, you should also send this identifying characteristic, let's just use the primary key (PK). When you POST data + PK, the PHP script should run an update query on the SQL.

When constructing these, the thing to think about is sending data from the browser using JavaScript to a PHP script. The PHP script gets only whatever packet of data you send, and it can return values by producing, for instance, JSON. Your JavaScript code can then use those return values to decide what to do next. Many beginners often make the mistake of thinking the PHP can make calls to the JS, but in reality it's the other way around, always start, here, with the JS.

In this instance, the PHP is going to save data in the database for you, so you need to ship all the data you need to save to the PHP. In JS, this is like having some magic function you call "saveMyData", in PHP, it's just like processing a form submission.

The JavaScript side of this looks something like this (untested):

<script type="text/javascript">
    var postUpdate = function(postKey){
        postKey = postKey || -1;
        $.post("/myscript.php", 
               /* note that you need to send some other form stuff
                  here that I've omitted for brevity */
               { data: $("#content").value(), key: postKey }, 
               function(reply){
                   if(reply.key){
                       // if we got a response containing the primary key
                       // then we can schedule the next update in 1s
                       setTimeout(function(){postUpdate(reply.key);}, "1000");
                   }
               }
        });
    };
    // first invocation:
    postUpdate();
</script>

The PHP side will look something like this (untested):

Aside: your implementation of filter should use mysql_real_escape_string() instead of striptags, mysql_real_escape_string will provide precisely the escaping you need.

<?php
require '../../core/includes/common.php';

$name = filter($_POST['name'], $db);
$title = filter($_POST['title'], $db);
$parentcheck = filter($_POST['parentcheck'],$db);
if(isset($_POST['parent'])){
    $parent = filter($_POST['parent'],$db);
}else{
    $parent = $parentcheck;
}
$menu = filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);

$pk = intval($_POST['key']);

if($pk == -1 || (isset($_POST['submit']) && $_POST['submit']=='ok')){
    $result = $db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')") 
              or die($db->error);
    $new_id = $db->insert_id;
    $result2 = $db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')") 
               or die($db->error);
    $pk = $db->insert_id;
    echo "{\"key\": ${pk}}";
    // header("location:".$wsurl."admin/?page=add");       
}else if($pk > 0){
     $result2 = $db->query("UPDATE pages SET content='$content' WHERE id='$pk')") 
               or die($db->error);
     echo "{\"key\": ${pk}}";
}
Mark Elliot
  • 75,278
  • 22
  • 140
  • 160
  • -1, is one thing for a newbie to have insecure code in a question. Its a very different thing for someone with 16k rep in an answer that displays code in a copy-pasteable format. – Johan Oct 02 '11 at 12:19
  • @Johan You caught me in mid-edit, I needed the name of the function and it took me a few minutes to pick it out of the manual. (You'll note my edit was posted before your post, so there's no copy-jacking here, either) – Mark Elliot Oct 02 '11 at 12:25
  • Much improved note that you cannot mix mysqli_ and mysql_ functions and the op seems to be using mysqli_ – Johan Oct 02 '11 at 12:44
  • @Johan i'm not newbie to php. i'm newbie to js (especially ajax). OK? – demonoid Oct 02 '11 at 12:44
  • @tt13 I disagree you use magic-quotes use the silver bullet -but not really- filter function. These are beginners errors. That is why I used the n-word. Please don't take it personal I can only judge you by your code. – Johan Oct 02 '11 at 12:49
0

For AJAX, you can use jQuery's ajax API. It is very good and is cross-browser. And for saving and auto-saving: you can use a temporary table to store your data. When the user presses the save button or when your data is auto-saved, you save your data to the table using AJAX and return a key for the newly created row. Upon future auto-save/save button events, you update the temporary table using AJAX.

And one word of advice, use a framework for your PHP and Javascript. I personally use Symfony and Backbone.js. Symfony checks for CSRF and XSS automatically and using Doctrine prevents SQL-injection too. There are other frameworks available (such as CodeIgniter, CakePHP and etc.) but I think Symfony is the best.

Edit: For the auto-save functionality, you can use Javascript SetTimeout to call your AJAX save function, when the page loads for the first time.

Omid Kamangar
  • 5,768
  • 9
  • 40
  • 69
0

With regard to security issues:

Your silver bullet function is fundamentally flawed, it does not work, will never work and can never work.

SQL has different escaping needs than hmtl.
The functions you use counteract each other. escape_string adds \, stripslashes removes them.
Never mind the order of the functions, you need to use a specialized escape function for one and only one purpose.
On top of that you are using depreciated functions.

For MySQL this is mysql_real_escape_string. Note that escape_string (without the real) is depreciated, because it is not thorough enough. Use real_escape_string instead. On mysqli escape_string is an alias for real_escape_string.

See:
How does the SQL injection from the "Bobby Tables" XKCD comic work?
The ultimate clean/secure function

Community
  • 1
  • 1
Johan
  • 74,508
  • 24
  • 191
  • 319
  • 1
    read the documentation. Real escape and escape are the same things for mysqli. – demonoid Oct 02 '11 at 12:26
  • @Pekka, got a bit confused about the mysql and mysqli libs. Fixed the answer. – Johan Oct 02 '11 at 12:34
  • Dev with 14k rep. confused about the mysql and mysqli libs. Awesome. So why did you downvote then? – demonoid Oct 02 '11 at 12:38
  • @tt13 the downvote as such was correct. The other problem is that when you learn a new fact something else has to go to make room in your head i guess i learned something new today but strangly now i cannot seem to remember what it was..... – Johan Oct 02 '11 at 13:01