summaryrefslogtreecommitdiffstats
path: root/utility
diff options
context:
space:
mode:
authorBernhard Posselt <nukeawhale@gmail.com>2013-03-21 16:32:36 +0100
committerBernhard Posselt <nukeawhale@gmail.com>2013-03-21 16:32:36 +0100
commitac84b27965f5a1aec859e389f099fb844e33de46 (patch)
treec98d7aace90fcb442208349918a3e71cd9a7691a /utility
parentf475d882d0a76908400e9857f7e8a4ae8ad8a752 (diff)
reorganize folder
Diffstat (limited to 'utility')
-rw-r--r--utility/opmlexporter.php84
-rw-r--r--utility/utils.php208
2 files changed, 292 insertions, 0 deletions
diff --git a/utility/opmlexporter.php b/utility/opmlexporter.php
new file mode 100644
index 000000000..d9d404ff1
--- /dev/null
+++ b/utility/opmlexporter.php
@@ -0,0 +1,84 @@
+<?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;
+
+/**
+* Exports the OPML
+*/
+class OPMLExporter {
+
+ private $api;
+ private $trans;
+
+ public function __construct($api){
+ $this->api = $api;
+ $this->trans = $api->getTrans();
+ }
+
+
+ /**
+ * Generates the OPML for the active user
+ * @return the OPML as string
+ */
+ public function buildOPML($feeds){
+ $dom = new \DomDocument('1.0', 'UTF-8');
+ $dom->formatOutput = true;
+
+ $opml_el = $dom->createElement('opml');
+ $opml_el->setAttribute('version', '2.0');
+
+ $head_el = $dom->createElement('head');
+
+ $title = $this->api->getUserId() . ' ' .
+ $this->trans->t('subscriptions in ownCloud - News');
+ $title_el = $dom->createElement('title', $title);
+
+ $head_el->appendChild( $title_el );
+ $opml_el->appendChild( $head_el );
+ $body_el = $dom->createElement('body');
+
+ $this->feedsToXML($feeds, $body_el, $dom);
+
+ $opml_el->appendChild( $body_el );
+ $dom->appendChild( $opml_el );
+
+ return $dom->saveXML();
+ }
+
+
+ /**
+ * Creates the OPML content recursively
+ */
+ protected function feedsToXML($data, $xml_el, $dom) {
+
+ foreach($data as $collection) {
+ $outline_el = $dom->createElement('outline');
+ if ($collection instanceOf Folder) {
+ $outline_el->setAttribute('title', $collection->getName());
+ $outline_el->setAttribute('text', $collection->getName());
+ $this->feedsToXML($collection->getChildren(), $outline_el, $dom);
+ }
+ elseif ($collection instanceOf Feed) {
+ $outline_el->setAttribute('title', $collection->getTitle());
+ $outline_el->setAttribute('text', $collection->getTitle());
+ $outline_el->setAttribute('type', 'rss');
+ $outline_el->setAttribute('xmlUrl', $collection->getUrl());
+ }
+ $xml_el->appendChild( $outline_el );
+ }
+ }
+
+
+}
+
diff --git a/utility/utils.php b/utility/utils.php
new file mode 100644
index 000000000..560114ca7
--- /dev/null
+++ b/utility/utils.php
@@ -0,0 +1,208 @@
+<?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 Transform a date from UNIX timestamp format to MDB2 timestamp format
+ * @param dbtimestamp a date in the UNIX timestamp format
+ * @returns a date in the MDB2 timestamp format, or NULL if an error occurred
+ */
+ public static function unixtimeToDbtimestamp($unixtime) {
+ if ($unixtime === null) {
+ return null;
+ }
+ $dt = \DateTime::createFromFormat('U', $unixtime);
+ if ($dt === false) {
+ return null;
+ }
+ return $dt->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * @brief Transform a date from MDB2 timestamp format to UNIX timestamp format
+ * @param dbtimestamp a date in the MDB2 timestamp format
+ * @returns a date in the UNIX timestamp format, or NULL if an error occurred
+ */
+ public static function dbtimestampToUnixtime($dbtimestamp) {
+ if ($dbtimestamp === null) {
+ return null;
+ }
+ $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $dbtimestamp);
+ if ($dt === false) {
+ return null;
+ }
+ return $dt->format('U');
+ }
+
+ /**
+ * @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;
+ }
+
+ //temporary try-catch to bypass SimplePie bugs
+ 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();
+ $item = new Item($itemUrl, $itemTitle, $itemGUID, $itemBody);
+
+ $spAuthor = $spitem->get_author();
+ if ($spAuthor !== null) {
+ $item->setAuthor($spAuthor->get_name());
+ }
+
+ //date in Item is stored in UNIX timestamp format
+ $itemDate = $spitem->get_date('U');
+ $item->setDate($itemDate);
+
+ // associated media file, for podcasts
+ $itemEnclosure = $spitem->get_enclosure();
+ if($itemEnclosure !== null) {
+ $enclosureType = $itemEnclosure->get_type();
+ $enclosureLink = $itemEnclosure->get_link();
+ if(stripos($enclosureType, "audio/") !== FALSE) {
+ $enclosure = new Enclosure();
+ $enclosure->setMimeType($enclosureType);
+ $enclosure->setLink($enclosureLink);
+ $item->setEnclosure($enclosure);
+ }
+ }
+
+ $items[] = $item;
+ }
+ }
+
+ $feed = new Feed($url, $title, $items);
+
+ $favicon = $spfeed->get_image_url();
+
+ if ($favicon !== null && self::checkFavicon($favicon)) { // use favicon from feed
+ $feed->setFavicon($favicon);
+ }
+ else { // try really hard to find a favicon
+ $webFavicon = self::discoverFavicon($url);
+ if ($webFavicon !== null) {
+ $feed->setFavicon($webFavicon);
+ }
+ }
+ return $feed;
+ }
+ catch (Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * Perform a "slim" fetch of a feed from remote.
+ * Differently from Utils::fetch(), it doesn't retrieve items nor a favicon
+ *
+ * @param url remote url of the feed
+ * @returns an instance of OC_News_Feed
+ */
+ public static function slimFetch($url) {
+ $spfeed = new \SimplePie_Core();
+ $spfeed->set_feed_url( $url );
+ $spfeed->enable_cache( false );
+ $spfeed->set_stupidly_fast( true );
+
+ if (!$spfeed->init()) {
+ return null;
+ }
+
+ //temporary try-catch to bypass SimplePie bugs
+ try {
+ $title = $spfeed->get_title();
+
+ $feed = new Feed($url, $title);
+
+ return $feed;
+ }
+ catch (Exception $e) {
+ return null;
+ }
+ }
+
+ public static function checkFavicon($favicon) {
+ if ($favicon === null || $favicon == false)
+ return false;
+
+ $file = new \SimplePie_File($favicon);
+ // size in bytes
+ $filesize = strlen($file->body);
+
+ if($file->success && $filesize > 0 && $filesize < 50000) { //bigger files are not considered favicons
+ $sniffer = new \SimplePie_Content_Type_Sniffer($file);
+ if(substr($sniffer->get_type(), 0, 6) === 'image/') {
+ $imgsize = getimagesize($favicon);
+ if ($imgsize['0'] <= 32 && $imgsize['1'] <= 32) { //bigger images are not considered favicons
+ 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;
+ }
+ }
+ }
+ return null;
+ }
+} \ No newline at end of file