summaryrefslogtreecommitdiffstats
path: root/lib/utils.php
blob: 7ad9f1929c7b8419031d68c936a910446432c5bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
/**
* ownCloud - News app
*
* @author Alessandro Cosentino
* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com>
*
* This file is licensed under the Affero General Public License version 3 or later.
* See the COPYING-README file
*
*/

namespace OCA\News;

// load SimplePie library
//TODO: is this a suitable place for the following require?
 require_once('news/3rdparty/SimplePie/autoloader.php');

class Utils {

	/**
	 * @brief Fetch a feed from remote
	 * @param url remote url of the feed
	 * @returns an instance of OC_News_Feed
	 */
	public static function fetch($url){
		$spfeed = new \SimplePie_Core();
		$spfeed->set_feed_url( $url );
		$spfeed->enable_cache( false );

		if (!$spfeed->init()) {
			return null;
		}

	   //I understand this try-catch sucks, but SimplePie gives weird errors sometimes
	   try {
		$spfeed->handle_content_type();
		$title = $spfeed->get_title();

		$items = array();
		if ($spitems = $spfeed->get_items()) {
			foreach($spitems as $spitem) {
				$itemUrl = $spitem->get_permalink();
				$itemTitle = $spitem->get_title();
				$itemGUID = $spitem->get_id();
				$itemBody = $spitem->get_content();
				$itemAuthor = $spitem->get_author();
				$item = new Item($itemUrl, $itemTitle, $itemGUID, $itemBody);
				if ($itemAuthor !== null) {
					$item->setAuthor($itemAuthor->get_name());
				}
				$items[] = $item;
			}
		}

		$feed = new Feed($url, $title, $items);

		$favicon = $spfeed->get_image_url();

		if ($favicon !== null) { // use favicon from feed
			if(self::checkFavicon($favicon))
				$feed->setFavicon($favicon);
		}
		else { // try really hard to find a favicon
			if( null !== ($webFavicon = self::discoverFavicon($url)) )
				$feed->setFavicon($webFavicon);
		}
		return $feed;
		}
	   catch (Exception $e) {
		return null;
	   }
	}

	public static function checkFavicon($favicon) {
		$file = new \SimplePie_File($favicon);
		// size in bytes
		$filesize = strlen($file->body);

		if($file->success && $filesize > 0 && $filesize < 50000) {
			$sniffer = new \SimplePie_Content_Type_Sniffer($file);
			if(substr($sniffer->get_type(), 0, 6) === 'image/') {
				return true;
			}
		}
		return false;
	}

	public static function discoverFavicon($url) {
		//try webroot favicon
		$favicon = \SimplePie_Misc::absolutize_url('/favicon.ico', $url);

		if(self::checkFavicon($favicon))
			return $favicon;

		//try to extract favicon from web page
		$absoluteUrl = \SimplePie_Misc::absolutize_url('/', $url);

		$handle = curl_init ( );
		curl_setopt ( $handle, CURLOPT_URL, $absoluteUrl );
		curl_setopt ( $handle, CURLOPT_RETURNTRANSFER, 1 );
		curl_setopt ( $handle, CURLOPT_FOLLOWLOCATION, TRUE );
		curl_setopt ( $handle, CURLOPT_MAXREDIRS, 10 );

		if ( FALSE!==($page=curl_exec($handle)) ) {
			preg_match ( '/<[^>]*link[^>]*(rel=["\']icon["\']|rel=["\']shortcut icon["\']) .*href=["\']([^>]*)["\'].*>/iU', $page, $match );
			if (1<sizeof($match)) {
				// the specified uri might be an url, an absolute or a relative path
				// we have to turn it into an url to be able to display it out of context
				$favicon = htmlspecialchars_decode ( $match[2] );
				// test for an url
				if (parse_url($favicon,PHP_URL_SCHEME)) {
					if(self::checkFavicon($favicon))
						return $favicon;
				}
				// test for an absolute path
				elseif ( 0===strpos(parse_url($favicon,PHP_URL_PATH),'/') ) {
					$url_token = parse_url($meta['final']);
					sprintf( '%s://%s/%s', $url_token['scheme'], $url_token['host'], $favicon );
					if(self::checkFavicon($favicon))
						return $favicon;
				}
				// so it appears to be a relative path
				else {
					$url_token = parse_url($meta['final']);
					sprintf( '%s://%s%s%s', $url_token['scheme'], $url_token['host'], dirname($url_token['path']), $favicon );
					if(self::checkFavicon($favicon))
						return $favicon;
				}
			}
		}
		return null;
	}
}