1

I've looked at this code until I'm cross-eyed and can't see the error I'm making. I'm a bit of a beginner.

My HTML - editPost.php:

<?php 
    session_start();
    include "includes/header.php";
    include "connectioninfo.php";
    include "functions.php";

    if(isset($_SESSION['user']))
    {
        editPost();
    }
    else
    {
        header("Location: /");
    }

    $return = getPost();
?>

<div class="container">
    <form action="editPost.php" method="post">
            <?php $id = $_GET['id']?>
            <input type="hidden" name="id" value="<?php echo $id?>">
        <div class="row">
            <div class="lab">
                <label for="category">Category:<br/></label>
            </div>
            <div class="inp">
                <select id="category" required autofocus name="category">
                    <option value="" selected disabled hidden>Choose a category.</option>
                    <option value="Something">About</option>
                    <option value="Something else">Coding</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class="lab">
                <label for="title">Title.</label>
            </div>
            <div class="inp">
                <input type="text" name="title" placeholder="Title" required value="<?php echo $return[0]?>">
            </div>
        </div>
        <div class="row">
            <div class="lab">
                <label for="content">Content.</label>
            </div>
            <div class="inp">
                <textarea name="content" id="content" style="height: 30em;"><?php echo $return[1]?></textarea>
            </div>
        </div>
        <div class="row">
            <input type="submit" name="submit" value="Post.">
        </div>
    </form>
</div>
<?php
include "includes/footer.php";
?>

getPost() is just getting the values to autofill the form. it's a function in the included functions.php:

function getPost()
{
    global $connection;

    $id=$_GET['id'];
    $query = "SELECT * FROM database WHERE id = '$id'";
    $result = $connection->query($query);    
    if($result)
    {
        while($post = $result->fetch_object())
        {
            $id = $post->id;
            $title = $post->title;
            $link = $post->permalink;
            $summary = $post->summary;
            $category = $post->category;
            $content = $post->content;
            $pubDate = $post->pubDate; 
            $author = $post->author;
            $return = array($title,$content);
            return $return;
        }
    }
    else
    {
        die('Query FAILED!' . mysqli_error());
    }
}

and finally, editPost()

function editPost()
{
    global $connection;

    if(isset($_POST['submit']))
    {
        global $connection;

        $title = mysqli_real_escape_string($connection,$_POST['title']);
        $content = mysqli_real_escape_string($connection,$_POST['content']);
        $category = $_POST['category'];
        $id = $_POST['id'];
        //Permalink
        $link = strtolower(trim($title));
        $link = preg_replace('/[^a-z0-9-]/', '-', $link);
        $link = preg_replace('/-+/', "-", $link);
        $link = rtrim($link, '-');
        $link = preg_replace('/\s+/', '-', $link);        

        $query = "UPDATE database SET title = '$title', permalink = '$link', content = '$content', category = '$category' ";
        $query .= "WHERE id = '$id'";

        $result = $connection->query($query);
        if(!$result)
        {
            die('Query FAILED!' . mysqli_error());
        }
        else
        {
            header("Location: /");
        }
        $result->close();
    }
}

Clicking on the edit link of a post brings me to this form, and it looks great - title and content are filled out with what's in the database, and I'm ready to edit.

The process (both html and function) is nearly identical to my createPost.php, and that works fine. but editPost.php just sends me back to the same page, with no values in the fields, and the post hasn't been updated. No error messages either.

What am I missing?

Edit

As a reference, I'm posting the contents of newPost.php and the function newPost() - which are working fine.

newPost.php:

<?php 
    session_start();
    include "connectioninfo.php";
    include "functions.php";

    if(isset($_SESSION['user']))
    {
        newPost();
    }
    else
    {
        header("Location: /");
    }

    include "includes/header.php";
?>

<div class="container">
    <form action="newPost.php" method="post">
        <div class="row">
            <div class="lab">
                <label for="category">Category.</label>
            </div>
            <div class="inp">
                <select id="category" required autofocus name="category">
                    <option value="" selected disabled hidden>Choose a category.</option>
                    <option value="About">About</option>
                    <option value="Coding">Coding</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class ="lab">
                <label for="title">Title.</label>
            </div>
            <div class ="inp">
                <input type="text" name="title" required placeholder="Title">
            </div>
        </div>
        <div class="row">
            <div class ="lab">
                <label for="summary">Summary.</label>
            </div>
            <div class ="inp">
                <input type="text" name="summary" required placeholder="Summary (for the RSS feed and Twitter)">
            </div>
        </div>
        <div class="row">
            <div class="lab">
                <label for="content">Content.</label>
            </div>
            <div class="inp">
                <textarea name="content" id="content" placeholder="The content of the post" style="height: 30em;"></textarea>
            </div>
        </div>
        <div class="row">
            <input type="submit" name="submit" value="Post.">
        </div>
    </form>   
</div>
<?php
include "includes/footer.php";
?>

newPost():

function newPost()
{
    if(isset($_POST['submit']))
    {
        global $connection;

        $title = mysqli_real_escape_string($connection,$_POST['title']);
        $summary = mysqli_real_escape_string($connection,$_POST['summary']);
        $content = mysqli_real_escape_string($connection,$_POST['content']);
        $category = $_POST['category'];
        $pubDate = date("Y-m-d H:i:s");
        $author = $_SESSION['user'];
        //Permalink
        $link = strtolower(trim($title));
        $link = preg_replace('/[^a-z0-9-]/', '-', $link);
        $link = preg_replace('/-+/', "-", $link);
        $link = rtrim($link, '-');
        $link = preg_replace('/\s+/', '-', $link);

        $query = "INSERT INTO database(title, permalink, category, summary, content, pubDate, author) ";
        $query .= "VALUES ('$title', '$link', '$category', '$summary', '$content', '$pubDate', '$author')";

        $result = $connection->query($query);
        if(!$result)
        {
            die('Query FAILED!' . mysqli_error());
        }
        else
        {
            header("Location: /");
        }
        $result->close();
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
P01y6107
  • 69
  • 9
  • I'm no php whizz but does that code GET a variable called ID from the user submitted form data, concatenate it straight into a database query and run the query? – Caius Jard Apr 27 '20 at 04:49
  • what debugging have you done? Are you certain your update query runs? Does the if isset evaluate to true etc? – Caius Jard Apr 27 '20 at 04:52
  • If edit does the update correctly you are sent back to the root home page (which I suppose is where your form is). --> header("Location: /"); – bestprogrammerintheworld Apr 27 '20 at 04:55
  • @bestprogrammerintheworld - it's apparently not doing the update correctly. The form is in editPost.php and that's not the root home page. When I click the post button it just refreshes editPost.php and removes all values from the fields. – P01y6107 Apr 27 '20 at 05:02
  • @CaiusJard I haven't been able to check if the query runs - fighting with my host to get access to logs. And there's no problem with the ID variable in itself - the code is getting the correct one, that much I've debugged. – P01y6107 Apr 27 '20 at 05:02
  • echo out the $query and do the query manually via phpmyadmin or similar? Does this work locally? – bestprogrammerintheworld Apr 27 '20 at 05:06
  • @bestprogrammerintheworld the query works great via phpmyadmin. Unfortunately XD - would have been nice though ;) – P01y6107 Apr 27 '20 at 05:11
  • I just added an "else echo "SOMETHING WENT WRONG" at the end of editPost() and guess what? Something went wrong. So the error is in _POST.... – P01y6107 Apr 27 '20 at 05:33
  • 1
    Indeed, now we're getting to basic debugging; pipping print statements into the page so you can tell where the code went as it ran, and what variables are set to. The next level is having a system where you can step through the code line by line as it runs and looks at the variable values and find out what the flow is and why. Consider using a better development environment than your current one https://stackoverflow.com/questions/2479776/is-there-an-ide-for-php-where-you-can-set-breakpoints-and-step-into-the-code – Caius Jard Apr 27 '20 at 05:57
  • 1
    Open your browser developers tools and see exactly what the browser is sending in the form data. Does it even contain a submit field? You've hung all the edit code on the fact that it does and only just put an else in to discover that it might not - so now is the time to look at whether that whole isset logic is the right thing to do (I mean; why have it at all? Does editPost ever get called if it's not a POST? How?). Also, why do you have two global connection statements? – Caius Jard Apr 27 '20 at 06:01
  • @CaiusJard - I'll try one of those IDEs and see how stepping will work for this. Not 100% sure how to answer your other questions. Other than finding out that no data is getting to $_POST (it's empty) I'm not sure WHY it's empty. As far as why I have two global connection statements - well both these functions were just one function earlier today when I started debugging - I seperated them to make things easier to read - since editPost() is pretty much identical to createPost() – P01y6107 Apr 27 '20 at 06:05
  • 1
    Suggest to press F12 in the browser and check that data really is being posted as you expect, then look at PHP to see if it really is being lost. Is it all being lost? Or just this one variable 'submit'. How does PHP know to call editPost upon a POST? – Caius Jard Apr 27 '20 at 06:18
  • @CaiusJard I'm trying to figure out how to debug with F12 (Firefox), so patience ;) print_r($_POST) is showing an empty array, so nothing is getting posted when I click the button. editPost.php has the form in it, it's calling itself upon submit (
    ) and should be using the function editPost() to process - but that again is showing that $_POST is an empty array
    – P01y6107 Apr 27 '20 at 06:24
  • Just edited the original post to include newPost.php and the function newPost() - which work FINE – P01y6107 Apr 27 '20 at 06:31
  • 1
    If you Press F12 in firefox, go on Network tab, make the POST, click the line that says POST in the grid, then choose Params on the right you can see what data firefox submitted – Caius Jard Apr 27 '20 at 07:20
  • 1
    The only thing that looks like a significant difference in a sidebyside between working and not working is that the not working version includes a header file before it does the db stuff, whereas the working thing includes it after. Does the header file damage the post data in some way? Side by side view: https://i.stack.imgur.com/fTfZz.png – Caius Jard Apr 27 '20 at 07:30
  • I've found the problem - and funny enough, it's not my php. It's my .htaccess, so I'm fighting with that now. mysite.com/editPost.php?id=1 is actually mysite.com/edit/1 - running the long form WORKS, the short form is giving me the error. My .htaccess has RewriteRule ^edit/([^/.]+)?$ /editPost?id=$1 [L] and I'm pretty sure that's the problem - somehow. – P01y6107 Apr 27 '20 at 08:03
  • Yep - that was the problem (rewrite rule). I just had to change
    to
    and it works no problem :-/ Thanks for your help @CaiusJard - I learned a lot!
    – P01y6107 Apr 27 '20 at 08:06

1 Answers1

0

thanks to everyone for their help. As I found out and stated in the comments, the problem was in my .htaccess

I do a rewrite in .htaccess - mysite.com/editPost.php?id=1 is actually mysite.com/edit/1 - running the long form WORKS, the short form is giving me the error.

My .htaccess has RewriteRule ^edit/([^/.]+)?$ /editPost?id=$1 [L] I just had to change <form action="editPost.php" method="post"> in editPost.php to <form action="edit" method="post"> and it works no problem :-/

P01y6107
  • 69
  • 9
  • 1
    Lastly, I implore you to address the concerns in the very first comment - you seem to take a value straight out of a text box on the internet, concatenate it into a db query and run it. Read [this](https://bobby-tables.com/) and [this](https://bobby-tables.com/php) and [this](https://coar.risc.anl.gov/consequences-of-sql-injection-attacks/) - I beseech you NOT to put this live until you've addressed this problem; putting this code live is asking to be hacked and have your entire site trashed or worse – Caius Jard Apr 27 '20 at 08:14
  • @CaiusJard can you be a bit more specific? I've tried to protect from all injections by using a $connection->real_escape_string on all input forms (the exception being 'category', which is a dropdown). Am I missing something else? Is it the prepare and bind that you're thinking I should use? – P01y6107 Apr 27 '20 at 10:38
  • 1
    @P01y6107: yes, prepared statements are the way to go. String escaping has a number of edge-cases that can slip through. – halfer Apr 27 '20 at 10:50
  • 1
    https://stackoverflow.com/questions/139199/can-i-protect-against-sql-injection-by-escaping-single-quote-and-surrounding-use – Caius Jard Apr 27 '20 at 10:51