0
<?php
    session_start();
    if(!$_SESSION['Admin']) {
    header('Location: login.php'); exit();
    }
    ?>
    <!DOCTYPE HTML>
    <html>
    <head>
        <title> ticketExpress | Admin </title>
        <link rel='stylesheet' href='../assets/css/style.css'> 
    </head>
    <body>
    <div id='containerAdmin'>
    <h1> <img class='logo' src='../assets/images/logo.png' width='200' height='43'> </h1> <a href='?logout' class='logout'> Logout </a>
    <h3> Open Tickets </h3>
    <hr />
    <?php
    require("../configuration/config.php");
    $GetTickets = $con->query("SELECT * FROM tickets WHERE open='true'");
    while($TicketInfo = $GetTickets->fetch_object()) {
    $Subject = $TicketInfo->Subject;
    echo "<div id='ticket'>".$Subject ."<a href='?delete=$TicketInfo->ID'><img style='float:right'src='../assets/images/delete.png' width='15px' height='15px'></a><a style='float:right; color:red; text-decoration:none; margin-right:10px;' href='?close=$TicketInfo->ID'> Close </a><font style='float:right; margin-right:10px;  color:green;' id='responseMsg'> </font></div>";
    }
    if(isset($_GET['delete'])) {
    $ID = $_GET['delete'];
    echo "
    <script type='text/javascript'>
        var ajax = new XMLHttpRequest();
        ajax.open('POST','delete.php', true);
        ajax.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        ajax.onreadystatechange = function () {
            if(ajax.readyState == 4 && ajax.status == 200) {
                document.getElementById('responseMsg').innerHTML = ajax.responseText;
            }
            }
            ajax.send('delete=$ID');
        </script>
        ";
    }
    if(isset($_GET['logout'])) {
    session_destroy();
    header('Location: login.php');
    }
    if(isset($_GET['close'])) {
    $ID = $_GET['close'];
    echo "
    <script type='text/javascript'>
        var ajax = new XMLHttpRequest();
        ajax.open('POST','close.php', true);
        ajax.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        ajax.onreadystatechange = function () {
            if(ajax.readyState == 4 && ajax.status == 200) {
                document.getElementById('responseMsg').innerHTML = ajax.responseText;
            } 
            }
            ajax.send('close=$ID');
        </script>
        ";
    }
    ?>
    <br />
    </div>
    </body>
    </html>

My problem is that whenever I click delete, the ajax response always appears next to the first ticket on the page (the top one)

If I for example click "Close" next to ticket 21, the AJAX response "Ticket Succesfully Closed" will always appear next to the first ticket on the page (for example ticket 1)

Here is close.php

<?php
require('../configuration/config.php');
if(isset($_POST['close'])) {
echo "Ticket Successfully Closed";
$TID = $_POST['close'];
$con->query("UPDATE tickets SET open='false' WHERE ID='$TID'");
}

And delete.php

<?php
require('../configuration/config.php');
if(isset($_POST['delete'])) {
echo "Ticket Deleted";
$TID = $_POST['delete'];
$con->query("DELETE FROM tickets WHERE ID='$TID'");
}

All answers are much appreciated as always! thanks in advance

putvande
  • 15,068
  • 3
  • 34
  • 50
  • 2
    There's a ***HUGE*** flaw in your code security. – Jeff Noel Aug 14 '13 at 12:57
  • 2
    @JeffNoel You couldn't spend the few extra seconds to tell him *what* the flaw is? – user229044 Aug 14 '13 at 13:06
  • @meagar So couldn't you. To OP: It is really easy for someone to include a malicious string within your SQL query and proceed to do whatever they want to your database. Please read more about [How to prevent SQL Injections in PHP](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php). – Jeff Noel Aug 14 '13 at 13:28
  • I didn't read the question; you obviously had. – user229044 Aug 14 '13 at 13:29

1 Answers1

0

Your issue is in the while statement where you display the open tickets on the main page.

<font style='float:right; margin-right:10px;  color:green;' id='responseMsg'> </font>

First of all, the <font> tag is deprecated. Use another <div> instead. Second, what's happening here is that every ticket has an element with id='responseMsg' next to it. When JavaScript is asked to find an element with an ID of responseMsg, since there are multiples, it always resorts to the first one in the DOM.

To fix this, you need to use the IDs that you've given the tickets in your database. Try something like this:

while ($TicketInfo = $GetTickets->fetch_object()) {
    $Subject = $TicketInfo->Subject;
    $ID = $TicketInfo->ID;
    echo "<div class='ticket' id='ticket" . $ID . "'>" . $Subject . "...";
    // Later in the ticket...
    echo "<div class='ticketResponse' id='responseMsg" . $ID . "'> </div>";
}

This way you have tickets denoted by <div id='ticket1' ... >, and <div id='ticket2' ... >, and so on.

I notice that you used <div id='ticket'> to denote every ticket object. Again, this isn't valid HTML. You should define a CSS class for tickets to use, and then use <div class='ticket' ... > to enclose every ticket.

Anyway. After those changes are made, you need to change your responses from close.php and delete.php so that they can indicate the ID of the ticket that was closed or deleted. Then, your AJAX on your main page needs to parse this response and use the parsed ticket ID to put the message next to the appropriate ticket.

Change close.php to the following:

if(isset($_POST['close'])) {
    $TID = $con->real_escape_string($_POST['close']);
    $success = $con->query("UPDATE tickets SET open='false' WHERE ID='$TID'");
    if ($success) {
        echo $TID . "|Ticket Successfully Closed";
    }
    else {
        echo $TID . "|Ticket could not be closed.";
    }
}

And do something similar for delete.php. Notice that you need to send the response after the query is executed, because what if the query doesn't work?

Finally, for your AJAX...

ajax.onreadystatechange = function () {
    if(ajax.readyState == 4 && ajax.status == 200) {
        var response = ajax.responseText.split('|'),
            id = response[0],
            text = response[1];
        document.getElementById('responseMsg' + id).innerHTML = text;
    }
}
ajax.send('delete=$ID');

So basically, you'll have close.php and delete.php send a response in the format ID|MESSAGE. Then your AJAX function takes the data, splits it by the | character, and uses the different pieces accordingly.

And finally, note my use of mysqli::real_escape_string() in your close.php file. This fixes the security flaw that Jeff commented on. You never want to put data provided by the user directly into a database query. This makes you vulnerable to SQL injection attacks.

Hope this helps!

theftprevention
  • 5,083
  • 3
  • 18
  • 31