WordPress.org

Ready to get started?Download WordPress

Forums

[Plugin: Hot Linked Image Cacher] great plugin, but can we make it MORE automatic? (8 posts)

  1. colchu
    Member
    Posted 5 years ago #

    it would be so awesome if images from every new post could be automatically cached, instead of having to run this script manually from time to time.

    what do you think?

    cc

  2. colchu
    Member
    Posted 5 years ago #

    hi there, i couldn't wait... so I hacked the plugin.

    Here it is in case anyone can use it.

    Every hotlinked image will automatically be cached upon posting.

    <?php
    /*
    Plugin Name: Hot Linked Image Cacher
    Plugin URI: http://www.linewbie.com/wordpress-plugins/
    Description: Goes through your posts and gives you the option to cache some or all hotlinked images locally in the upload folder of this plugin
    Version: 1.01
    Author: linewbie
    Author URI: http://www.linewbie.com
    WordPress Version Required: 1.5
    */
    
    /*
    Copyright (C) 2007 Linewbie.com
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */
    
    function hi_mkdirr($pathname, $mode = 0777) { // Recursive, Hat tip: PHP.net
    	// Check if directory already exists
    	if ( is_dir($pathname) || empty($pathname) )
    		return true;
    
    	// Ensure a file does not already exist with the same name
    	if ( is_file($pathname) )
    		return false;
    
    	// Crawl up the directory tree
    	$next_pathname = substr( $pathname, 0, strrpos($pathname, DIRECTORY_SEPARATOR) );
    	if ( hi_mkdirr($next_pathname, $mode) ) {
    		if (!file_exists($pathname))
    			return mkdir($pathname, $mode);
    	}
    
    	return false;
    }
    
    function hi_mm_ci_add_pages() {
    
    	add_management_page('Hot Linked Image Cacher Plugin', 'Hotlinked Image Cacher', 8, __FILE__,
    'hi_mm_ci_manage_page');
    }
    
    function hi_mm_ci_manage_page() {
    	global $wpdb;
    	$debug = 0;
    	$httppath = get_option('siteurl') . "/wp-content/plugins/hot-linked-image-cacher/upload";
    	$tophttp = get_option('siteurl');
    	if($debug==1){
    	echo $httppath." is the url for this site";
      }
    	$absoupload = ABSPATH . "/wp-content/plugins/hot-linked-image-cacher/upload";
    	if($debug==1) {
    		echo $absoupload . " is the absolute path";
    	}
    
    ?>
    <div class="wrap">
    <h2>Hotlinked Image Caching</h2>
    <?php if ( !isset($_POST['step']) ) : ?>
    <p>Here's how this plugin works:</p>
    
    <ol>
    <li>Enter the <b>post id</b> for the post you need to perform image cache on.</li>
    <li>If you need to perform image cache on all post, then put <b>all</b> in the post id field.</li>
    <li>Then you'll be presented with a list of domains, check the domains you want to grab the image from.</li>
    <li>The images will be copied to your upload directory (this directory is under your hot-linked-image-cacher plugin directory and must be writable).</li>
    <li>The img links in your posts will be updated to their new local url location automatically.</li>
    </ol>
    <form action="" method="post">
    <p class="submit">
    	<div align="left">
    	Choose from one of the following methods to grab remote image, <b>curl</b> is more secure. If your server support both method, choose <b>curl</b>.
    	The default will be using <b>curl</b>, you must choose <b>allow_url_fopen</b> if your server do not support <b>curl</b> but enabled <b>allow_url_fopen</b> in php.ini.
    
    	<input type="radio" name="urlmethod" value="curl" checked="checked"> <b>curl</b> (choose this method if your server support <b>curl</b>)
    	<input type="radio" name="urlmethod" value="allow_url_fopen"> <b>allow_url_fopen</b> (choose this method if your server allow remote fopen AND does not support <b>curl</b>) 
    
      </div>
    	Post ID: <input name="postid" type="text" id="postid" value="enter a post id here">
    	<input name="step" type="hidden" id="step" value="2">
    	<input type="submit" name="Submit" value="Get Started &raquo;" />
    </p>
    </form>
    <?php endif; ?>
    
    <?php
    $urlmethod = $_POST['urlmethod'];
    $postidnum = $_POST['postid'];
    if ('2' == $_POST['step']) : ?>
    <?php
    if ($postidnum == 'all' || $postidnum == 'All' || $postidnum == 'ALL' || $postidnum == 'enter a post id here') {
    $posts = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE post_content LIKE ('%<img%')");
    if ( !$posts )
    	die('No posts with images were found.');
    }
    else {
    $posts = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE ID LIKE $postidnum");
    if ( !$posts )
    	die('No posts with this Post ID were found.');
    }
    
    if($debug==1){
    	echo $postidnum." was the post ID chosen";
    }
    
    foreach ($posts as $post) :
    	preg_match_all('|<img.*?src=[\'"](.*?)[\'"].*?>|i', $post->post_content, $matches);
    
    	foreach ($matches[1] as $url) :
    			if($debug==1){
    			echo $url;
    			echo $httppath;
    		  }
    		  $op2 = stristr( $url, $tophttp );
    			if ( $op2 === false ){
    				$msg = 'NOT LOCAL';
    				if($debug==1){
    				echo $msg;
    			  }
    			} else {
    				continue; // Already local
    			}
    		$url = parse_url($url);
    
    		$url['host'] = str_replace('www.', '', $url['host']);
    		$domains[$url['host']]++;
    	endforeach;
    
    endforeach;
    ?>
    <p>Check the domains that you want to grab images from:</p>
    <form action="" method="post">
    
    <ul>
    <?php
    if (!is_null($domains)) {
    foreach ($domains as $domain => $num) :
    ?>
    
    <li>
    		<label><input type="checkbox" name="domains[]" value="<?php echo $domain; ?>" /> <code><?php echo $domain; ?></code> (<?php echo $num; ?> images found)</label>
    	</li>
    <?php endforeach; } ?>
    </ul>
    <p class="submit">
    	<input name="urlmethod" type="hidden" id="urlmethod" value="<?php echo $urlmethod; ?>" />
    	<input name="postid" type="hidden" id="postid" value="<?php echo $postidnum; ?>" />
    	<input name="step" type="hidden" id="step" value="3" />
    	<input type="submit" name="Submit" value="Cache These Images &raquo;" />
    </p>
    </form>
    <?php endif; ?>
    
    <?php if ('3' == $_POST['step']) : ?>
    <?php
    $urlmethod = $_POST['urlmethod'];
    $postidnum = $_POST['postid'];
    if($debug==1){
    	echo $urlmethod." is the current url method";
    	echo $postidnum." is the current post ID";
    }
    if ( !isset($_POST['domains']) )
    	die("You didn't check any domains, did you change your mind?");
    if ( !is_writable($absoupload) )
    	die('Your upload folder is not writable, chmod 777 on the folder /wp-content/plugins/hot-linked-image-cacher/upload/');
    
    foreach ( $_POST['domains'] as $domain ) :
    	if($debug==1){
    	echo $postidnum." is the post ID chosen, now going to rewrite urls";
      }
    	if ($postidnum == 'all' || $postidnum == 'All' || $postidnum == 'ALL') {
    	$posts = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE post_content LIKE ('%<img%') AND post_content LIKE ('%$domain%')");
      }
    	else {
    	$posts = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE ID LIKE $postidnum");
      }
    ?>
    <h3><?php echo $domain; ?></h3>
    
    <ul>
    <?php
    	$retval = hi_mm_ci_do_cache($wpdb,$httppath,$absoupload,$posts,$urlmethod,$domain);
    	echo $retval;
    ?>
    </ul>
    <?php
    endforeach;
    ?>
    <h3>All done!</h3>
    <?php endif; ?>
    </div>
    <?php
    }
    
    function hi_mm_ci_do_cache($wpdb,$httppath,$absoupload,$posts,$urlmethod,$domain) {
    $retval = '';
    
    foreach ($posts as $post) :
    		preg_match_all('|<img.*?src=[\'"](.*?)[\'"].*?>|i', $post->post_content, $matches);
    		foreach ( $matches[1] as $url ) :
    		  $dummy5 = $url;
    		  $dummy2 = str_replace('http://', '', $url);
          $dummy3 = str_replace('//', '/', $dummy2);
          $dummy4 = 'http://'.$dummy3;
          $url = $dummy4;
    		  $op1 = stristr( $url, $tophttp);
    			if ( $op1 === false ){
    				$msg = 'NOT LOCAL';
    			} else {
    				continue; // Already local
    			}
    			$filename = str_replace('%20', 'spa', basename ( $url ));
    			$b        = parse_url( $url );
    
    			$domain = str_replace('www.', '', $b['host']);
    			$dir      = $absoupload . '/' . $domain . dirname ( $b['path'] );
    
    			hi_mkdirr( $dir );
    			$f        = fopen( $dir . '/' . $filename , 'w' );
    			if($urlmethod=="curl" || is_null($urlmethod)){
    			$url      = $b['scheme'] . '://' . $b['host'] . str_replace(' ', '%20', $b['path']) . $b['query'];
    			$ch = curl_init();
          $timeout = 5;
          curl_setopt($ch, CURLOPT_URL, $url);
    		  curl_setopt($ch, CURLOPT_HEADER, 0);
    		  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    		  curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    		  $img = curl_exec($ch);
    		  curl_close($ch);
    		  }
    		  else{
    			$img = file_get_contents( $b['scheme'] . '://' . $b['host'] . str_replace(' ', '%20', $b['path']) . $b['query'] );
    		  }
    
    			if ( $img ) {
    				fwrite( $f, $img );
    				fclose( $f );
    				$local = $httppath . '/' . $domain . dirname ( $b['path'] ) . "/$filename";
    				$wpdb->query("UPDATE $wpdb->posts SET post_content = REPLACE(post_content, '$dummy5', '$local');");
    				$retval .= "
    <li>Cached $url</li>
    ";
    				flush();
    			}
    		endforeach;
    	endforeach;
    
    	return $retval;
    
    }
    
    function hi_mm_ci_cache_now($post_ID) {
    
    	global $wpdb;
    
    	/* autosave and other things appear to bump the post_id */
    	  $sql_get_real_post_id = "SELECT post_parent FROM " . $wpdb->posts . " WHERE ID = " . $post_ID;
    	  $post_ID_answer = $wpdb->get_results($sql_get_real_post_id);
    	  if ($post_ID_answer[0]->post_parent != 0) {
    		$post_ID = $post_ID_answer[0]->post_parent;
    	  }
    	  /* now $post_ID is really correct */
    
    	$postidnum = $post_ID;
    	$httppath = get_option('siteurl') . "/wp-content/plugins/hot-linked-image-cacher/upload";
    	$absoupload = ABSPATH . "/wp-content/plugins/hot-linked-image-cacher/upload";
    	$posts = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE ID LIKE $postidnum");
    
    	$urlmethod = 'curl';
    
    	hi_mm_ci_do_cache($wpdb,$httppath,$absoupload,$posts,$urlmethod,$domain);
    
    }
    
    add_action('admin_menu', 'hi_mm_ci_add_pages');
    
    add_action ( 'save_post', 'hi_mm_ci_cache_now');
    
    ?>
  3. dilneiss88
    Member
    Posted 5 years ago #

    hi colchu

    thanks for the hack

    but we have a lil problem..

    if the image are hosted in our host, it still download the image creating a copy of the imagem :S

    dont want this.. download de image only if are on other host...

    help?

  4. colchu
    Member
    Posted 5 years ago #

    yeah I noticed that... have been meaning to fix but I don't really have time, and I've just been living with it. (it still works, your path just gets longer and longer). But obviously it makes a mess.

  5. dilneiss88
    Member
    Posted 5 years ago #

    i know a bit of php

    can u point me the place of php it download the image?

  6. ridesign
    Member
    Posted 5 years ago #

    has anyone modified the above code to get it working?

  7. hairdude
    Member
    Posted 5 years ago #

    I have cleaned up the code and rewrote a large portion to make it more bulletproof. I also fixed it so that all posts with hotlinked images are now automatically cached. After you activate the plugin, everything should work automatically (for new posts). For old posts, you still have the option to manually download images and cache them.

    This version will also properly cache images that are generated dynamically (example: http://www.domain.com/image.php?id=12345), instead of just grabbing "static" image files.

    Cached images are now stored in the wp-content/upload/HLIC directory (by default). The old cache location was in a directory under the plugin name. I changed the cache directory because I did not want my images to disappear if the plugin was deleted.

    Release 1.11 contains the above improvements and does not have any problems with local images or images that have already been cached. All local image references and previously cached images are ignored (i.e. it does not try to make copies of them and create super-long pathnames).

    If you notice any problems, please post them here.

  8. bekar09
    Member
    Posted 4 years ago #

    is there any way we can have the default wordpress directory structure? like 'year/month/date' blahblah. in this context I would like to know whether the plugin uses the core wordpress functions to store an image into the file system and thereby generate the attachment id for a particular image?

    i want to use have the default wordpress directory structure. help is much appreciated.

Topic Closed

This topic has been closed to new replies.

About this Topic