Mitch
Mitch

Reputation: 183

PHP cURL - Illegal Characters Found in URL

I'm trying to force a download using the URL from the database. The URL from the database is a external URL.

Using cURL, I'm trying to check if the URL is still alive like so:

$id = strip_tags($_GET['dl']);

// grab stuff from db
$resource = $engine->runQuery("SELECT downloadurl, section FROM resources WHERE id=:id");
$resource->execute(array(':id'=>$id));
$row = $resource->fetch(PDO::FETCH_ASSOC);

// define memberonly sections
$memberonly = array(18, 7, 16, 19, 12);

if(in_array($row['section'], $memberonly)) {
    if($engine->isLoggedin()) {
        $dlurl = $row['downloadurl'];
        $filename = basename($dlurl);

        // curl lookup
        $curl = curl_init($dlurl);
        curl_setopt($curl, CURLOPT_NOBODY, true);
        curl_exec($curl);
        $retcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);

        if($retcode == 200) { // exists
            header('Content-Type: application/octet-stream');
            header("Content-Transfer-Encoding: Binary"); 
            header("Content-disposition: attachment; filename=\"" . $filename . "\""); 
            readfile($dlurl);
            exit;
        } elseif($retcode == 404) {
            echo 'File does not exist.';
        } else {
            echo 'Server is busy. Please try again later.';
        }
    } else {
        // head to root
        header('Location: /');
    }
}

cURL kept returning 0, so I used var_dump(curl_error($curl)); to see what the problem is. It outputs:

string(31) "Illegal characters found in URL"

This is what the database URL looks like:

http://gs2.ww.prod.dl.playstation.net/gs2/ppkgo/prod/CUSA00663_00/12/f_d2245740342e84367b73efbbf753a26de0aecbd69e6a494f1bdf4626cb52d3cc/f/UP0001-CUSA00663_00-AC5GAMEPS4000001-A0105-V0100_1.pkg

How can I resolve this?

Upvotes: 3

Views: 4207

Answers (2)

h2ooooooo
h2ooooooo

Reputation: 39532

Seeing as the file is 2.1 GB even with caching you'd have an insane first-time download time and your PHP would probably wait quite a while ((2.1 * 1024) / (100 / 8)) = at least 2.86 minutes at a 100 mbit/s connection + php overhead + hdd write time before even starting the file download for the user (as your server has to download it first).

Since you have an URL to the asset you're better off just forwarding the user there by using:

$url = 'http://gs2.ww.prod.dl.playstation.net/gs2/ppkgo/prod/CUSA00663_00/12/f_d2245740342e84367b73efbbf753a26de0aecbd69e6a494f1bdf4626cb52d3cc/f/UP0001-CUSA00663_00-AC5GAMEPS4000001-A0105-V0100_1.pkg';

header(sprintf('Location: %s', $url));
die();

Pros:

  • Download is MUCH faster for the user as they don't have to wait for your server to download the file first
  • You avoid using up your bandwidth (at LEAST 4.2 GB for the first user - first download then upload to the user)
  • PHP has way less overhead
  • You won't fill up your local server with cached files

Cons:

  • Your users can see the origin of the files (is this really an issue?)
  • They (playstation.net) will know the request came from you (they can see that in the referrer). You can use services like https://dereferer.me/ to avoid this, if you really need it.

It essentially makes the flow go from:

1. user
2.   your web server
3.     PHP
4.       playstation.net
5.     PHP
6.   your web server
7. user

to

1. user
2.   playstation.net
3. user

Upvotes: 1

Himel Rana
Himel Rana

Reputation: 666

Add this Line $dlurl = urlencode($dlurl);after $filename = basename($dlurl);

like below:

$dlurl = $row['downloadurl'];

$filename = basename($dlurl);

$dlurl = urlencode($dlurl);

Also try this to remove unexpected charecter from your url:

$dlurl  = str_replace(' ', '', $dlurl ); // remove spaces
$dlurl = str_replace("\t", '', $dlurl ); // remove tabs
$dlurl = str_replace("\n", '', $dlurl ); // remove new lines
$dlurl = str_replace("\r", '', $dlurl ); // remove carriage returns

final code can be like below:

$dlurl = $row['downloadurl'];
$dlurl  = str_replace(' ', '', $dlurl ); // remove spaces
$dlurl = str_replace("\t", '', $dlurl ); // remove tabs
$dlurl = str_replace("\n", '', $dlurl ); // remove new lines
$dlurl = str_replace("\r", '', $dlurl ); // remove carriage returns
$filename = basename($dlurl);

if you do this no need urlencode.

Upvotes: 4

Related Questions