0

I am using a PHP form POST which puts data (into a Text file) into my SQL database and then the codes create a unique download link to be able to download the Text file from the SQL database. The connection to the SQL database works perfectly.
But all I`m getting is "We couldn't find the file to download."

The Form (index.php) whereby I input the data to be input into the Text File

    <form action="index2.php" method="POST">
    <input name="field1" type="text" />
    <input name="field2" type="text" />
    <input type="submit" name="submit" value="Save Data">
   </form>

Index2.php (This creates the Text File and inserts the details from the Form. It also creates the unique download link to download the file.)

<?php
if(isset($_POST['field1']) && isset($_POST['field2'])) {
    $data = $_POST['field1'] . '-' . $_POST['field2'] . "\n";
    $ret = file_put_contents('/tmp/mydata.txt', $data, FILE_APPEND | LOCK_EX);
}
else {
   die('no post data to process');
}
?>


<?php

//connect to the DB
$resDB = mysql_connect("xxx", "xxx", "xxx");
mysql_select_db("xxx", $resDB);

function createKey(){
    //create a random key
    $strKey = md5(microtime());

    //check to make sure this key isnt already in use
    $resCheck = mysql_query("SELECT count(*) FROM downloads WHERE downloadkey = '{$strKey}' LIMIT 1");
    $arrCheck = mysql_fetch_assoc($resCheck);
    if($arrCheck['count(*)']){
        //key already in use
        return createKey();
    }else{
        //key is OK
        return $strKey;
    }
}

//get a unique download key
$strKey = createKey();

//insert the download record into the database
mysql_query("INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', '{$ret}', '".(time()+(60*60*24*7))."')");

?>

<html>
    <head>
        <title>One Time Download Example</title>
    </head>
    <h1>One Time Download Example</h1>
    <p>Your unique download URL is:</p>
    <strong><a href="download.php?key=<?=$strKey;?>">download.php?key=<?=$strKey;?></a></strong>
    <p>This link will allow you to download the source code a single time within the next 7 days.</p>
</html>

Finally, download.php that checks everything and downloads the Text File from the database.

<?php

//The directory where the download files are kept - keep outside of the web document root
$strDownloadFolder = "/downloads/";

//If you can download a file more than once
$boolAllowMultipleDownload = 0;

//connect to the DB
$resDB = mysql_connect("xxx", "xxx", "xxx");
mysql_select_db("xxx", $resDB);

if(!empty($_GET['key'])){
    //check the DB for the key
    $resCheck = mysql_query("SELECT * FROM downloads WHERE downloadkey = '".mysql_real_escape_string($_GET['key'])."' LIMIT 1");
    $arrCheck = mysql_fetch_assoc($resCheck);
    if(!empty($arrCheck['file'])){
        //check that the download time hasnt expired
        if($arrCheck['expires']>=time()){
            if(!$arrCheck['downloads'] OR $boolAllowMultipleDownload){
                //everything is hunky dory - check the file exists and then let the user download it
                $strDownload = $strDownloadFolder.$arrCheck['file'];

                if(file_exists($strDownload)){

                    //get the file content
                    $strFile = file_get_contents($strDownload);

                    //set the headers to force a download
                    header("Content-type: application/force-download");
                    header("Content-Disposition: attachment; filename=\"".str_replace(" ", "_", $arrCheck['file'])."\"");

                    //echo the file to the user
                    echo $strFile;

                    //update the DB to say this file has been downloaded
                    mysql_query("UPDATE downloads SET downloads = downloads + 1 WHERE downloadkey = '".mysql_real_escape_string($_GET['key'])."' LIMIT 1");

                    exit;

                }else{
                    echo "We couldn't find the file to download.";
                }
            }else{
                //this file has already been downloaded and multiple downloads are not allowed
                echo "This file has already been downloaded.";
            }
        }else{
            //this download has passed its expiry date
            echo "This download has expired.";
        }
    }else{
        //the download key given didnt match anything in the DB
        echo "No file was found to download.";
    }
}else{
    //No download key wa provided to this script
    echo "No download key was provided. Please return to the previous page and try again.";
}

?>
Thomas
  • 11
  • Try var_dump('$strDownload') since that' seems to be the problem.. Your path is probably wrong.. – Naruto Oct 07 '16 at 10:22
  • Then clearly `file_exists($strDownload)` is false. What is the value of `$strDownload` when this happens? – David Oct 07 '16 at 10:22
  • Your script is at risk of [SQL Injection Attack](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) Have a look at what happened to [Little Bobby Tables](http://bobby-tables.com/) Even [if you are escaping inputs, its not safe!](http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string) Use [prepared parameterized statements](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php) – RiggsFolly Oct 07 '16 at 10:23
  • @David Thank you for pointing our the mistake. How can I assign the `$strDownload` to the file? Should I say it to `$strKey` – Thomas Oct 07 '16 at 10:24
  • @RiggsFolly I am using a unique download link with an Expire Time Limit. Also, the link works for only 1 download and there is a time limit for the link to expire. Is it still not safe? – Thomas Oct 07 '16 at 10:26
  • ok Thanks @RiggsFolly, I`ll go for another method then. – Thomas Oct 07 '16 at 10:27
  • `$strDownloadFolder = "/downloads/";` Did you mean to start that path with a `/` meaning start in root folder and look for a directory called `downloads` – RiggsFolly Oct 07 '16 at 10:27
  • Change to PDO. Heres a link to a guide about properly using PDO and it does not involve a lot of work. http://phpdelusions.net/pdo – DTH Oct 07 '16 at 10:27
  • You write the file to `/tmp/mydata.txt` but you use `$ret` which is a byte count from here `$ret = file_put_contents('/tmp/mydata.txt', $data, FILE_APPEND | LOCK_EX);` as the filename in your database. Look at the data you store in your database – RiggsFolly Oct 07 '16 at 10:33
  • I think you have coded yourself a large lump of nonsense! When you re-write the code to use PDO, better totally re-thing the process as well – RiggsFolly Oct 07 '16 at 10:35
  • 1
    @Thomas: Randomly guessing which variables may or may not hold the value you're looking for probably isn't going to get you very far. Do some debugging to find out what *actual values* you have. – David Oct 07 '16 at 10:46

0 Answers0