Skip to content

Instantly share code, notes, and snippets.

@eethann
Created October 1, 2009 20:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eethann/199208 to your computer and use it in GitHub Desktop.
Save eethann/199208 to your computer and use it in GitHub Desktop.
<?php
/**
* when twitpic URL is found in filtered $text, download the image file
* - use curl to get info from API on actual URL (w/ temporary auth key)
* - then use that URL to download the file to local $dl_dir
* @return downloaded file path or FALSE
*/
function _twitpic_filter_download_twitpic($pic_code) {
$pic_url = 'http://twitpic.com/show/full/' . $pic_code;
// get download directory
$dl_dir = variable_get('twitpic_filter_images_dir', file_directory_path()); // set in filter config
$dl_dir = trim($dl_dir, '\\/'); // clear trailing slash
// does the file already exist / already downloaded?
// PROBLEM: we don't know the file type at this point! only known from the API call...
// but don't want to run API call every time a pic is shown...
// workaround: the file convention is 'twitpic_CODE.TYPE' in $dl_dir - so look for 'twitpic_CODE.*'
// THIS ASSUMES PIC CODES ARE UNIQUE... THEY SHOULD BE, SINCE THAT'S ALL THAT ID'S THEM...
$check_exists = glob($dl_dir . '/twitpic_'.$pic_code.'*');
// (checking pattern from relative dir not realpath(), should be ok; otherwise have to strip prefix)
watson_debug($check_exists, 'check ' . realpath($dl_dir) . '/twitpic_'.$pic_code.'*');
if (!empty($check_exists)) { // at least 1 file exists
// weird scenario w/ >1 file found, shouldn't happen, but track just in case
if (sizeof($check_exists) > 1) {
drupal_set_message("More than one Twitpic file matching code {$pic_code} exists", 'warning');
watchdog('twitpic_filter', 'More than one Twitpic file matching code {$pic_code} exists: ' . watson_debug($check_exists,'',false), WATCHDOG_WARNING);
}
// path should now be in same format as if downloaded new
return array_shift($check_exists);
}
// doesn't exist yet...
// GET FILE INFO (ESP TYPE), THEN DOWNLOAD
$ch = curl_init($pic_url);
// (set these opts thru trial and error)
curl_setopt_array($ch, array(
CURLOPT_BINARYTRANSFER => 1,
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1, // follow redirects - key!
CURLOPT_TIMEOUT => 10, // too short? but don't want page to freeze b/c of this
CURLOPT_NOBODY => 1, // don't output anywhere
));
curl_exec($ch);
$info = curl_getinfo($ch); // xml converted to array
//drupal_set_message("info for $pic_url:" . watson_debug($info, '', false)); // DEBUGGING
curl_close($ch);
// get file info
// actual URL will be returned w/ auth key
if (!isset($info['url'])) {
watchdog('twitpic_filter', 'Unable to get file info for Twitpic #'.$pic_code, WATCHDOG_ERROR);
drupal_set_message('Twitpic Filter unable to get file info for Twitpic #'.$pic_code, 'error');
return FALSE;
}
$pic_url = $info['url']; // actual
if (! preg_match('|/photos/full/([0-9]*)\.(.{3,4})\?|i', $info['url'], $info_matches)) {
watchdog('twitpic_filter', 'Returned URL for Twitpic #'.$pic_code.' not in expected format', WATCHDOG_ERROR);
drupal_set_message('Returned URL for Twitpic #'.$pic_code.' not in expected format', 'error');
return FALSE;
}
// check file type
if (!isset($info_matches[2])) {
watchdog('twitpic_filter', 'No file type found for Twitpic #'.$pic_code, WATCHDOG_ERROR);
drupal_set_message('No file type found for Twitpic #'.$pic_code, 'error');
return FALSE;
}
$file_type = strtolower($info_matches[2]);
// validate file type
// @TODO should these be set in admin form?
if (! in_array($file_type, array('jpg', 'jpeg', 'png', 'gif'))) {
watchdog('twitpic_filter', 'Invalid file type found for Twitpic #'.$pic_code, WATCHDOG_ERROR);
drupal_set_message('Invalid file type found for Twitpic #'.$pic_code, 'error');
return FALSE;
}
// file type is good, download it...
// same convention as above -- see comment about file type
// (only now is file type known for sure)
$dl_file = $dl_dir . '/' . 'twitpic_'.$pic_code . '.' . $file_type; // relative to webroot
$dl_realpath = realpath($dl_file); // absolute
// running all these now w/ errors suppressed
// @TODO curl handle errors more gracefully?
@$ch = curl_init($pic_url); // reinitialize
@$fp = fopen($dl_realpath, "wb");
@curl_setopt_array($ch, array(
CURLOPT_FILE => $fp,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_TIMEOUT => 60,
));
@curl_exec($ch);
@curl_close($ch);
@fclose($fp);
// @TODO handle permission error?
// make sure file not empty
if (!file_exists($dl_realpath) or !filesize($dl_realpath)) {
watchdog('twitpic_filter', "Attempted to download twitpic '$pic_code' to $dl_realpath, but file is missing or empty.", WATCHDOG_ERROR);
drupal_set_message("Attempted to download twitpic '$pic_code' to $dl_file, but file is missing or empty.", 'error');
return FALSE;
}
drupal_set_message("Downloaded Twitpic '$pic_code' to $dl_file");
return $dl_file;
}
/**
* passed $text from the filter 'processing', find Twitpic URLs and replace with images
* @param $text passed from filter 'process' $op
* @param $format passed from filter, for checking per-filter configs (imagecache preset, etc)
* @return $text for output (changed or unchanged)
*/
function _twitpic_filter_put_pics($text, $format) { // called by 'process' $op of twitpic_filter_filter()
/**
* pattern: twitpic url w/ 5-digit code, not in html attribute (src or href),
* not w/ alphanumeric, slash, period, or quotations before or after
* (see testpattern.php)
*/
$twitpic_pattern = '#(?<![\'".a-zA-Z0-9/])(http://twitpic.com/([a-zA-Z0-9]{5}))(?![\'".a-zA-Z0-9/])#im';
if ($matchres===FALSE) { // regex ERROR
watchdog('twitpic_filter', 'Regex error', WATCHDOG_ERROR);
drupal_set_message('Regex error in Twitpic Filter.', 'error');
return $text;
}
// technically there can only be 1 twitpic per tweet (preg_match), but allow for many (preg_match_all) for other uses
elseif (preg_match_all($twitpic_pattern, $text, $matches, PREG_SET_ORDER)) {
// watson_debug($matches, 'all matches');
// $matches will be 2-D, each element having [0]=full match, [1]=URL, [2]=code (0=1 effectively)
foreach($matches as $match) {
// not sure if/when this scenario would occur, but check just in case
if (!isset($match[2])) {
watchdog('twitpic_filter', 'Twitpic match apparently found but missing code: '
. '<pre>'.print_r($match,true).'</pre>', WATCHDOG_WARNING);
drupal_set_message('Twitpic Filter unable to find an image code.', 'error', false);
}
else { // code found
$replace = $match[1]; // URL to replace w/ image
$pic_code = $match[2]; // twitpic image code to look for
// Download file or use existing if already downloaded
$pic_file = _twitpic_filter_download_twitpic($pic_code);
if (!empty($pic_file)) { // found/downloaded
$pic_url = url($pic_file, array('absolute'=>true));
// substitute plain URL w/ image
// @TODO pass this thru a theme hook, handle w/ imagecache if requested (by $format)
// temporary...
$replace_with = "<img src='{$pic_url}' width='300' />";
//$text .= watson_debug($match, '',false);
// just do a simple str_replace... case-sensitive should be fine
// (maybe even necessary - if twitpic codes are case-sensitive)
// - no $count limit here, will replace all, is that ok?
$text = str_replace($replace, $replace_with, $text);
// @TODO it's coming out as a link, maybe b/c turned into links by prior filters? need to resolve
// @TODO remove all the watson calls, message debugging
}
}
}
return $text; // breaks loop
} // for
return $text; // unchanged
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment