| 1 |
<?php
|
| 2 |
// $Id: feedapi_fav.module,v 1.3 2007/11/11 22:04:46 alexb Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implementation of hook_nodeapi().
|
| 6 |
*/
|
| 7 |
function feedapi_fav_nodeapi(&$node, $op, $teaser, $page) {
|
| 8 |
switch ($op) {
|
| 9 |
case 'insert':
|
| 10 |
case 'update':
|
| 11 |
if (feedapi_enabled($node->type)) {
|
| 12 |
// Only try to retrieve favicon if there is none stored for this feed.
|
| 13 |
// Todo: update favicons after a while.
|
| 14 |
if (!_feedapi_get_favicon($node->nid)) {
|
| 15 |
if ($node->feed->url) {
|
| 16 |
if ($fav_file_name = _feedapi_fav_retrieve_favicon($node->feed->url)) {
|
| 17 |
_feedapi_store_favicon($node->nid, $fav_file_name);
|
| 18 |
}
|
| 19 |
}
|
| 20 |
}
|
| 21 |
}
|
| 22 |
break;
|
| 23 |
// Todo: make this a CCK field.
|
| 24 |
case 'view':
|
| 25 |
if ($fav_file_name = _feedapi_get_favicon($node->nid)) {
|
| 26 |
$node->content['feedapi_favicon']['#value'] =
|
| 27 |
theme('feedapi_fav_favicon', _feedapi_fav_get_directory() . $fav_file_name);
|
| 28 |
}
|
| 29 |
break;
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
| 33 |
/**
|
| 34 |
* Get favicon for given node.
|
| 35 |
*/
|
| 36 |
function _feedapi_get_favicon($nid) {
|
| 37 |
return db_result(db_query('SELECT filename FROM {feedapi_fav} WHERE nid = %d', $nid));
|
| 38 |
}
|
| 39 |
|
| 40 |
/**
|
| 41 |
* Store favicon to db.
|
| 42 |
*/
|
| 43 |
function _feedapi_store_favicon($nid, $fav_file_name) {
|
| 44 |
db_query('DELETE FROM {feedapi_fav} WHERE nid = %d', $nid);
|
| 45 |
db_query('INSERT INTO {feedapi_fav} (nid, filename) VALUES(%d, "%s")', $nid, $fav_file_name);
|
| 46 |
}
|
| 47 |
|
| 48 |
/**
|
| 49 |
* Get storage directory for favicons.
|
| 50 |
* @return directory in which favicons will be stored.
|
| 51 |
*/
|
| 52 |
function _feedapi_fav_get_directory() {
|
| 53 |
return file_directory_path() .'/feedapi_fav/';
|
| 54 |
}
|
| 55 |
|
| 56 |
/**
|
| 57 |
* Retrieves and saves favicon to disk.
|
| 58 |
* Code largely from urlicon module.
|
| 59 |
*/
|
| 60 |
function _feedapi_fav_retrieve_favicon($url_str) {
|
| 61 |
// Define acceptable Content-Types
|
| 62 |
// Added text for text/plain Content-Type as that was returned from a test of www.nytimes.com
|
| 63 |
// Added text for application/octet-stream Content-Type as that was returned from a test of www.sourceforge.net
|
| 64 |
$ui_ctype = array('image/x-icon', 'application/octet-stream', 'text/plain', 'image/vnd.microsoft.icon');
|
| 65 |
$url = @parse_url($url_str);
|
| 66 |
// work only with host url here
|
| 67 |
$url_str = $url['scheme'] .'://'. $url['host'];
|
| 68 |
$domain = explode('.', $url['host']);
|
| 69 |
$domain = check_url(str_replace('.', '_', $url['host']));
|
| 70 |
|
| 71 |
//check if favicon exists locally
|
| 72 |
if ($url['host']) {
|
| 73 |
|
| 74 |
//check for favicon in metatags
|
| 75 |
$data = drupal_http_request(check_url($url_str));
|
| 76 |
|
| 77 |
if (preg_match('/<link[^>]+rel="(?:shortcut )?icon"[^>]+?href="([^"]+?)"/si', $data->data, $icons)) {
|
| 78 |
|
| 79 |
if (strpos($icons[1], '://')) {
|
| 80 |
// absolute path
|
| 81 |
$data = drupal_http_request(check_url($icons[1]));
|
| 82 |
}
|
| 83 |
else if (substr($icons[1], 0, 3) == '../') {
|
| 84 |
// relative path
|
| 85 |
$path = '';
|
| 86 |
$elements = explode('/', $url['path']);
|
| 87 |
$i = 0;
|
| 88 |
while (!strpos($elements[$i], '.') AND $i <= count($elements)) {
|
| 89 |
$path .= $elements[$i] .'/';
|
| 90 |
$i++;
|
| 91 |
}
|
| 92 |
|
| 93 |
$data = drupal_http_request(check_url($url['scheme'] .'://'. $url['host'] . $path . $icons[1]));
|
| 94 |
}
|
| 95 |
else if (substr($icons[1], 0, 1) == '/') {
|
| 96 |
// relative path
|
| 97 |
$data = drupal_http_request(check_url($url['scheme'] .'://'. $url['host'] . $icons[1]));
|
| 98 |
}
|
| 99 |
else {
|
| 100 |
// get favicon from webroot
|
| 101 |
$data = drupal_http_request(check_url('http://'. $url['host'] .'/favicon.ico'));
|
| 102 |
}
|
| 103 |
|
| 104 |
}
|
| 105 |
else {
|
| 106 |
// get favicon from webroot
|
| 107 |
$data = drupal_http_request(check_url('http://'. $url['host'] .'/favicon.ico'));
|
| 108 |
}
|
| 109 |
|
| 110 |
// Verify if the favicon was returned
|
| 111 |
if (($data->code == '200' OR $data->redirect_code == '200') AND ($data->headers['Content-Length'] > 0 OR $data->headers['Content-length'] > 0)) {
|
| 112 |
//check for acceptable Content-Type
|
| 113 |
//TODO: refactor code
|
| 114 |
$content_type_1 = explode(';', $data->headers['Content-Type']);
|
| 115 |
$content_type_2 = explode(';', $data->headers['Content-type']);
|
| 116 |
|
| 117 |
if (in_array($content_type_1[0], $ui_ctype) OR in_array($content_type_2[0], $ui_ctype)) {
|
| 118 |
// save favicon to file
|
| 119 |
$filename = $domain .'.ico';
|
| 120 |
$filepath = _feedapi_fav_get_directory() . $filename;
|
| 121 |
if (file_save_data($data->data, $filepath, FILE_EXISTS_REPLACE)) {
|
| 122 |
return $filename;
|
| 123 |
}
|
| 124 |
}
|
| 125 |
}
|
| 126 |
}
|
| 127 |
return FALSE;
|
| 128 |
}
|
| 129 |
|
| 130 |
/**
|
| 131 |
* Theming function for favicons.
|
| 132 |
*/
|
| 133 |
function theme_feedapi_fav_favicon($favicon_path) {
|
| 134 |
return '<img src="'. base_path() . $favicon_path .'" class="feedapi-favicon">';
|
| 135 |
}
|