function tweetimport_import_twitter_feed($twitter_account) { require_once (ABSPATH . WPINC . '/class-feed.php'); $feed = new SimplePie(); $account_parts = explode ('/', $twitter_account['twitter_name'], 2); if ($twitter_account['account_type'] == 1): //Account is Favorites $feed->set_feed_url(str_replace('#=#USER#=#', $account_parts[0], TWEETIMPORT_API_FAVORITES_URL)); elseif ($twitter_account['account_type'] == 0 && count($account_parts) == 1): //User timeline $feed->set_feed_url(str_replace('#=#USER#=#', $account_parts[0], TWEETIMPORT_API_USER_TIMELINE_URL)); elseif ($twitter_account['account_type'] == 2 && count($account_parts) == 2): //Account is list $feed_url = str_replace('#=#USER#=#', $account_parts[0], TWEETIMPORT_API_LIST_URL); $feed_url = str_replace('#=#LIST#=#', $account_parts[1], $feed_url); $feed->set_feed_url($feed_url); else : return '<strong>ERROR: Account information not correct. Account type wrong?</strong>'; endif; $feed->set_useragent('Tweet Import http://skinju.com/wordpress/tweetimport'); $feed->set_cache_class('WP_Feed_Cache'); $feed->set_file_class('WP_SimplePie_File'); $feed->enable_cache(true); $feed->set_cache_duration (apply_filters('tweetimport_cache_duration', 880)); $feed->enable_order_by_date(false); $feed->init(); $feed->handle_content_type(); if ($feed->error()): return '<strong>ERROR: Feed Reading Error.</strong>'; endif; $rss_items = $feed->get_items(); $imported_count = 0; foreach ($rss_items as $item) { $item = apply_filters ('tweetimport_tweet_before_new_post', $item); //return false to stop processing an item. if (!$item) continue; $processed_description = $item->get_description(); //Get the twitter author from the beginning of the tweet text $twitter_author = trim(preg_replace("~^(\w+):(.*?)$~", "\\1", $processed_description)); if ($twitter_account['strip_name'] == 1): $processed_description = preg_replace("~^(\w+):(.*?)~i", "\\2", $processed_description); endif; if ($twitter_account['names_clickable'] == 1): $processed_description = preg_replace("~@(\w+)~", "<a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>", $processed_description); $processed_description = preg_replace("~^(\w+):~", "<a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>:", $processed_description); endif; if ($twitter_account['hashtags_clickable'] == 1): if ($twitter_account['hashtags_clickable_twitter'] == 1): $processed_description = preg_replace("/#(\w+)/", "<a href=\"http://search.twitter.com/search?q=\\1\" target=\"_blank\">#\\1</a>", $processed_description); else: $processed_description = preg_replace("/#(\w+)/", "<a href=\"" . skinju_get_tag_link("\\1") . "\">#\\1</a>", $processed_description); endif; endif; $processed_description = preg_replace("#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t< ]*)#", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $processed_description); $processed_description = preg_replace("#(^|[\n ])((www|ftp)\.[^ \"\t\n\r< ]*)#", "\\1<a href=\"http://\\2\" target=\"_blank\">\\2</a>", $processed_description); $new_post = array('post_title' => trim (substr (preg_replace("~{$account_parts[0]}: ~i", "", $item->get_title()), 0, 25) . '...'), 'post_content' => trim ($processed_description), 'post_date' => $item->get_date('Y-m-d H:i:s'), 'post_author' => $twitter_account['author'], 'post_category' => array($twitter_account['category']), 'post_status' => 'publish'); $new_post = apply_filters('tweetimport_new_post_before_create', $new_post); // Offer the chance to manipulate new post data. return false to skip if (!$new_post) continue; $new_post_id = wp_insert_post($new_post); $imported_count++; add_post_meta ($new_post_id, 'tweetimport_twitter_author', $twitter_author, true); add_post_meta ($new_post_id, 'tweetimport_date_imported', date ('Y-m-d H:i:s'), true); add_post_meta ($new_post_id, 'tweetimport_twitter_id', $item->get_id(), true); add_post_meta ($new_post_id, 'tweetimport_twitter_id', $item->get_id(), true); add_post_meta ($new_post_id, '_tweetimport_twitter_id_hash', $item->get_id(true), true); add_post_meta ($new_post_id, 'tweetimport_twitter_post_uri', $item->get_link(0)); add_post_meta ($new_post_id, 'tweetimport_author_avatar', $item->get_link(0, 'image')); preg_match_all ('~#([A-Za-z0-9_]+)(?=\s|\Z)~', $item->get_description(), $out); if ($twitter_account['add_tag']) $out[0][] = $twitter_account['add_tag']; wp_set_post_tags($new_post_id, implode (',', $out[0])); } return $imported_count; }
public function import($forceResync) { if (get_option('goodreads_user_id')) { if (!class_exists('SimplePie')) { require_once ABSPATH . WPINC . '/class-feed.php'; } $rss_source = sprintf(self::$apiurl, get_option('goodreads_user_id')); /* Create the SimplePie object */ $feed = new SimplePie(); /* Set the URL of the feed you're retrieving */ $feed->set_feed_url($rss_source); /* Tell SimplePie to cache the feed using WordPress' cache class */ $feed->set_cache_class('WP_Feed_Cache'); /* Tell SimplePie to use the WordPress class for retrieving feed files */ $feed->set_file_class('WP_SimplePie_File'); /* Tell SimplePie how long to cache the feed data in the WordPress database */ $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', get_option('reclaim_update_interval'), $rss_source)); /* Run any other functions or filters that WordPress normally runs on feeds */ do_action_ref_array('wp_feed_options', array(&$feed, $rss_source)); /* Initiate the SimplePie instance */ $feed->init(); /* Tell SimplePie to send the feed MIME headers */ $feed->handle_content_type(); if ($feed->error()) { parent::log(sprintf(__('no %s data', 'reclaim'), $this->shortname)); parent::log($feed->error()); } else { $data = self::map_data($feed); parent::insert_posts($data); update_option('reclaim_' . $this->shortname . '_last_update', current_time('timestamp')); } } else { parent::log(sprintf(__('%s user data missing. No import was done', 'reclaim'), $this->shortname)); } }
/** * Fetches and parses an RSS or Atom feed, and returns its items. * * Each element in the returned array will have the following keys: * * - **authors** – An array of the item’s authors, where each sub-element has the following keys: * - **name** – The author’s name * - **url** – The author’s URL * - **email** – The author’s email * - **categories** – An array of the item’s categories, where each sub-element has the following keys: * - **term** – The category’s term * - **scheme** – The category’s scheme * - **label** – The category’s label * - **content** – The item’s main content. * - **contributors** – An array of the item’s contributors, where each sub-element has the following keys: * - **name** – The contributor’s name * - **url** – The contributor’s URL * - **email** – The contributor’s email * - **date** – A {@link DateTime} object representing the item’s date. * - **dateUpdated** – A {@link DateTime} object representing the item’s last updated date. * - **permalink** – The item’s URL. * - **summary** – The item’s summary content. * - **title** – The item’s title. * * @param string $url The feed’s URL. * @param int $limit The maximum number of items to return. Default is 0 (no limit). * @param int $offset The number of items to skip. Defaults to 0. * @param string $cacheDuration Any valid [PHP time format](http://www.php.net/manual/en/datetime.formats.time.php). * * @return array|string The list of feed items. */ public function getFeedItems($url, $limit = 0, $offset = 0, $cacheDuration = null) { $items = array(); if (!extension_loaded('dom')) { Craft::log('Craft needs the PHP DOM extension (http://www.php.net/manual/en/book.dom.php) enabled to parse feeds.', LogLevel::Warning); return $items; } if (!$cacheDuration) { $cacheDuration = craft()->config->getCacheDuration(); } else { $cacheDuration = DateTimeHelper::timeFormatToSeconds($cacheDuration); } $feed = new \SimplePie(); $feed->set_feed_url($url); $feed->set_cache_location(craft()->path->getCachePath()); $feed->set_cache_duration($cacheDuration); $feed->init(); // Something went wrong. if ($feed->error()) { Craft: log('There was a problem parsing the feed: ' . $feed->error(), LogLevel::Warning); return array(); } foreach ($feed->get_items($offset, $limit) as $item) { $date = $item->get_date('U'); $dateUpdated = $item->get_updated_date('U'); $items[] = array('authors' => $this->_getItemAuthors($item->get_authors()), 'categories' => $this->_getItemCategories($item->get_categories()), 'content' => $item->get_content(true), 'contributors' => $this->_getItemAuthors($item->get_contributors()), 'date' => $date ? new DateTime('@' . $date) : null, 'dateUpdated' => $dateUpdated ? new DateTime('@' . $dateUpdated) : null, 'permalink' => $item->get_permalink(), 'summary' => $item->get_description(true), 'title' => $item->get_title(), 'enclosures' => $this->_getEnclosures($item->get_enclosures())); } return $items; }
function fetch_feed2($url) { require_once ABSPATH . WPINC . '/class-feed.php'; $feed = new SimplePie(); $feed->set_sanitize_class('WP_SimplePie_Sanitize_KSES'); // We must manually overwrite $feed->sanitize because SimplePie's // constructor sets it before we have a chance to set the sanitization class $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); $feed->set_cache_class('WP_Feed_Cache'); $feed->set_file_class('WP_SimplePie_File'); $feed->set_feed_url($url); $feed->force_feed(true); /** This filter is documented in wp-includes/class-feed.php */ $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url)); /** * Fires just before processing the SimplePie feed object. * * @since 3.0.0 * * @param object &$feed SimplePie feed object, passed by reference. * @param mixed $url URL of feed to retrieve. If an array of URLs, the feeds are merged. */ do_action_ref_array('wp_feed_options', array(&$feed, $url)); $feed->init(); $feed->handle_content_type(); if ($feed->error()) { return new WP_Error('simplepie-error', $feed->error()); } return $feed; }
public function addAction() { require_once PLUGIN_DIR . "/FeedImporter/libraries/SimplePie/simplepie.inc"; $feed = new SimplePie(); $varName = strtolower($this->_modelClass); $class = $this->_modelClass; $record = new FeedImporter_Feed(); //Need an id to work with the tags, so save it now, even though it might be sloppy/confusing $record->save(); if ($_GET['feed_url']) { $feed_url = $_GET['feed_url']; $debug = new stdClass(); $feed->set_feed_url($feed_url); // Run SimplePie. $feed->init(); $feed->handle_content_type(); if ($feed->error()) { $this->flash($feed->error()); //return here? } $debug->title = $feed->get_title(); $debug->description = $feed->get_description(); //Set up the tag configurations for the first import $import = new FeedImporter_Import(); $import->processFeedTags($feed, $record->id); $record->feed_url = $feed_url; $record->feed_title = $feed->get_title(); $record->feed_description = $feed->get_description(); } $record->save(); // Create a new FakeCron_Task for the feed $fc_task = new FakeCron_Task(); $fc_task->interval = 0; $fc_task->name = "Cron for feed " . $record->feed_title; $fc_task->plugin_class = "FeedImporter_FakeCronTask"; $fc_task->plugin_name = 'FeedImporter'; $fc_task->params = serialize(array($record->id)); $fc_task->save(); $record->task_id = $fc_task->id; $_POST['task_id'] = $fc_task->id; $this->view->assign(array($varName => $record)); try { if ($record->saveForm($_POST)) { $this->redirect->goto('browse'); } } catch (Omeka_Validator_Exception $e) { $this->flashValidationErrors($e); } catch (Exception $e) { $this->flash($e->getMessage()); } }
public function doImport() { _log("Feed Import Started at " . date('c')); $db = get_db(); $hasError = false; require_once PLUGIN_DIR . "/FeedImporter/libraries/SimplePie/simplepie.inc"; $this->fi_feed = $db->getTable('FeedImporter_Feed')->find($this->feed_id); $this->fi_tags = $db->getTable('FeedImporter_TagConfig')->findByFeedId($this->feed_id, true); if ($this->fi_feed->map_authors) { $this->authorsMap = unserialize($this->fi_feed->authors_map); } $sp_feed = new SimplePie(); $sp_feed->enable_cache(false); $sp_feed->set_feed_url($this->fi_feed->feed_url); $sp_feed->handle_content_type(); // Run SimplePie. $sp_feed->init(); if ($sp_feed->error()) { $hasError = true; $this->status = self::STATUS_FEED_ERRORS; $this->sp_error = $sp_feed->error(); $this->save(); return false; } if (!$hasError) { foreach ($sp_feed->get_items() as $sp_item) { if ($this->_needsImport($sp_item)) { $this->processItemTags($sp_item); $metadataArray = $this->buildFeedItemMetadata($sp_item); $elementTextsArray = $this->buildFeedItemElementTexts($sp_item); $newOmekaItem = insert_item($metadataArray, $elementTextsArray); $newImportedItem = new FeedImporter_ImportedItem(); $newImportedItem->item_id = $newOmekaItem->id; $newImportedItem->feed_id = $this->fi_feed->id; $newImportedItem->import_id = $this->id; $newImportedItem->sp_id = $sp_item->get_id(); $newImportedItem->save(); $this->_buildFeedItemItemTypeData($sp_item, $newOmekaItem); $license = $sp_item->get_link(0, 'license'); if ($this->fi_feed->import_media && !empty($license)) { $this->_doFileImportForItem($sp_item, $newOmekaItem); } } } } $this->status = self::STATUS_COMPLETED_IMPORT; $this->save(); return true; }
/** * Add a new feed to the database * * Adds the specified feed name and URL to the database. If no name is set * by the user, it fetches one from the feed. If the URL specified is a HTML * page and not a feed, it lets SimplePie do autodiscovery and uses the XML * url returned. * * @since 1.0 * * @param string $url URL to feed or website (if autodiscovering) * @param string $name Title/Name of feed * @param string $cat Category to add feed to * @return bool True if succeeded, false if failed */ public function add($url, $name = '', $cat = 'default') { if (empty($url)) { throw new Exception(_r("Couldn't add feed: No feed URL supplied"), Errors::get_code('admin.feeds.no_url')); } if (!preg_match('#https|http|feed#', $url)) { if (strpos($url, '://')) { throw new Exception(_r('Unsupported URL protocol'), Errors::get_code('admin.feeds.protocol_error')); } $url = 'http://' . $url; } require_once LILINA_INCPATH . '/contrib/simplepie/simplepie.inc'; $feed_info = new SimplePie(); $feed_info->set_useragent(LILINA_USERAGENT . ' SimplePie/' . SIMPLEPIE_BUILD); $feed_info->set_stupidly_fast(true); $feed_info->set_cache_location(get_option('cachedir')); $feed_info->set_favicon_handler(get_option('baseurl') . '/lilina-favicon.php'); $feed_info->set_feed_url($url); $feed_info->init(); $feed_error = $feed_info->error(); $feed_url = $feed_info->subscribe_url(); if (!empty($feed_error)) { throw new Exception(sprintf(_r("Couldn't add feed: %s is not a valid URL or the server could not be accessed. Additionally, no feeds could be found by autodiscovery."), $url), Errors::get_code('admin.feeds.invalid_url')); } if (empty($name)) { //Get it from the feed $name = $feed_info->get_title(); } $id = sha1($feed_url); $this->feeds[$id] = array('feed' => $feed_url, 'url' => $feed_info->get_link(), 'id' => $id, 'name' => $name, 'cat' => $cat, 'icon' => $feed_info->get_favicon()); $this->feeds[$id] = apply_filters('feed-create', $this->feeds[$id], $url); $this->save(); return array('msg' => sprintf(_r('Added feed "%1$s"'), $name), 'id' => $id); }
function get_rss_feed($url) { require_once ABSPATH . WPINC . '/class-feed.php'; $feed = new SimplePie(); $feed->set_sanitize_class('WP_SimplePie_Sanitize_KSES'); $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); $feed->set_useragent('Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36'); $feed->set_cache_class('WP_Feed_Cache'); $feed->set_file_class('WP_SimplePie_File'); $feed->set_feed_url($url); $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url)); do_action_ref_array('wp_feed_options', array(&$feed, $url)); $feed->init(); $feed->handle_content_type(); if ($feed->error()) { return new WP_Error('simplepie-error', $feed->error()); } return $feed; }
/** * Fetches and parses an RSS or Atom feed, and returns its items. * * Each element in the returned array will have the following keys: * * - **authors** – An array of the item’s authors, where each sub-element has the following keys: * - **name** – The author’s name * - **url** – The author’s URL * - **email** – The author’s email * - **categories** – An array of the item’s categories, where each sub-element has the following keys: * - **term** – The category’s term * - **scheme** – The category’s scheme * - **label** – The category’s label * - **content** – The item’s main content. * - **contributors** – An array of the item’s contributors, where each sub-element has the following keys: * - **name** – The contributor’s name * - **url** – The contributor’s URL * - **email** – The contributor’s email * - **date** – A {@link DateTime} object representing the item’s date. * - **dateUpdated** – A {@link DateTime} object representing the item’s last updated date. * - **permalink** – The item’s URL. * - **summary** – The item’s summary content. * - **title** – The item’s title. * * @param string $url The feed’s URL. * @param int $limit The maximum number of items to return. Default is 0 (no limit). * @param int $offset The number of items to skip. Defaults to 0. * @param string $cacheDuration Any valid [PHP time format](http://www.php.net/manual/en/datetime.formats.time.php). * * @return array|string The list of feed items. */ public function getFeedItems($url, $limit = 0, $offset = 0, $cacheDuration = null) { $items = array(); if (!extension_loaded('dom')) { Craft::log('Craft needs the PHP DOM extension (http://www.php.net/manual/en/book.dom.php) enabled to parse feeds.', LogLevel::Warning); return $items; } if (!$cacheDuration) { $cacheDuration = craft()->config->getCacheDuration(); } else { $cacheDuration = DateTimeHelper::timeFormatToSeconds($cacheDuration); } // Potentially long-running request, so close session to prevent session blocking on subsequent requests. craft()->session->close(); $feed = new \SimplePie(); $feed->set_feed_url($url); $feed->set_cache_location(craft()->path->getCachePath()); $feed->set_cache_duration($cacheDuration); $feed->init(); // Something went wrong. if ($feed->error()) { Craft::log('There was a problem parsing the feed: ' . $feed->error(), LogLevel::Warning); return array(); } foreach ($feed->get_items($offset, $limit) as $item) { // Validate the permalink $permalink = $item->get_permalink(); if ($permalink) { $urlModel = new UrlModel(); $urlModel->url = $item->get_permalink(); if (!$urlModel->validate()) { Craft::log('An item was omitted from the feed (' . $url . ') because its permalink was an invalid URL: ' . $permalink); continue; } } $date = $item->get_date('U'); $dateUpdated = $item->get_updated_date('U'); $items[] = array('authors' => $this->_getItemAuthors($item->get_authors()), 'categories' => $this->_getItemCategories($item->get_categories()), 'content' => $item->get_content(true), 'contributors' => $this->_getItemAuthors($item->get_contributors()), 'date' => $date ? new DateTime('@' . $date) : null, 'dateUpdated' => $dateUpdated ? new DateTime('@' . $dateUpdated) : null, 'permalink' => $item->get_permalink(), 'summary' => $item->get_description(true), 'title' => $item->get_title(), 'enclosures' => $this->_getEnclosures($item->get_enclosures())); } return $items; }
static function read($feed) { $parser = new SimplePie(); $parser->set_feed_url($feed); $parser->set_cache_location(storage_path() . '/cache'); $parser->set_cache_duration(100); $success = $parser->init(); $parser->handle_content_type(); if ($parser->error() || !$success) { return null; } else { return $parser->get_items(); } }
/** * Geonames Feeds GeoCoding (RSS to GEORSS) * Due to limitations, this returns only 20 items * * @param string location / address * @return string raw georss data */ function geocode_feed($feed_url = NULL) { $base_url = "http://" . GEOCODER_GEONAMES . "/rssToGeoRSS?"; // Only requests service if we have an user $geocode_username = Settings_Model::get_setting('feed_geolocation_user'); if ($feed_url && !empty($geocode_username)) { // First check to make sure geonames webservice is running $geonames_status = @remote::status($base_url); if ($geonames_status == "200") { // Successful $request_url = $base_url . "&feedUrl=" . urlencode($feed_url) . "&username=" . $geocode_username; } else { // Down perhaps?? Use direct feed $request_url = $feed_url; } $request = new HttpClient($request_url); if (!($georss = $request->execute($request_url))) { // If the request failed, something may be wrong with the GEOCODER_GEONAMES service return false; } //$georss = utf8_encode($georss); // Lez verify this we got a good reply from the geocoder before proceeding $data = new SimplePie(); $data->set_raw_data($georss); $data->init(); $data->handle_content_type(); // Feed no good - get outta here! if ($data->error()) { Kohana::log('error', $data->error() . $request_url); return false; } return trim($georss); } else { return false; } }
function powerpress_get_news($feed_url, $limit = 10) { include_once ABSPATH . WPINC . '/feed.php'; $rss = fetch_feed($feed_url); // If feed doesn't work... if (is_wp_error($rss)) { require_once ABSPATH . WPINC . '/class-feed.php'; // Try fetching the feed using CURL directly... $content = powerpress_remote_fopen($feed_url, false, array(), 3, false, true); if (!$content) { return false; } // Load the content in a fetch_feed object... $rss = new SimplePie(); $rss->set_sanitize_class('WP_SimplePie_Sanitize_KSES'); // We must manually overwrite $feed->sanitize because SimplePie's // constructor sets it before we have a chance to set the sanitization class $rss->sanitize = new WP_SimplePie_Sanitize_KSES(); $rss->set_cache_class('WP_Feed_Cache'); $rss->set_file_class('WP_SimplePie_File'); $rss->set_raw_data($content); $rss->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $feed_url)); do_action_ref_array('wp_feed_options', array(&$rss, $feed_url)); $rss->init(); $rss->set_output_encoding(get_option('blog_charset')); $rss->handle_content_type(); if ($rss->error()) { return false; } } $rss_items = $rss->get_items(0, $rss->get_item_quantity($limit)); // If the feed was erroneously if (!$rss_items) { $md5 = md5($this->feed); delete_transient('feed_' . $md5); delete_transient('feed_mod_' . $md5); $rss->__destruct(); unset($rss); $rss = fetch_feed($this->feed); $rss_items = $rss->get_items(0, $rss->get_item_quantity($num)); $rss->__destruct(); unset($rss); } return $rss_items; }
public function setCron() { $getUnique = $this->getAllFeedUrls(); if (!empty($getUnique)) { foreach ($getUnique as $feedTableData) { $feed_user_title = $feedTableData->feed_user_title; $feed_url = $feedTableData->feed_admin_url; $usercat = $feedTableData->feed_user_category; $feed_filter_type = $feedTableData->feed_filter_type; $favicon_icon = $feedTableData->feed_favicon; $feed = new SimplePie(); $feed->set_feed_url($feed_url); $feed->set_cache_location(APPPATH . '/cache'); $feed->set_output_encoding('ISO-8859-1'); $feed->init(); $feed->handle_content_type(); // Language $lang = $feed->get_language(); $language = isset($lang) ? $lang : 'en-us'; if ($feed->get_type() & SIMPLEPIE_TYPE_NONE) { $feed_type = 'Unknown'; } elseif ($feed->get_type() & SIMPLEPIE_TYPE_RSS_ALL) { $feed_type = 'RSS'; } elseif ($feed->get_type() & SIMPLEPIE_TYPE_ATOM_ALL) { $feed_type = 'Atom'; } elseif ($feed->get_type() & SIMPLEPIE_TYPE_ALL) { $feed_type = 'Supported'; } // Author if ($author = $feed->get_author()) { $feedAuthor = $author->get_name(); } else { $feedAuthor = ''; } if ($feed->error()) { die; } else { $feed_image_link = $feed->get_image_link(); $feed_image_url = $feed->get_image_url(); $feed_image_title = $feed->get_image_title(); $this->addFeeds($feed->get_items(0, 500), $feed_image_link, $feed_image_url, $feed_image_title, $usercat, $feed_url, $language, $feed_type, $feedAuthor, $feed_filter_type, $feed_user_title, $favicon_icon); } } } }
/** * Create a SimplePie object * @param string $url URL of the RSS feed to parse * @param integer $duration Length of the cache in minutes * @param string $cache_name Name of the cache directory within /cache * @return Object SimplePie object */ public function create($url, $duration = 180, $cache_name = '') { $feed = new SimplePie(); $feed->set_feed_url($url); // Load our own caching driver for SimplePie $feed->registry->call('Cache', 'register', array('ee', 'EE_SimplePie_Cache_driver')); // Establish the cache $feed->set_cache_location('ee:' . $cache_name); $feed->set_cache_duration($duration * 60); // Get parameter to seconds // Check to see if the feed was initialized, if so, deal with the type $success = $feed->init(); $feed->handle_content_type(); if ($success) { return $feed; } throw new Exception("RSS Parser Error: " . $feed->error()); }
/** * Add a new feed to the database * * Adds the specified feed name and URL to the database. If no name is set * by the user, it fetches one from the feed. If the URL specified is a HTML * page and not a feed, it lets SimplePie do autodiscovery and uses the XML * url returned. * * @since 1.0 * * @param string $url URL to feed or website (if autodiscovering) * @param string $name Title/Name of feed * @param string $cat Category to add feed to * @return bool True if succeeded, false if failed */ public function add($url, $name = '', $cat = 'default') { if (empty($url)) { throw new Exception(_r("Couldn't add feed: No feed URL supplied"), Errors::get_code('admin.feeds.no_url')); } if (!preg_match('#https|http|feed#', $url)) { if (strpos($url, '://')) { throw new Exception(_r('Unsupported URL protocol'), Errors::get_code('admin.feeds.protocol_error')); } $url = 'http://' . $url; } $reporting = error_reporting(); error_reporting(E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR); require_once LILINA_INCPATH . '/contrib/simplepie.class.php'; // Need this for LILINA_USERAGENT class_exists('HTTPRequest'); require_once LILINA_INCPATH . '/core/class-httprequest.php'; $feed_info = new SimplePie(); $feed_info->set_useragent(LILINA_USERAGENT . ' SimplePie/' . SIMPLEPIE_BUILD); $feed_info->set_stupidly_fast(true); $feed_info->set_cache_location(get_option('cachedir')); $feed_info->set_feed_url($url); $feed_info->init(); $feed_error = $feed_info->error(); $feed_url = $feed_info->subscribe_url(); if (!empty($feed_error)) { throw new Exception(sprintf(_r("Couldn't add feed: %s is not a valid URL or the server could not be accessed. Additionally, no feeds could be found by autodiscovery."), $url), Errors::get_code('admin.feeds.invalid_url')); } if (empty($name)) { //Get it from the feed $name = $feed_info->get_title(); } $id = sha1($feed_url); // Do a naive check to see if the feed already exists if ($this->get($id) !== false) { throw new Exception(_r("Couldn't add feed: you have already added that feed"), Errors::get_code('admin.feeds.feed_already_exists')); } $this->feeds[$id] = array('feed' => $feed_url, 'url' => $feed_info->get_link(), 'id' => $id, 'name' => $name, 'cat' => $cat, 'icon' => self::discover_favicon($feed_info, $id)); $this->feeds[$id] = apply_filters('feed-create', $this->feeds[$id], $url, $feed_info); $this->save(); error_reporting($reporting); return array('msg' => sprintf(_r('Added feed "%1$s"'), $name), 'id' => $id); }
public function getFeed($refresh = false) { require_once dirname(__FILE__) . "/../../autoloader.php"; $feed = new SimplePie(); $url = "http://www.pinterest.com/taivasogilvy/feed.rss"; $feed->set_feed_url($url); if ($refresh) { $feed->enable_cache(false); } else { $feed->set_cache_location($this->config->cacheFolder); $feed->set_cache_duration($this->config->cacheTime); } $feed->enable_order_by_date(false); $feed->init(); $feed->handle_content_type(); if ($feed->error()) { return false; } else { return $feed; } }
/** * Given the content of a page and its URL, returns an array of FeedItem objects (or false on failure) * @param $content * @param $url * @return array|bool */ function parseFeed($content, $url) { // Check for microformats if ($html = @\DOMDocument::loadHTML($content)) { try { $parser = new \Mf2\Parser($html, $url); $parsed_content = $parser->parse(); return $this->mf2FeedToFeedItems($parsed_content, $url); } catch (\Exception $e) { return false; } } // Try XML (RSS or Atom) $xml_parser = new \SimplePie(); $xml_parser->set_raw_data($content); $xml_parser->init(); if (!$xml_parser->error()) { return $this->xmlFeedToFeedItems($xml_parser->get_items(), $url); } return false; }
public function fetch_feed($url) { $cache_path = $this->app['resources']->getPath('cache') . '/simplepie'; if (!file_exists($cache_path)) { mkdir($cache_path, 0777, true); } $feed = new \SimplePie(); $feed->set_cache_location($cache_path); $feed->set_feed_url($url); $feed->init(); $feed->handle_content_type(); $error = $feed->error(); if ($error) { throw new \Exception($error); } $rv = array(); foreach ($feed->get_items() as $item) { $rv[] = array('feed' => $url, 'id' => $item->get_id(), 'url' => $item->get_permalink(), 'title' => $item->get_title(), 'description' => $item->get_description(), 'date' => $item->get_date('j F Y | g:i a')); } return $rv; }
public function getFeed($refresh = false) { require_once dirname(__FILE__) . "/../../autoloader.php"; $feed = new SimplePie(); $url = "http://taivasfi.blogspot.fi/feeds/posts/default"; $url = "http://blogi.taivas.fi/?feed=rss2"; $feed->set_feed_url($url); if ($refresh) { $feed->enable_cache(false); } else { $feed->set_cache_location($this->config->cacheFolder); $feed->set_cache_duration($this->config->cacheTime); } $feed->enable_order_by_date(false); $feed->init(); $feed->handle_content_type(); if ($feed->error()) { return false; } else { return $feed; } }
/** * Opens an RSS feed, parses and loads the contents. * * @param string $url The URL of the RSS feed * @param bool $nativeOrder If true, disable order by date to preserve native ordering * @param bool $force Force SimplePie to parse the feed despite errors * * @return object An object that encapsulates the feed contents and operations on those contents. * @throws FeedParserException If opening or parsing feed fails **/ public function parseFeed($url, $nativeOrder = false, $force = false) { require_once PATH_SYSTEM . '/vendors/SimplePie.php'; $feed = new SimplePie(); $feed->set_timeout($this->timeout); $feed->set_feed_url($url); $feed->enable_order_by_date(!$nativeOrder); $feed->force_feed($force); if ($this->cacheDuration != null) { $feed->set_cache_duration(intval($this->cacheDuration)); } if ($this->cacheDirectory != null) { $feed->set_cache_location($this->cacheDirectory); } if ($this->stripHtmlTags != null) { $feed->strip_htmltags($this->stripHtmlTags); } @$feed->init(); if ($err = $feed->error()) { throw new FeedParserException($err); } return $feed; }
private function GetRssItems($text) { // Make sure we have the cache location configured Kit::ClassLoader('file'); $file = new File($this->db); $file->EnsureLibraryExists(); // Parse the text template $matches = ''; preg_match_all('/\\[.*?\\]/', $text, $matches); Debug::LogEntry('audit', 'Loading SimplePie to handle RSS parsing'); // Use SimplePie to get the feed include_once '3rdparty/simplepie/autoloader.php'; $feed = new SimplePie(); $feed->set_cache_location($file->GetLibraryCacheUri()); $feed->set_feed_url(urldecode($this->GetOption('uri'))); $feed->set_cache_duration($this->GetOption('updateInterval', 3600) * 60); $feed->handle_content_type(); $feed->init(); if ($feed->error()) { Debug::LogEntry('audit', 'Feed Error: ' . $feed->error()); return array(); } // Store our formatted items $items = array(); foreach ($feed->get_items() as $item) { // Substitute for all matches in the template $rowString = $text; // Substitite foreach ($matches[0] as $sub) { $replace = ''; // Pick the appropriate column out if (strstr($sub, '|') !== false) { // Use the provided namespace to extract a tag list($tag, $namespace) = explode('|', $sub); $tags = $item->get_item_tags(str_replace(']', '', $namespace), str_replace('[', '', $tag)); $replace = is_array($tags) ? $tags[0]['data'] : ''; } else { // Use the pool of standard tags switch ($sub) { case '[Title]': $replace = $item->get_title(); break; case '[Description]': $replace = $item->get_description(); break; case '[Content]': $replace = $item->get_content(); break; case '[Copyright]': $replace = $item->get_copyright(); break; case '[Date]': $replace = $item->get_local_date(); break; case '[PermaLink]': $replace = $item->get_permalink(); break; case '[Link]': $replace = $item->get_link(); break; } } // Substitute the replacement we have found (it might be '') $rowString = str_replace($sub, $replace, $rowString); } $items[] = $rowString; } // Return the formatted items return $items; }
/** * @brief Process atom feed and update anything/everything we might need to update. * * $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or * might not) try and subscribe to it. * $datedir sorts in reverse order * * @param array $xml * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds. * @param $importer * The contact_record (joined to user_record) of the local user who owns this * relationship. It is this person's stuff that is going to be updated. * @param $contact * The person who is sending us stuff. If not set, we MAY be processing a "follow" activity * from an external network and MAY create an appropriate contact record. Otherwise, we MUST * have a contact record. * @param int $pass by default ($pass = 0) we cannot guarantee that a parent item has been * imported prior to its children being seen in the stream unless we are certain * of how the feed is arranged/ordered. * * With $pass = 1, we only pull parent items out of the stream. * * With $pass = 2, we only pull children (comments/likes). * * So running this twice, first with pass 1 and then with pass 2 will do the right * thing regardless of feed ordering. This won't be adequate in a fully-threaded * model where comments can have sub-threads. That would require some massive sorting * to get all the feed items into a mostly linear ordering, and might still require * recursion. */ function consume_feed($xml, $importer, &$contact, $pass = 0) { require_once 'library/simplepie/simplepie.inc'; if (!strlen($xml)) { logger('consume_feed: empty input'); return; } $feed = new SimplePie(); $feed->set_raw_data($xml); $feed->init(); if ($feed->error()) { logger('consume_feed: Error parsing XML: ' . $feed->error()); } $permalink = $feed->get_permalink(); // Check at the feed level for updated contact name and/or photo // process any deleted entries $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry'); if (is_array($del_entries) && count($del_entries) && $pass != 2) { foreach ($del_entries as $dentry) { $deleted = false; if (isset($dentry['attribs']['']['ref'])) { $mid = $dentry['attribs']['']['ref']; $deleted = true; if (isset($dentry['attribs']['']['when'])) { $when = $dentry['attribs']['']['when']; $when = datetime_convert('UTC', 'UTC', $when, 'Y-m-d H:i:s'); } else { $when = datetime_convert('UTC', 'UTC', 'now', 'Y-m-d H:i:s'); } } if ($deleted && is_array($contact)) { $r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1", dbesc(base64url_encode($mid)), dbesc($contact['xchan_hash']), intval($importer['channel_id'])); if ($r) { $item = $r[0]; if (!($item['item_restrict'] & ITEM_DELETED)) { logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG); drop_item($item['id'], false); } } } } } // Now process the feed if ($feed->get_item_quantity()) { logger('consume_feed: feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG); $items = $feed->get_items(); foreach ($items as $item) { $is_reply = false; $item_id = base64url_encode($item->get_id()); logger('consume_feed: processing ' . $item_id, LOGGER_DEBUG); $rawthread = $item->get_item_tags(NAMESPACE_THREAD, 'in-reply-to'); if (isset($rawthread[0]['attribs']['']['ref'])) { $is_reply = true; $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']); } if ($is_reply) { if ($pass == 1) { continue; } // Have we seen it? If not, import it. $item_id = base64url_encode($item->get_id()); $author = array(); $datarray = get_atom_elements($feed, $item, $author); if (!x($author, 'author_name') || $author['author_is_feed']) { $author['author_name'] = $contact['xchan_name']; } if (!x($author, 'author_link') || $author['author_is_feed']) { $author['author_link'] = $contact['xchan_url']; } if (!x($author, 'author_photo') || $author['author_is_feed']) { $author['author_photo'] = $contact['xchan_photo_m']; } $datarray['author_xchan'] = ''; if ($author['author_link'] != $contact['xchan_url']) { $x = import_author_unknown(array('name' => $author['author_name'], 'url' => $author['author_link'], 'photo' => array('src' => $author['author_photo']))); if ($x) { $datarray['author_xchan'] = $x; } } if (!$datarray['author_xchan']) { $datarray['author_xchan'] = $contact['xchan_hash']; } $datarray['owner_xchan'] = $contact['xchan_hash']; $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id'])); // Update content if 'updated' changes if ($r) { if (x($datarray, 'edited') !== false && datetime_convert('UTC', 'UTC', $datarray['edited']) !== $r[0]['edited']) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } update_feed_item($importer['channel_id'], $datarray); } continue; } $datarray['parent_mid'] = $parent_mid; $datarray['uid'] = $importer['channel_id']; logger('consume_feed: ' . print_r($datarray, true), LOGGER_DATA); $xx = item_store($datarray); $r = $xx['item_id']; continue; } else { // Head post of a conversation. Have we seen it? If not, import it. $item_id = base64url_encode($item->get_id()); $author = array(); $datarray = get_atom_elements($feed, $item, $author); if (is_array($contact)) { if (!x($author, 'author_name') || $author['author_is_feed']) { $author['author_name'] = $contact['xchan_name']; } if (!x($author, 'author_link') || $author['author_is_feed']) { $author['author_link'] = $contact['xchan_url']; } if (!x($author, 'author_photo') || $author['author_is_feed']) { $author['author_photo'] = $contact['xchan_photo_m']; } } if (!x($author, 'author_name') || !x($author, 'author_link')) { logger('consume_feed: no author information! ' . print_r($author, true)); continue; } $datarray['author_xchan'] = ''; if ($author['author_link'] != $contact['xchan_url']) { $x = import_author_unknown(array('name' => $author['author_name'], 'url' => $author['author_link'], 'photo' => array('src' => $author['author_photo']))); if ($x) { $datarray['author_xchan'] = $x; } } if (!$datarray['author_xchan']) { $datarray['author_xchan'] = $contact['xchan_hash']; } $datarray['owner_xchan'] = $contact['xchan_hash']; $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id'])); // Update content if 'updated' changes if ($r) { if (x($datarray, 'edited') !== false && datetime_convert('UTC', 'UTC', $datarray['edited']) !== $r[0]['edited']) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } update_feed_item($importer['channel_id'], $datarray); } continue; } $datarray['parent_mid'] = $item_id; $datarray['uid'] = $importer['channel_id']; if (!link_compare($author['owner_link'], $contact['xchan_url'])) { logger('consume_feed: Correcting item owner.', LOGGER_DEBUG); $author['owner_name'] = $contact['name']; $author['owner_link'] = $contact['url']; $author['owner_avatar'] = $contact['thumb']; } logger('consume_feed: author ' . print_r($author, true), LOGGER_DEBUG); logger('consume_feed: ' . print_r($datarray, true), LOGGER_DATA); $xx = item_store($datarray); $r = $xx['item_id']; continue; } } } }
function discover_by_url($url, $arr = null) { require_once 'library/HTML5/Parser.php'; $x = scrape_feed($url); if (!$x) { if (!$arr) { return false; } $network = $arr['network'] ? $arr['network'] : 'unknown'; $name = $arr['name'] ? $arr['name'] : 'unknown'; $photo = $arr['photo'] ? $arr['photo'] : ''; $addr = $arr['addr'] ? $arr['addr'] : ''; $guid = $url; } $profile = $url; logger('scrape_feed results: ' . print_r($x, true)); if ($x['feed_atom']) { $guid = $x['feed_atom']; } if ($x['feed_rss']) { $guid = $x['feed_rss']; } if (!$guid) { return false; } // try and discover stuff from the feeed require_once 'library/simplepie/simplepie.inc'; $feed = new SimplePie(); $level = 0; $x = z_fetch_url($guid, false, $level, array('novalidate' => true)); if (!$x['success']) { logger('probe_url: feed fetch failed for ' . $poll); return false; } $xml = $x['body']; logger('probe_url: fetch feed: ' . $guid . ' returns: ' . $xml, LOGGER_DATA); logger('probe_url: scrape_feed: headers: ' . $x['header'], LOGGER_DATA); // Don't try and parse an empty string $feed->set_raw_data($xml ? $xml : '<?xml version="1.0" encoding="utf-8" ?><xml></xml>'); $feed->init(); if ($feed->error()) { logger('probe_url: scrape_feed: Error parsing XML: ' . $feed->error()); } $name = unxmlify(trim($feed->get_title())); $photo = $feed->get_image_url(); $author = $feed->get_author(); if ($author) { if (!$name) { $name = unxmlify(trim($author->get_name())); } if (!$name) { $name = trim(unxmlify($author->get_email())); if (strpos($name, '@') !== false) { $name = substr($name, 0, strpos($name, '@')); } } if (!$profile && $author->get_link()) { $profile = trim(unxmlify($author->get_link())); } if (!$photo) { $rawtags = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo') { $photo = $elems['link'][0]['attribs']['']['href']; } } } } else { $item = $feed->get_item(0); if ($item) { $author = $item->get_author(); if ($author) { if (!$name) { $name = trim(unxmlify($author->get_name())); if (!$name) { $name = trim(unxmlify($author->get_email())); } if (strpos($name, '@') !== false) { $name = substr($name, 0, strpos($name, '@')); } } if (!$profile && $author->get_link()) { $profile = trim(unxmlify($author->get_link())); } } if (!$photo) { $rawmedia = $item->get_item_tags('http://search.yahoo.com/mrss/', 'thumbnail'); if ($rawmedia && $rawmedia[0]['attribs']['']['url']) { $photo = unxmlify($rawmedia[0]['attribs']['']['url']); } } if (!$photo) { $rawtags = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo') { $photo = $elems['link'][0]['attribs']['']['href']; } } } } } if ($poll === $profile) { $lnk = $feed->get_permalink(); } if (isset($lnk) && strlen($lnk)) { $profile = $lnk; } if (!$network) { $network = 'rss'; } if (!$name) { $name = notags($feed->get_description()); } if (!$guid) { return false; } $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($guid)); if ($r) { return true; } if (!$photo) { $photo = z_root() . '/images/rss_icon.png'; } $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_instance_url, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($guid), dbesc($guid), dbesc($pubkey), dbesc($addr), dbesc($profile), dbesc($name), dbesc($network), dbesc(z_root()), dbesc(datetime_convert())); $photos = import_xchan_photo($photo, $guid); $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($guid)); return true; }
/** * Update the feeds * */ function UpdateFeeds() { if (!is_dir('./tmp')) { mkdir('./tmp', 0777); } $feedData = array(); $lock = Lock("Update Feeds", false); if (isset($lock)) { // load the list of feeds require_once './settings/feeds.inc'; require_once './lib/simplepie.inc'; // loop through and update each one foreach ($feeds as $category => &$feedList) { $feedData[$category] = array(); foreach ($feedList as $feedSource => $feedUrl) { $feedUrl = trim($feedUrl); if (strlen($feedUrl)) { $feed = new SimplePie(); if ($feed) { $rawFeed = trim(http_fetch($feedUrl)); $feed->set_raw_data($rawFeed); $feed->enable_cache(false); $feed->init(); // try sanitizing the data if we have a problem parsing the feed if (strlen($feed->error())) { FixFeed($rawFeed); $feed->set_raw_data($rawFeed); $feed->enable_cache(false); $feed->init(); } foreach ($feed->get_items() as $item) { $dateStr = $item->get_date(DATE_RSS); if ($dateStr && strlen($dateStr)) { $date = strtotime($dateStr); if ($date) { // only include articles from the last 30 days $now = time(); $elapsed = 0; if ($now > $date) { $elapsed = $now - $date; } $days = (int) ($elapsed / 86400); if ($days <= 30) { // make sure we don't have another article from the exact same time while (isset($feedData[$category][$date])) { $date++; } $feedData[$category][$date] = array('source' => $feedSource, 'title' => $item->get_title(), 'link' => urldecode($item->get_permalink()), 'date' => $dateStr); } } } $item->__destruct(); } $feed->__destruct(); unset($feed); } } } if (count($feedData[$category])) { krsort($feedData[$category]); } } // save out the feed data file_put_contents('./tmp/feeds.dat', json_encode($feedData)); Unlock($lock); } }
/** * Get a specific RSS feed * * @param $url string/array URL of the feed or array of URL * @param $cache_duration timestamp cache duration (default DAY_TIMESTAMP) * * @return feed object **/ static function getRSSFeed($url, $cache_duration = DAY_TIMESTAMP) { global $CFG_GLPI; $feed = new SimplePie(); $feed->set_cache_location(GLPI_RSS_DIR); $feed->set_cache_duration($cache_duration); // proxy support if (!empty($CFG_GLPI["proxy_name"])) { $prx_opt = array(); $prx_opt[CURLOPT_PROXY] = $CFG_GLPI["proxy_name"]; $prx_opt[CURLOPT_PROXYPORT] = $CFG_GLPI["proxy_port"]; if (!empty($CFG_GLPI["proxy_user"])) { $prx_opt[CURLOPT_HTTPAUTH] = CURLAUTH_ANYSAFE; $prx_opt[CURLOPT_PROXYUSERPWD] = $CFG_GLPI["proxy_user"] . ":" . Toolbox::decrypt($CFG_GLPI["proxy_passwd"], GLPIKEY); } $feed->set_curl_options($prx_opt); } $feed->enable_cache(true); $feed->set_feed_url($url); $feed->force_feed(true); // Initialize the whole SimplePie object. Read the feed, process it, parse it, cache it, and // all that other good stuff. The feed's information will not be available to SimplePie before // this is called. $feed->init(); // We'll make sure that the right content type and character encoding gets set automatically. // This function will grab the proper character encoding, as well as set the content type to text/html. $feed->handle_content_type(); if ($feed->error()) { return false; } return $feed; }
function probe_url($url, $mode = PROBE_NORMAL) { require_once 'include/email.php'; $result = array(); if (!$url) { return $result; } $network = null; $diaspora = false; $diaspora_base = ''; $diaspora_guid = ''; $diaspora_key = ''; $has_lrdd = false; $email_conversant = false; $twitter = strpos($url, 'twitter.com') !== false ? true : false; $at_addr = strpos($url, '@') !== false ? true : false; if (!$twitter) { if (strpos($url, 'mailto:') !== false && $at_addr) { $url = str_replace('mailto:', '', $url); $links = array(); } else { $links = lrdd($url); } if (count($links)) { $has_lrdd = true; logger('probe_url: found lrdd links: ' . print_r($links, true), LOGGER_DATA); foreach ($links as $link) { if ($link['@attributes']['rel'] === NAMESPACE_ZOT) { $zot = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === NAMESPACE_DFRN) { $dfrn = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === 'salmon') { $notify = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === NAMESPACE_FEED) { $poll = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') { $hcard = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') { $profile = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') { $poco = unamp($link['@attributes']['href']); } if ($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') { $diaspora_base = unamp($link['@attributes']['href']); $diaspora = true; } if ($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') { $diaspora_guid = unamp($link['@attributes']['href']); $diaspora = true; } if ($link['@attributes']['rel'] === 'diaspora-public-key') { $diaspora_key = base64_decode(unamp($link['@attributes']['href'])); $pubkey = rsatopem($diaspora_key); $diaspora = true; } } // Status.Net can have more than one profile URL. We need to match the profile URL // to a contact on incoming messages to prevent spam, and we won't know which one // to match. So in case of two, one of them is stored as an alias. Only store URL's // and not webfinger user@host aliases. If they've got more than two non-email style // aliases, let's hope we're lucky and get one that matches the feed author-uri because // otherwise we're screwed. foreach ($links as $link) { if ($link['@attributes']['rel'] === 'alias') { if (strpos($link['@attributes']['href'], '@') === false) { if (isset($profile)) { if ($link['@attributes']['href'] !== $profile) { $alias = unamp($link['@attributes']['href']); } } else { $profile = unamp($link['@attributes']['href']); } } } } } elseif ($mode == PROBE_NORMAL) { // Check email $orig_url = $url; if (strpos($orig_url, '@') && validate_email($orig_url)) { $x = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", intval(local_user())); $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user())); if (count($x) && count($r)) { $mailbox = construct_mailbox_name($r[0]); $password = ''; openssl_private_decrypt(hex2bin($r[0]['pass']), $password, $x[0]['prvkey']); $mbox = email_connect($mailbox, $r[0]['user'], $password); if (!$mbox) { logger('probe_url: email_connect failed.'); } unset($password); } if ($mbox) { $msgs = email_poll($mbox, $orig_url); logger('probe_url: searching ' . $orig_url . ', ' . count($msgs) . ' messages found.', LOGGER_DEBUG); if (count($msgs)) { $addr = $orig_url; $network = NETWORK_MAIL; $name = substr($url, 0, strpos($url, '@')); $phost = substr($url, strpos($url, '@') + 1); $profile = 'http://' . $phost; // fix nick character range $vcard = array('fn' => $name, 'nick' => $name, 'photo' => avatar_img($url)); $notify = 'smtp ' . random_string(); $poll = 'email ' . random_string(); $priority = 0; $x = email_msg_meta($mbox, $msgs[0]); if (stristr($x->from, $orig_url)) { $adr = imap_rfc822_parse_adrlist($x->from, ''); } elseif (stristr($x->to, $orig_url)) { $adr = imap_rfc822_parse_adrlist($x->to, ''); } if (isset($adr)) { foreach ($adr as $feadr) { if (strcasecmp($feadr->mailbox, $name) == 0 && strcasecmp($feadr->host, $phost) == 0 && strlen($feadr->personal)) { $personal = imap_mime_header_decode($feadr->personal); $vcard['fn'] = ""; foreach ($personal as $perspart) { if ($perspart->charset != "default") { $vcard['fn'] .= iconv($perspart->charset, 'UTF-8//IGNORE', $perspart->text); } else { $vcard['fn'] .= $perspart->text; } } $vcard['fn'] = notags($vcard['fn']); } } } } imap_close($mbox); } } } } if ($mode == PROBE_NORMAL) { if (strlen($zot)) { $s = fetch_url($zot); if ($s) { $j = json_decode($s); if ($j) { $network = NETWORK_ZOT; $vcard = array('fn' => $j->fullname, 'nick' => $j->nickname, 'photo' => $j->photo); $profile = $j->url; $notify = $j->post; $pubkey = $j->pubkey; $poll = 'N/A'; } } } if (strlen($dfrn)) { $ret = scrape_dfrn($hcard ? $hcard : $dfrn); if (is_array($ret) && x($ret, 'dfrn-request')) { $network = NETWORK_DFRN; $request = $ret['dfrn-request']; $confirm = $ret['dfrn-confirm']; $notify = $ret['dfrn-notify']; $poll = $ret['dfrn-poll']; $vcard = array(); $vcard['fn'] = $ret['fn']; $vcard['nick'] = $ret['nick']; $vcard['photo'] = $ret['photo']; } } } if ($diaspora && $diaspora_base && $diaspora_guid) { if ($mode == PROBE_DIASPORA || !$notify) { $notify = $diaspora_base . 'receive/users/' . $diaspora_guid; $batch = $diaspora_base . 'receive/public'; } if (strpos($url, '@')) { $addr = str_replace('acct:', '', $url); } } if ($network !== NETWORK_ZOT && $network !== NETWORK_DFRN && $network !== NETWORK_MAIL) { if ($diaspora) { $network = NETWORK_DIASPORA; } elseif ($has_lrdd) { $network = NETWORK_OSTATUS; } $priority = 0; if ($hcard && !$vcard) { $vcard = scrape_vcard($hcard); // Google doesn't use absolute url in profile photos if (x($vcard, 'photo') && substr($vcard['photo'], 0, 1) == '/') { $h = @parse_url($hcard); if ($h) { $vcard['photo'] = $h['scheme'] . '://' . $h['host'] . $vcard['photo']; } } logger('probe_url: scrape_vcard: ' . print_r($vcard, true), LOGGER_DATA); } if ($twitter) { logger('twitter: setup'); $tid = basename($url); $tapi = 'https://api.twitter.com/1/statuses/user_timeline.rss'; if (intval($tid)) { $poll = $tapi . '?user_id=' . $tid; } else { $poll = $tapi . '?screen_name=' . $tid; } $profile = 'http://twitter.com/#!/' . $tid; $vcard['photo'] = 'https://api.twitter.com/1/users/profile_image/' . $tid; $vcard['nick'] = $tid; $vcard['fn'] = $tid . '@twitter'; } if (!x($vcard, 'fn')) { if (x($vcard, 'nick')) { $vcard['fn'] = $vcard['nick']; } } $check_feed = false; if ($twitter || !$poll) { $check_feed = true; } if (!isset($vcard) || !x($vcard, 'fn') || !$profile) { $check_feed = true; } if ($at_addr && !count($links)) { $check_feed = false; } if ($check_feed) { $feedret = scrape_feed($poll ? $poll : $url); logger('probe_url: scrape_feed ' . ($poll ? $poll : $url) . ' returns: ' . print_r($feedret, true), LOGGER_DATA); if (count($feedret) && ($feedret['feed_atom'] || $feedret['feed_rss'])) { $poll = x($feedret, 'feed_atom') ? unamp($feedret['feed_atom']) : unamp($feedret['feed_rss']); if (!x($vcard)) { $vcard = array(); } } if (x($feedret, 'photo') && !x($vcard, 'photo')) { $vcard['photo'] = $feedret['photo']; } require_once 'library/simplepie/simplepie.inc'; $feed = new SimplePie(); $xml = fetch_url($poll); logger('probe_url: fetch feed: ' . $poll . ' returns: ' . $xml, LOGGER_DATA); $a = get_app(); logger('probe_url: scrape_feed: headers: ' . $a->get_curl_headers(), LOGGER_DATA); $feed->set_raw_data($xml); $feed->init(); if ($feed->error()) { logger('probe_url: scrape_feed: Error parsing XML: ' . $feed->error()); } if (!x($vcard, 'photo')) { $vcard['photo'] = $feed->get_image_url(); } $author = $feed->get_author(); if ($author) { $vcard['fn'] = unxmlify(trim($author->get_name())); if (!$vcard['fn']) { $vcard['fn'] = trim(unxmlify($author->get_email())); } if (strpos($vcard['fn'], '@') !== false) { $vcard['fn'] = substr($vcard['fn'], 0, strpos($vcard['fn'], '@')); } $email = unxmlify($author->get_email()); if (!$profile && $author->get_link()) { $profile = trim(unxmlify($author->get_link())); } if (!$vcard['photo']) { $rawtags = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo') { $vcard['photo'] = $elems['link'][0]['attribs']['']['href']; } } } } else { $item = $feed->get_item(0); if ($item) { $author = $item->get_author(); if ($author) { $vcard['fn'] = trim(unxmlify($author->get_name())); if (!$vcard['fn']) { $vcard['fn'] = trim(unxmlify($author->get_email())); } if (strpos($vcard['fn'], '@') !== false) { $vcard['fn'] = substr($vcard['fn'], 0, strpos($vcard['fn'], '@')); } $email = unxmlify($author->get_email()); if (!$profile && $author->get_link()) { $profile = trim(unxmlify($author->get_link())); } } if (!$vcard['photo']) { $rawmedia = $item->get_item_tags('http://search.yahoo.com/mrss/', 'thumbnail'); if ($rawmedia && $rawmedia[0]['attribs']['']['url']) { $vcard['photo'] = unxmlify($rawmedia[0]['attribs']['']['url']); } } if (!$vcard['photo']) { $rawtags = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo') { $vcard['photo'] = $elems['link'][0]['attribs']['']['href']; } } } } } if (!$vcard['photo'] && strlen($email)) { $vcard['photo'] = avatar_img($email); } if ($poll === $profile) { $lnk = $feed->get_permalink(); } if (isset($lnk) && strlen($lnk)) { $profile = $lnk; } if (!x($vcard, 'fn')) { $vcard['fn'] = notags($feed->get_title()); } if (!x($vcard, 'fn')) { $vcard['fn'] = notags($feed->get_description()); } if (strpos($vcard['fn'], 'Twitter / ') !== false) { $vcard['fn'] = substr($vcard['fn'], strpos($vcard['fn'], '/') + 1); $vcard['fn'] = trim($vcard['fn']); } if (!x($vcard, 'nick')) { $vcard['nick'] = strtolower(notags(unxmlify($vcard['fn']))); if (strpos($vcard['nick'], ' ')) { $vcard['nick'] = trim(substr($vcard['nick'], 0, strpos($vcard['nick'], ' '))); } } if (!$network) { $network = NETWORK_FEED; } if (!$priority) { $priority = 2; } } } if (!x($vcard, 'photo')) { $a = get_app(); $vcard['photo'] = $a->get_baseurl() . '/images/person-175.jpg'; } if (!$profile) { $profile = $url; } // No human could be associated with this link, use the URL as the contact name if ($network === NETWORK_FEED && $poll && !x($vcard, 'fn')) { $vcard['fn'] = $url; } $vcard['fn'] = notags($vcard['fn']); $vcard['nick'] = str_replace(' ', '', notags($vcard['nick'])); $result['name'] = $vcard['fn']; $result['nick'] = $vcard['nick']; $result['url'] = $profile; $result['addr'] = $addr; $result['batch'] = $batch; $result['notify'] = $notify; $result['poll'] = $poll; $result['request'] = $request; $result['confirm'] = $confirm; $result['poco'] = $poco; $result['photo'] = $vcard['photo']; $result['priority'] = $priority; $result['network'] = $network; $result['alias'] = $alias; $result['pubkey'] = $pubkey; logger('probe_url: ' . print_r($result, true), LOGGER_DEBUG); return $result; }
public function processData(\IRequestObject $requestObject) { $objectId = $requestObject->getId(); $portlet = $portletObject = \steam_factory::get_object($GLOBALS["STEAM"]->get_id(), $objectId); //icon $referIcon = \Portal::getInstance()->getAssetUrl() . "icons/refer_white.png"; //reference handling $params = $requestObject->getParams(); if (isset($params["referenced"]) && $params["referenced"] == true) { $portletIsReference = true; $referenceId = $params["referenceId"]; } else { $portletIsReference = false; } $portletName = $portlet->get_attribute(OBJ_DESC); $this->getExtension()->addCSS(); $this->getExtension()->addJS(); //old bib include_once PATH_BASE . "koala-core/lib/bid/slashes.php"; //get content of portlet $content = $portlet->get_attribute("bid:portlet:content"); if (is_array($content) && count($content) > 0) { array_walk($content, "_stripslashes"); } else { $content = array(); } $portletInstance = \PortletRss::getInstance(); $portletPath = $portletInstance->getExtensionPath(); $num_items = isset($content["num_items"]) ? $content["num_items"] : 0; if (isset($content["address"])) { $feed = new \SimplePie(); $feed->set_cache_location(PATH_CACHE); $feed->set_feed_url(derive_url($content["address"])); $feed->init(); if ($num_items == 0) { $items = $feed->get_items(); } else { $items = array_slice($feed->get_items(), 0, $num_items); } } $desc_length = isset($content["desc_length"]) ? $content["desc_length"] : 0; if (isset($content["allow_html"])) { $allow_html = $content["allow_html"] == "checked" ? true : false; } else { $allow_html = false; } $UBB = new \UBBCode(); include_once PATH_BASE . "koala-core/lib/bid/derive_url.php"; $portletFileName = $portletPath . "/ui/html/index.html"; $tmpl = new \HTML_TEMPLATE_IT(); $tmpl->loadTemplateFile($portletFileName); $tmpl->setVariable("EDIT_BUTTON", ""); $tmpl->setVariable("PORTLET_ID", $portlet->get_id()); $tmpl->setVariable("RSS_NAME", $portletName); //refernce icon if ($portletIsReference) { $tmpl->setVariable("REFERENCE_ICON", "<img src='{$referIcon}'>"); } //popupmenu if (!$portletIsReference && $portlet->check_access_write($GLOBALS["STEAM"]->get_current_steam_user())) { $popupmenu = new \Widgets\PopupMenu(); $popupmenu->setData($portlet); $popupmenu->setNamespace("PortletRss"); $popupmenu->setElementId("portal-overlay"); $tmpl->setVariable("POPUPMENU", $popupmenu->getHtml()); } if ($portletIsReference && $portlet->check_access_write($GLOBALS["STEAM"]->get_current_steam_user())) { $popupmenu = new \Widgets\PopupMenu(); $popupmenu->setData($portlet); $popupmenu->setNamespace("Portal"); $popupmenu->setElementId("portal-overlay"); $popupmenu->setParams(array(array("key" => "sourceObjectId", "value" => $portlet->get_id()), array("key" => "linkObjectId", "value" => $referenceId))); $popupmenu->setCommand("PortletGetPopupMenuReference"); $tmpl->setVariable("POPUPMENU", $popupmenu->getHtml()); } if (sizeof($content) > 0) { if ($feed->error()) { $tmpl->setVariable("NOITEMSTEXT", "RSS-Ladefehler"); } else { if (count($items) == 0) { $tmpl->setVariable("NOITEMSTEXT", "RSS-Feed ist leer."); } else { foreach ($items as $item) { $tmpl->setCurrentBlock("BLOCK_RSS_ITEM"); if ($allow_html) { $itemtitle = $item->get_title(); $itemdesc = $item->get_description(); } else { $itemtitle = strip_tags($item->get_title()); $itemdesc = strip_tags($item->get_description()); } if ($desc_length == 0) { $itemdesc = ""; } else { if ($desc_length > 0 && strlen($itemdesc) > $desc_length) { $itemdesc = substr($itemdesc, 0, $desc_length) . "..."; } } $tmpl->setVariable("ITEMTITLE", $itemtitle); $tmpl->setVariable("ITEMDESC", $itemdesc); $tmpl->setVariable("ITEMURL", derive_url($item->get_permalink())); $tmpl->setVariable("LINK", ""); $tmpl->parse("BLOCK_RSS_ITEM"); } } } } else { $tmpl->setVariable("NOITEMSTEXT", "RSS-Feed nicht konfiguriert."); } $htmlBody = $tmpl->get(); $this->content = $htmlBody; //widgets $outputWidget = new \Widgets\RawHtml(); $outputWidget->setHtml($htmlBody); $outputWidget->addWidget(new \Widgets\PopupMenu()); $this->rawHtmlWidget = $outputWidget; }
// On désactive la mise en cache $simple->set_useragent('Mozilla/5.0 (compatible; SimplePie.org; simple.tuxfamily.org)'); // User-Agent propre à SRR $sqlite = new PDO('sqlite:core/private/data.db'); // On charge la base de données $query = $sqlite->query('SELECT id,url,last_check FROM feeds WHERE user_id=' . $sqlite->quote($_GET['uid'])); // On récupère la liste des flux $time = time(); while ($response = $query->fetch()) { if ($time > $response['last_check'] + 600) { $feed_id = $response['id']; $simple->set_feed_url($response['url']); $simple->init(); $simple->handle_content_type(); $error = 0; if ($simple->error()) { $error = 1; } foreach ($simple->get_items() as $item) { $title = $sqlite->quote(strip_tags($item->get_title())); $permalink = $sqlite->quote($item->get_permalink()); $date = strtotime($item->get_date()); if ($date < $response['last_check'] - 30) { // Si l'item lu date de 30 secondes avant la dernière recherche, on stoppe break; } $description = $sqlite->quote($item->get_content()); if (empty($description)) { $description = $sqlite->quote($item->get_description()); } $description = preg_replace('/(<(link|script|iframe|object|applet|embed).*?>[^<]*(<\\/(link|script|iframe|object|applet|embed).*?>)?)/i', '', $description);
/** * Build SimplePie object based on RSS or Atom feed from URL. * * @since 2.8 * * @param string $url URL to retrieve feed * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success */ function fetch_feed($url) { require_once ABSPATH . WPINC . '/class-feed.php'; $feed = new SimplePie(); $feed->set_feed_url($url); $feed->set_cache_class('WP_Feed_Cache'); $feed->set_file_class('WP_SimplePie_File'); $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 43200)); $feed->init(); $feed->handle_content_type(); if ($feed->error()) { return new WP_Error('simplepie-error', $feed->error()); } return $feed; }
function local_delivery($importer, $data) { $a = get_app(); logger(__FUNCTION__, LOGGER_TRACE); if ($importer['readonly']) { // We aren't receiving stuff from this person. But we will quietly ignore them // rather than a blatant "go away" message. logger('local_delivery: ignoring'); return 0; //NOTREACHED } // Consume notification feed. This may differ from consuming a public feed in several ways // - might contain email or friend suggestions // - might contain remote followup to our message // - in which case we need to accept it and then notify other conversants // - we may need to send various email notifications $feed = new SimplePie(); $feed->set_raw_data($data); $feed->enable_order_by_date(false); $feed->init(); if ($feed->error()) { logger('local_delivery: Error parsing XML: ' . $feed->error()); } // Check at the feed level for updated contact name and/or photo $name_updated = ''; $new_name = ''; $photo_timestamp = ''; $photo_url = ''; $contact_updated = ''; $rawtags = $feed->get_feed_tags(NAMESPACE_DFRN, 'owner'); // Fallback should not be needed here. If it isn't DFRN it won't have DFRN updated tags // if(! $rawtags) // $rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if ($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) { $name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']; $new_name = $elems['name'][0]['data']; // Manually checking for changed contact names if ($new_name != $importer['name'] and $new_name != "" and $name_updated <= $importer['name-date']) { $name_updated = date("c"); $photo_timestamp = date("c"); } } if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo' && $elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']) { if ($photo_timestamp == "") { $photo_timestamp = datetime_convert('UTC', 'UTC', $elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); } $photo_url = $elems['link'][0]['attribs']['']['href']; } } if ($photo_timestamp && strlen($photo_url) && $photo_timestamp > $importer['avatar-date']) { $contact_updated = $photo_timestamp; logger('local_delivery: Updating photo for ' . $importer['name']); require_once "include/Photo.php"; $photos = import_profile_photo($photo_url, $importer['importer_uid'], $importer['id']); q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'\n\t\t\tWHERE `uid` = %d AND `id` = %d AND NOT `self`", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($importer['importer_uid']), intval($importer['id'])); } if ($name_updated && strlen($new_name) && $name_updated > $importer['name-date']) { if ($name_updated > $contact_updated) { $contact_updated = $name_updated; } $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($importer['importer_uid']), intval($importer['id'])); $x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`", dbesc(notags(trim($new_name))), dbesc(datetime_convert()), intval($importer['importer_uid']), intval($importer['id']), dbesc(notags(trim($new_name)))); // do our best to update the name on content items if (count($r) and notags(trim($new_name)) != $r[0]['name']) { q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'", dbesc(notags(trim($new_name))), dbesc($r[0]['name']), dbesc($r[0]['url']), intval($importer['importer_uid']), dbesc(notags(trim($new_name)))); } } if ($contact_updated and $new_name and $photo_url) { poco_check($importer['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $importer['id'], $importer['importer_uid']); } // Currently unsupported - needs a lot of work $reloc = $feed->get_feed_tags(NAMESPACE_DFRN, 'relocate'); if (isset($reloc[0]['child'][NAMESPACE_DFRN])) { $base = $reloc[0]['child'][NAMESPACE_DFRN]; $newloc = array(); $newloc['uid'] = $importer['importer_uid']; $newloc['cid'] = $importer['id']; $newloc['name'] = notags(unxmlify($base['name'][0]['data'])); $newloc['photo'] = notags(unxmlify($base['photo'][0]['data'])); $newloc['thumb'] = notags(unxmlify($base['thumb'][0]['data'])); $newloc['micro'] = notags(unxmlify($base['micro'][0]['data'])); $newloc['url'] = notags(unxmlify($base['url'][0]['data'])); $newloc['request'] = notags(unxmlify($base['request'][0]['data'])); $newloc['confirm'] = notags(unxmlify($base['confirm'][0]['data'])); $newloc['notify'] = notags(unxmlify($base['notify'][0]['data'])); $newloc['poll'] = notags(unxmlify($base['poll'][0]['data'])); $newloc['sitepubkey'] = notags(unxmlify($base['sitepubkey'][0]['data'])); /** relocated user must have original key pair */ /*$newloc['pubkey'] = notags(unxmlify($base['pubkey'][0]['data'])); $newloc['prvkey'] = notags(unxmlify($base['prvkey'][0]['data']));*/ logger("items:relocate contact " . print_r($newloc, true) . print_r($importer, true), LOGGER_DEBUG); // update contact $r = q("SELECT photo, url FROM contact WHERE id=%d AND uid=%d;", intval($importer['id']), intval($importer['importer_uid'])); if ($r === false) { return 1; } $old = $r[0]; $x = q("UPDATE contact SET\n\t\t\t\t\tname = '%s',\n\t\t\t\t\tphoto = '%s',\n\t\t\t\t\tthumb = '%s',\n\t\t\t\t\tmicro = '%s',\n\t\t\t\t\turl = '%s',\n\t\t\t\t\tnurl = '%s',\n\t\t\t\t\trequest = '%s',\n\t\t\t\t\tconfirm = '%s',\n\t\t\t\t\tnotify = '%s',\n\t\t\t\t\tpoll = '%s',\n\t\t\t\t\t`site-pubkey` = '%s'\n\t\t\tWHERE id=%d AND uid=%d;", dbesc($newloc['name']), dbesc($newloc['photo']), dbesc($newloc['thumb']), dbesc($newloc['micro']), dbesc($newloc['url']), dbesc(normalise_link($newloc['url'])), dbesc($newloc['request']), dbesc($newloc['confirm']), dbesc($newloc['notify']), dbesc($newloc['poll']), dbesc($newloc['sitepubkey']), intval($importer['id']), intval($importer['importer_uid'])); if ($x === false) { return 1; } // update items $fields = array('owner-link' => array($old['url'], $newloc['url']), 'author-link' => array($old['url'], $newloc['url']), 'owner-avatar' => array($old['photo'], $newloc['photo']), 'author-avatar' => array($old['photo'], $newloc['photo'])); foreach ($fields as $n => $f) { $x = q("UPDATE `item` SET `%s`='%s' WHERE `%s`='%s' AND uid=%d", $n, dbesc($f[1]), $n, dbesc($f[0]), intval($importer['importer_uid'])); if ($x === false) { return 1; } } // TODO // merge with current record, current contents have priority // update record, set url-updated // update profile photos // schedule a scan? return 0; } // handle friend suggestion notification $sugg = $feed->get_feed_tags(NAMESPACE_DFRN, 'suggest'); if (isset($sugg[0]['child'][NAMESPACE_DFRN])) { $base = $sugg[0]['child'][NAMESPACE_DFRN]; $fsugg = array(); $fsugg['uid'] = $importer['importer_uid']; $fsugg['cid'] = $importer['id']; $fsugg['name'] = notags(unxmlify($base['name'][0]['data'])); $fsugg['photo'] = notags(unxmlify($base['photo'][0]['data'])); $fsugg['url'] = notags(unxmlify($base['url'][0]['data'])); $fsugg['request'] = notags(unxmlify($base['request'][0]['data'])); $fsugg['body'] = escape_tags(unxmlify($base['note'][0]['data'])); // Does our member already have a friend matching this description? $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1", dbesc($fsugg['name']), dbesc(normalise_link($fsugg['url'])), intval($fsugg['uid'])); if (count($r)) { return 0; } // Do we already have an fcontact record for this person? $fid = 0; $r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1", dbesc($fsugg['url']), dbesc($fsugg['name']), dbesc($fsugg['request'])); if (count($r)) { $fid = $r[0]['id']; // OK, we do. Do we already have an introduction for this person ? $r = q("select id from intro where uid = %d and fid = %d limit 1", intval($fsugg['uid']), intval($fid)); if (count($r)) { return 0; } } if (!$fid) { $r = q("INSERT INTO `fcontact` ( `name`,`url`,`photo`,`request` ) VALUES ( '%s', '%s', '%s', '%s' ) ", dbesc($fsugg['name']), dbesc($fsugg['url']), dbesc($fsugg['photo']), dbesc($fsugg['request'])); } $r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1", dbesc($fsugg['url']), dbesc($fsugg['name']), dbesc($fsugg['request'])); if (count($r)) { $fid = $r[0]['id']; } else { return 0; } $hash = random_string(); $r = q("INSERT INTO `intro` ( `uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked` )\n\t\t\tVALUES( %d, %d, %d, '%s', '%s', '%s', %d )", intval($fsugg['uid']), intval($fid), intval($fsugg['cid']), dbesc($fsugg['body']), dbesc($hash), dbesc(datetime_convert()), intval(0)); notification(array('type' => NOTIFY_SUGGEST, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $fsugg, 'link' => $a->get_baseurl() . '/notifications/intros', 'source_name' => $importer['name'], 'source_link' => $importer['url'], 'source_photo' => $importer['photo'], 'verb' => ACTIVITY_REQ_FRIEND, 'otype' => 'intro')); return 0; } $ismail = false; $rawmail = $feed->get_feed_tags(NAMESPACE_DFRN, 'mail'); if (isset($rawmail[0]['child'][NAMESPACE_DFRN])) { logger('local_delivery: private message received'); $ismail = true; $base = $rawmail[0]['child'][NAMESPACE_DFRN]; $msg = array(); $msg['uid'] = $importer['importer_uid']; $msg['from-name'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['name'][0]['data'])); $msg['from-photo'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['avatar'][0]['data'])); $msg['from-url'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])); $msg['contact-id'] = $importer['id']; $msg['title'] = notags(unxmlify($base['subject'][0]['data'])); $msg['body'] = escape_tags(unxmlify($base['content'][0]['data'])); $msg['seen'] = 0; $msg['replied'] = 0; $msg['uri'] = notags(unxmlify($base['id'][0]['data'])); $msg['parent-uri'] = notags(unxmlify($base['in-reply-to'][0]['data'])); $msg['created'] = datetime_convert(notags(unxmlify('UTC', 'UTC', $base['sentdate'][0]['data']))); dbesc_array($msg); $r = dbq("INSERT INTO `mail` (`" . implode("`, `", array_keys($msg)) . "`) VALUES ('" . implode("', '", array_values($msg)) . "')"); // send notifications. require_once 'include/enotify.php'; $notif_params = array('type' => NOTIFY_MAIL, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $msg, 'source_name' => $msg['from-name'], 'source_link' => $importer['url'], 'source_photo' => $importer['thumb'], 'verb' => ACTIVITY_POST, 'otype' => 'mail'); notification($notif_params); return 0; // NOTREACHED } $community_page = 0; $rawtags = $feed->get_feed_tags(NAMESPACE_DFRN, 'community'); if ($rawtags) { $community_page = intval($rawtags[0]['data']); } if (intval($importer['forum']) != $community_page) { q("update contact set forum = %d where id = %d", intval($community_page), intval($importer['id'])); $importer['forum'] = (string) $community_page; } logger('local_delivery: feed item count = ' . $feed->get_item_quantity()); // process any deleted entries $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry'); if (is_array($del_entries) && count($del_entries)) { foreach ($del_entries as $dentry) { $deleted = false; if (isset($dentry['attribs']['']['ref'])) { $uri = $dentry['attribs']['']['ref']; $deleted = true; if (isset($dentry['attribs']['']['when'])) { $when = $dentry['attribs']['']['when']; $when = datetime_convert('UTC', 'UTC', $when, 'Y-m-d H:i:s'); } else { $when = datetime_convert('UTC', 'UTC', 'now', 'Y-m-d H:i:s'); } } if ($deleted) { // check for relayed deletes to our conversation $is_reply = false; $r = q("select * from item where uri = '%s' and uid = %d limit 1", dbesc($uri), intval($importer['importer_uid'])); if (count($r)) { $parent_uri = $r[0]['parent-uri']; if ($r[0]['id'] != $r[0]['parent']) { $is_reply = true; } } if ($is_reply) { $community = false; if ($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) { $sql_extra = ''; $community = true; logger('local_delivery: possible community delete'); } else { $sql_extra = " and contact.self = 1 and item.wall = 1 "; } // was the top-level post for this reply written by somebody on this site? // Specifically, the recipient? $is_a_remote_delete = false; // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,\n\t\t\t\t\t\t`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`\n\t\t\t\t\t\tINNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\t\t\t\t\tWHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')\n\t\t\t\t\t\tAND `item`.`uid` = %d\n\t\t\t\t\t\t{$sql_extra}\n\t\t\t\t\t\tLIMIT 1", dbesc($parent_uri), dbesc($parent_uri), dbesc($parent_uri), intval($importer['importer_uid'])); if ($r && count($r)) { $is_a_remote_delete = true; } // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a // valid community comment. Also forum_mode makes it valid for sure. // If neither, it's not. if ($is_a_remote_delete && $community) { if (!$r[0]['forum_mode'] && !$r[0]['wall']) { $is_a_remote_delete = false; logger('local_delivery: not a community delete'); } } if ($is_a_remote_delete) { logger('local_delivery: received remote delete'); } } $r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN contact on `item`.`contact-id` = `contact`.`id`\n\t\t\t\t\tWHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['importer_uid']), intval($importer['id'])); if (count($r)) { $item = $r[0]; if ($item['deleted']) { continue; } logger('local_delivery: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG); if ($item['object-type'] === ACTIVITY_OBJ_EVENT) { logger("Deleting event " . $item['event-id'], LOGGER_DEBUG); event_delete($item['event-id']); } if ($item['verb'] === ACTIVITY_TAG && $item['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($item['object'], false); $xt = parse_xml_string($item['target'], false); if ($xt->type === ACTIVITY_OBJ_NOTE) { $i = q("select * from `item` where uri = '%s' and uid = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (count($i)) { // For tags, the owner cannot remove the tag on the author's copy of the post. $owner_remove = $item['contact-id'] == $i[0]['contact-id'] ? true : false; $author_remove = $item['origin'] && $item['self'] ? true : false; $author_copy = $item['origin'] ? true : false; if ($owner_remove && $author_copy) { continue; } if ($author_remove || $owner_remove) { $tags = explode(',', $i[0]['tag']); $newtags = array(); if (count($tags)) { foreach ($tags as $tag) { if (trim($tag) !== trim($xo->body)) { $newtags[] = trim($tag); } } } q("update item set tag = '%s' where id = %d", dbesc(implode(',', $newtags)), intval($i[0]['id'])); create_tags_from_item($i[0]['id']); } } } } if ($item['uri'] == $item['parent-uri']) { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',\n\t\t\t\t\t\t\t`body` = '', `title` = ''\n\t\t\t\t\t\t\tWHERE `parent-uri` = '%s' AND `uid` = %d", dbesc($when), dbesc(datetime_convert()), dbesc($item['uri']), intval($importer['importer_uid'])); create_tags_from_itemuri($item['uri'], $importer['importer_uid']); create_files_from_itemuri($item['uri'], $importer['importer_uid']); update_thread_uri($item['uri'], $importer['importer_uid']); } else { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',\n\t\t\t\t\t\t\t`body` = '', `title` = ''\n\t\t\t\t\t\t\tWHERE `uri` = '%s' AND `uid` = %d", dbesc($when), dbesc(datetime_convert()), dbesc($uri), intval($importer['importer_uid'])); create_tags_from_itemuri($uri, $importer['importer_uid']); create_files_from_itemuri($uri, $importer['importer_uid']); update_thread_uri($uri, $importer['importer_uid']); if ($item['last-child']) { // ensure that last-child is set in case the comment that had it just got wiped. q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); // who is the last child now? $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d\n\t\t\t\t\t\t\t\tORDER BY `created` DESC LIMIT 1", dbesc($item['parent-uri']), intval($importer['importer_uid'])); if (count($r)) { q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d", intval($r[0]['id'])); } } // if this is a relayed delete, propagate it to other recipients if ($is_a_remote_delete) { proc_run('php', "include/notifier.php", "drop", $item['id']); } } } } } } foreach ($feed->get_items() as $item) { $is_reply = false; $item_id = $item->get_id(); $rawthread = $item->get_item_tags(NAMESPACE_THREAD, 'in-reply-to'); if (isset($rawthread[0]['attribs']['']['ref'])) { $is_reply = true; $parent_uri = $rawthread[0]['attribs']['']['ref']; } if ($is_reply) { $community = false; if ($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) { $sql_extra = ''; $community = true; logger('local_delivery: possible community reply'); } else { $sql_extra = " and contact.self = 1 and item.wall = 1 "; } // was the top-level post for this reply written by somebody on this site? // Specifically, the recipient? $is_a_remote_comment = false; $top_uri = $parent_uri; $r = q("select `item`.`parent-uri` from `item`\n\t\t\t\tWHERE `item`.`uri` = '%s'\n\t\t\t\tLIMIT 1", dbesc($parent_uri)); if ($r && count($r)) { $top_uri = $r[0]['parent-uri']; // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,\n\t\t\t\t\t`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`\n\t\t\t\t\tINNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\t\t\t\tWHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')\n\t\t\t\t\tAND `item`.`uid` = %d\n\t\t\t\t\t{$sql_extra}\n\t\t\t\t\tLIMIT 1", dbesc($top_uri), dbesc($top_uri), dbesc($top_uri), intval($importer['importer_uid'])); if ($r && count($r)) { $is_a_remote_comment = true; } } // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a // valid community comment. Also forum_mode makes it valid for sure. // If neither, it's not. if ($is_a_remote_comment && $community) { if (!$r[0]['forum_mode'] && !$r[0]['wall']) { $is_a_remote_comment = false; logger('local_delivery: not a community reply'); } } if ($is_a_remote_comment) { logger('local_delivery: received remote comment'); $is_like = false; // remote reply to our post. Import and then notify everybody else. $datarray = get_atom_elements($feed, $item); $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { $iid = $r[0]['id']; if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } logger('received updated comment', LOGGER_DEBUG); $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); proc_run('php', "include/notifier.php", "comment-import", $iid); } continue; } $own = q("select name,url,thumb from contact where uid = %d and self = 1 limit 1", intval($importer['importer_uid'])); $datarray['type'] = 'remote-comment'; $datarray['wall'] = 1; $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['importer_uid']; $datarray['owner-name'] = $own[0]['name']; $datarray['owner-link'] = $own[0]['url']; $datarray['owner-avatar'] = $own[0]['thumb']; $datarray['contact-id'] = $importer['id']; if ($datarray['verb'] === ACTIVITY_LIKE || $datarray['verb'] === ACTIVITY_DISLIKE || $datarray['verb'] === ACTIVITY_ATTEND || $datarray['verb'] === ACTIVITY_ATTENDNO || $datarray['verb'] === ACTIVITY_ATTENDMAYBE) { $is_like = true; $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; $datarray['last-child'] = 0; // only one like or dislike per person // splitted into two queries for performance issues $r = q("select id from item where uid = %d and `contact-id` = %d and verb = '%s' and (`parent-uri` = '%s') and deleted = 0 limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($datarray['parent-uri'])); if ($r && count($r)) { continue; } $r = q("select id from item where uid = %d and `contact-id` = %d and verb = '%s' and (`thr-parent` = '%s') and deleted = 0 limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($datarray['parent-uri'])); if ($r && count($r)) { continue; } } if ($datarray['verb'] === ACTIVITY_TAG && $datarray['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($datarray['object'], false); $xt = parse_xml_string($datarray['target'], false); if ($xt->type == ACTIVITY_OBJ_NOTE && $xt->id) { // fetch the parent item $tagp = q("select * from item where uri = '%s' and uid = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (!count($tagp)) { continue; } // extract tag, if not duplicate, and this user allows tags, add to parent item if ($xo->id && $xo->content) { $newtag = '#[url=' . $xo->id . ']' . $xo->content . '[/url]'; if (!stristr($tagp[0]['tag'], $newtag)) { $i = q("SELECT `blocktags` FROM `user` where `uid` = %d LIMIT 1", intval($importer['importer_uid'])); if (count($i) && !intval($i[0]['blocktags'])) { q("UPDATE item SET tag = '%s', `edited` = '%s', `changed` = '%s' WHERE id = %d", dbesc($tagp[0]['tag'] . (strlen($tagp[0]['tag']) ? ',' : '') . $newtag), intval($tagp[0]['id']), dbesc(datetime_convert()), dbesc(datetime_convert())); create_tags_from_item($tagp[0]['id']); } } } } } $posted_id = item_store($datarray); $parent = 0; if ($posted_id) { $datarray["id"] = $posted_id; $r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($posted_id), intval($importer['importer_uid'])); if (count($r)) { $parent = $r[0]['parent']; $parent_uri = $r[0]['parent-uri']; } if (!$is_like) { $r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d", dbesc(datetime_convert()), intval($importer['importer_uid']), intval($r[0]['parent'])); $r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d", dbesc(datetime_convert()), intval($importer['importer_uid']), intval($posted_id)); } if ($posted_id && $parent) { proc_run('php', "include/notifier.php", "comment-import", "{$posted_id}"); if (!$is_like && !$importer['self']) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_uri' => $parent_uri)); } } return 0; // NOTREACHED } } else { // regular comment that is part of this total conversation. Have we seen it? If not, import it. $item_id = $item->get_id(); $datarray = get_atom_elements($feed, $item); if ($importer['rel'] == CONTACT_IS_FOLLOWER) { continue; } $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); } // update last-child if it changes $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow'); if ($allow && $allow[0]['data'] != $r[0]['last-child']) { $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc(datetime_convert()), dbesc($parent_uri), intval($importer['importer_uid'])); $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", intval($allow[0]['data']), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); } continue; } $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; if ($datarray['verb'] === ACTIVITY_LIKE || $datarray['verb'] === ACTIVITY_DISLIKE || $datarray['verb'] === ACTIVITY_ATTEND || $datarray['verb'] === ACTIVITY_ATTENDNO || $datarray['verb'] === ACTIVITY_ATTENDMAYBE) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; // only one like or dislike per person // splitted into two queries for performance issues $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`parent-uri` = '%s') limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($parent_uri)); if ($r && count($r)) { continue; } $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`thr-parent` = '%s') limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($parent_uri)); if ($r && count($r)) { continue; } } if ($datarray['verb'] === ACTIVITY_TAG && $datarray['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($datarray['object'], false); $xt = parse_xml_string($datarray['target'], false); if ($xt->type == ACTIVITY_OBJ_NOTE) { $r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (!count($r)) { continue; } // extract tag, if not duplicate, add to parent item if ($xo->content) { if (!stristr($r[0]['tag'], trim($xo->content))) { q("UPDATE item SET tag = '%s' WHERE id = %d", dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $xo->id . ']' . $xo->content . '[/url]'), intval($r[0]['id'])); create_tags_from_item($r[0]['id']); } } } } $posted_id = item_store($datarray); // find out if our user is involved in this conversation and wants to be notified. if (!x($datarray['type']) || $datarray['type'] != 'activity') { $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0", dbesc($top_uri), intval($importer['importer_uid'])); if (count($myconv)) { $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname']; // first make sure this isn't our own post coming back to us from a wall-to-wall event if (!link_compare($datarray['author-link'], $importer_url)) { foreach ($myconv as $conv) { // now if we find a match, it means we're in this conversation if (!link_compare($conv['author-link'], $importer_url)) { continue; } require_once 'include/enotify.php'; $conv_parent = $conv['parent']; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $conv_parent, 'parent_uri' => $parent_uri)); // only send one notification break; } } } } continue; } } else { // Head post of a conversation. Have we seen it? If not, import it. $item_id = $item->get_id(); $datarray = get_atom_elements($feed, $item); if (x($datarray, 'object-type') && $datarray['object-type'] === ACTIVITY_OBJ_EVENT) { $ev = bbtoevent($datarray['body']); if ((x($ev, 'desc') || x($ev, 'summary')) && x($ev, 'start')) { $ev['cid'] = $importer['id']; $ev['uid'] = $importer['uid']; $ev['uri'] = $item_id; $ev['edited'] = $datarray['edited']; $ev['private'] = $datarray['private']; $ev['guid'] = $datarray['guid']; $r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['uid'])); if (count($r)) { $ev['id'] = $r[0]['id']; } $xyz = event_store($ev); continue; } } $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); update_thread_uri($item_id, $importer['importer_uid']); } // update last-child if it changes $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow'); if ($allow && $allow[0]['data'] != $r[0]['last-child']) { $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", intval($allow[0]['data']), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); } continue; } $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; if (!link_compare($datarray['owner-link'], $importer['url'])) { // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, // but otherwise there's a possible data mixup on the sender's system. // the tgroup delivery code called from item_store will correct it if it's a forum, // but we're going to unconditionally correct it here so that the post will always be owned by our contact. logger('local_delivery: Correcting item owner.', LOGGER_DEBUG); $datarray['owner-name'] = $importer['senderName']; $datarray['owner-link'] = $importer['url']; $datarray['owner-avatar'] = $importer['thumb']; } if ($importer['rel'] == CONTACT_IS_FOLLOWER && !tgroup_check($importer['importer_uid'], $datarray)) { continue; } // This is my contact on another system, but it's really me. // Turn this into a wall post. $notify = item_is_remote_self($importer, $datarray); $posted_id = item_store($datarray, false, $notify); if (stristr($datarray['verb'], ACTIVITY_POKE)) { $verb = urldecode(substr($datarray['verb'], strpos($datarray['verb'], '#') + 1)); if (!$verb) { continue; } $xo = parse_xml_string($datarray['object'], false); if ($xo->type == ACTIVITY_OBJ_PERSON && $xo->id) { // somebody was poked/prodded. Was it me? $links = parse_xml_string("<links>" . unxmlify($xo->link) . "</links>", false); foreach ($links->link as $l) { $atts = $l->attributes(); switch ($atts['rel']) { case "alternate": $Blink = $atts['href']; break; default: break; } } if ($Blink && link_compare($Blink, $a->get_baseurl() . '/profile/' . $importer['nickname'])) { // send a notification require_once 'include/enotify.php'; notification(array('type' => NOTIFY_POKE, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => $datarray['verb'], 'otype' => 'person', 'activity' => $verb, 'parent' => $datarray['parent'])); } } } continue; } } return 0; // NOTREACHED }