2

I made a nice simple userscript:
When I browse the web, I can "bookmark" any image in 1 click
My userscript

  1. Grab the img src
  2. Grab the url of the webpage
  3. Copy the .jpg .png .gif to my server

Everything works perfectly, BUT in some cases, the script cannot copy the file...
Actually the file is created but do not contains the img data, it only contains the content of an error webpage:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /data/x/xxx_xxx_x.jpg on this server.</p>
<p>Additionally, a 403 Forbidden
error was encountered while trying to use an ErrorDocument to handle the request.</p>
<hr>
<address>Apache Server at xxxxxxxx.net Port 80</address>
</body></html>

The "copy" code (php):

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $urlimg); 
curl_setopt($ch, CURLOPT_HEADER, false); 
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
set_time_limit(300); # 5 minutes for PHP 
curl_setopt($ch, CURLOPT_TIMEOUT, 300); # and also for CURL 
$path = $dirpix.'/'.$aa.'/'.$mm;
if ( ! is_dir($path)) {
    mkdir($path);
}
$outfile = fopen($path.'/'.$id.'.'.$ext, 'wb'); 
curl_setopt($ch, CURLOPT_FILE, $outfile); 
curl_exec($ch); 
fclose($outfile); 
curl_close($ch); 

Maybe the website blocks that kind of "copy" script? Thanks!

Havelock
  • 6,913
  • 4
  • 34
  • 42
jrm
  • 885
  • 5
  • 12
  • 20
  • 1
    Did you check the policies of the websites that returns the error message? It sounds to me like it would be some sort of [hotlinking prevention](http://blog.mark8t.com/2009/02/07/hotlink-prevention-how-to-stop-people-from-linking-to-your-images/) in place. – mariosangiorgio Sep 05 '12 at 16:28
  • nope, I can hotlink, no problem (the first version of my script did not copy the files, I just used hotlinks) – jrm Sep 05 '12 at 16:56

4 Answers4

1

2 things I can think of here are,

  1. Set a user agent to your curl request. Because from what you say, you are able to view the image but curl is getting 403 error, it could very well be userAgent filtering on server side.

  2. Add referer to your curl request. You can send the referer information from your userscript to the php script. You'd have to post or get window.location.href's value.

Prasanth
  • 5,230
  • 2
  • 29
  • 61
  • interesting... seems smart - I will try to do that and keep you posted, thanks – jrm Sep 06 '12 at 15:33
  • difficult to know if it changes anything cause I can't replicate the bug... but I add your very good ideas in my script - thanks! – jrm Sep 06 '12 at 15:58
  • You are welcome. Perhaps you could also look into another clever solution: convert the image to base64 string and send it to your server. see http://stackoverflow.com/questions/6150289/how-to-convert-image-into-base64-string-using-javascript – Prasanth Sep 06 '12 at 17:50
0

Try it below code it working fine in my server. it is tested code:-

<?php

$img[]='http://i.indiafm.com/stills/celebrities/sada/thumb1.jpg';
$img[]='http://i.indiafm.com/stills/celebrities/sada/thumb5.jpg';

$path="images/";


foreach($img as $i){
    save_image($i, $path);
    if(getimagesize($path.basename($i))){
        echo '<h3 style="color: green;">Image ' . basename($i) . ' Downloaded OK</h3>';
    }else{
        echo '<h3 style="color: red;">Image ' . basename($i) . ' Download Failed</h3>';
    }
}

//Alternative Image Saving Using cURL seeing as allow_url_fopen is disabled - bummer
function save_image($img,$fullpath='basename'){
    if($fullpath!='basename'){
        $fullpath = $fullpath.basename($img);
    }
    $ch = curl_init ($img);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
    $rawdata=curl_exec($ch);
    curl_close ($ch);
    if(file_exists($fullpath)){
        unlink($fullpath);
    }
    $fp = fopen($fullpath,'x');
    fwrite($fp, $rawdata);
    fclose($fp);
}
Abid Hussain
  • 7,724
  • 3
  • 35
  • 53
0

for correct work add

$agent= 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11';

curl_setopt($ch, CURLOPT_USERAGENT, $agent);
Deniska Axe
  • 154
  • 1
  • 4
0

I had a hard time to access my DLink camera using this method.

But finally I found the issue: authentication.

Don't forget authentication.

This is the solution that worked for me, thanks to all contributors.

    <?php

function download_image1($image_url, $image_file){
    $fp = fopen ($image_file, 'w+');              // open file handle

    $ch = curl_init($image_url);

$agent= 'Accept:image/jpeg,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11';

curl_setopt($ch, CURLOPT_USERAGENT, $agent);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,true);
curl_setopt($ch, CURLOPT_TIMEOUT, 400);
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
curl_setopt($ch, CURLOPT_REFERER, "http://google.com");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // Follows redirect responses.
curl_setopt($ch, CURLOPT_USERPWD, "user:password");

$raw=curl_exec($ch);
if ($raw === false) {
    trigger_error(curl_error($ch));
}

curl_close ($ch);
$localName = $image_file; // The file name of the source can be used locally       
if(file_exists($localName)){
    unlink($localName);
}

$fp = fopen($localName,'x'); 
fwrite($fp, $raw);
fclose($fp);

}

download_image1("http://url_here/image.jpg","/path/filename.jpg"); // to access DLink cameras
// be sure you have rights to the path
?>

The code above probably has some redundance, since I am openning fopen twice. To be honest, I won't correct, sinve it is working!