<?php namespace HashOver;// Copyright (C) 2010-2021 Jacob Barkdull// This file is part of HashOver.//// HashOver is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as// published by the Free Software Foundation, either version 3 of the// License, or (at your option) any later version.//// HashOver is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with HashOver.  If not, see <http://www.gnu.org/licenses/>.// Tell browser this is XML/RSSheader ('Content-Type: application/xml; charset=utf-8');// Change to the HashOver directorychdir (realpath ('../'));// Do some standard HashOver setup workrequire ('backend/nocache-headers.php');require ('backend/standard-setup.php');// Setup class autoloadersetup_autoloader (function ($error) {	echo '<?xml version="1.0" encoding="UTF-8"?>', PHP_EOL;	echo '<error>', $error, '</error>';});// Parses comment into RSS itemfunction parse_comments (&$metadata, &$comment, &$rss, &$xml, &$hashover){	// Skip deleted/unmoderated comments	if (isset ($comment['notice'])) {		return;	}	// Encode HTML entities	$comment['body'] = htmlentities ($comment['body'], ENT_COMPAT, 'UTF-8', true);	// Decode HTML entities	$comment['body'] = html_entity_decode ($comment['body'], ENT_COMPAT, 'UTF-8');	// Remove [img] tags	$comment['body'] = preg_replace ('/\[(img|\/img)\]/iS', '', $comment['body']);	// Parse comment as markdown	$comment['body'] = $hashover->markdown->parseMarkdown ($comment['body']);	// Convert <code> tags to <pre> tags	$comment['body'] = preg_replace ('/(<|<\/)code>/iS', '\\1pre>', $comment['body']);	// Get name from comment or use configured default	$name = Misc::getArrayItem ($comment, 'name') ?: $hashover->setup->defaultName;	// Create item element	$item = $xml->createElement ('item');	// Start item summary title with user's name	$title = $name . ' : ';	// Strip HTML tags from comment and remove all newlines	$single_comment = str_replace (PHP_EOL, ' ', strip_tags ($comment['body']));	// Check if comment is more than 40 characters long	if (mb_strlen ($single_comment) > 40) {		// If so, add 40 characters of comment to summary title		$title .= mb_substr ($single_comment, 0, 40) . '...';	} else {		// If not, add comment to summary title as-is		$title .= $single_comment;	}	// Create item title element	$item_title = $xml->createElement ('title');	$item_title_value = $xml->createTextNode (html_entity_decode ($title, ENT_COMPAT, 'UTF-8'));	$item_title->appendChild ($item_title_value);	// Add item title element to item element	$item->appendChild ($item_title);	// Create item name element	$item_name = $xml->createElement ('name');	$item_name_value = $xml->createTextNode (html_entity_decode ($name, ENT_COMPAT, 'UTF-8'));	$item_name->appendChild ($item_name_value);	// Add item name element to item element	$item->appendChild ($item_name);	// URL regular expression	$url_regex = '/((http|https|ftp):\/\/[a-z0-9-@:%_\+.~#?&\/=]+) {0,}/iS';	// Add HTML anchor tag to URLs (hyperlinks)	$comment['body'] = preg_replace ($url_regex, '<a href="\\1" target="_blank">\\1</a>', $comment['body']);	// Replace newlines with break tags	$comment['body'] = str_replace (PHP_EOL, '<br>', $comment['body']);	// Create item description element	$item_description = $xml->createElement ('description');	$item_description_value = $xml->createTextNode ($comment['body']);	$item_description->appendChild ($item_description_value);	// Add item description element to item element	$item->appendChild ($item_description);	// Create item avatar element	$item_avatar = $xml->createElement ('avatar');	$item_avatar_value = $xml->createTextNode ($comment['avatar']);	$item_avatar->appendChild ($item_avatar_value);	// Add item avatar element to item element	$item->appendChild ($item_avatar);	// Check if likes are enabled	if (!empty ($comment['likes'])) {		// If so, create item likes element		$item_likes = $xml->createElement ('likes');		$item_likes_value = $xml->createTextNode ($comment['likes']);		$item_likes->appendChild ($item_likes_value);		// Add item likes element to item element		$item->appendChild ($item_likes);	}	// Check if dislikes are enabled	if ($hashover->setup->allowsDislikes === true) {		// If so, check if comment has any dislikes		if (!empty ($comment['dislikes'])) {			// If so, create dislikes item element			$item_dislikes = $xml->createElement ('dislikes');			$item_dislikes_value = $xml->createTextNode ($comment['dislikes']);			$item_dislikes->appendChild ($item_dislikes_value);			// Add dislikes item element to item element			$item->appendChild ($item_dislikes);		}	}	// Create item publication date element	$item_pubDate = $xml->createElement ('pubDate');	$item_pubDate_value = date (DATE_RSS, $comment['timestamp']);	$item_pubDate_node = $xml->createTextNode ($item_pubDate_value);	$item_pubDate->appendChild ($item_pubDate_node);	// Add item pubDate element to item element	$item->appendChild ($item_pubDate);	// URL to comment for item guide and link elements	$item_permalink_url = $metadata['url'] . '#' . $comment['permalink'];	// Create item guide element	$item_guid = $xml->createElement ('guid');	$item_guid_value = $xml->createTextNode ($item_permalink_url);	$item_guid->appendChild ($item_guid_value);	// Add item guide element to item element	$item->appendChild ($item_guid);	// Create item link element	$item_link = $xml->createElement ('link');	$item_link_value = $xml->createTextNode ($item_permalink_url);	$item_link->appendChild ($item_link_value);	// Add item link element to item element	$item->appendChild ($item_link);	// Add item element to main RSS element	$rss->appendChild ($item);	// Recursively parse replies	if (!empty ($comment['replies'])) {		foreach ($comment['replies'] as $reply) {			parse_comments ($metadata, $reply, $rss, $xml, $hashover);		}	}}// Creates RSS feedfunction create_rss (&$hashover){	// Shorter variable name	$thread = $hashover->setup->threadName;	// Attempt to read page information metadata	$metadata = $hashover->thread->data->readMeta ('page-info', $thread);	// Check if metadata read successfully	if ($metadata !== false) {		// If so, set page URL blank if it's missing from the metadata		if (!isset ($metadata['url'])) {			$metadata['url'] = '';		}		// And set page title to "Untitled" if it's missing from the metadata		if (!isset ($metadata['title'])) {			$metadata['title'] = $hashover->locale->text['untitled'];		}	} else {		// If not, set default metadata information		$metadata = array (			'url' => '',			'title' => $hashover->locale->text['untitled']		);	}	// Create new DOM document.	$xml = new \DOMDocument ('1.0', 'UTF-8');	$xml->preserveWhiteSpace = false;	$xml->formatOutput = true;	// Create main RSS element	$rss = $xml->createElement ('rss');	$rss->setAttribute ('version', '2.0');	$rss->setAttribute ('xmlns:dc', 'http://purl.org/dc/elements/1.1/');	$rss->setAttribute ('xmlns:content', 'http://purl.org/rss/1.0/modules/content/');	$rss->setAttribute ('xmlns:atom', 'http://www.w3.org/2005/Atom');	// Create channel element	$channel = $xml->createElement ('channel');	// Create channel title element	$title = $xml->createElement ('title');	$title_value = $xml->createTextNode (html_entity_decode ($metadata['title'], ENT_COMPAT, 'UTF-8'));	$title->appendChild ($title_value);	// Add channel title to channel element	$channel->appendChild ($title);	// Create channel link element	$link = $xml->createElement ('link');	$link_value = $xml->createTextNode (html_entity_decode ($metadata['url'], ENT_COMPAT, 'UTF-8'));	$link->appendChild ($link_value);	// Add channel link to channel element	$channel->appendChild ($link);	// Check if there is more than one comment	if ($hashover->thread->totalCount !== 1) {		// If so, use "X Comments" locale string		$showing_comments_locale = $hashover->locale->text['showing-comments'];	} else {		// If not, use "X Comment" locale string		$showing_comments_locale = $hashover->locale->text['showing-comment'];	}	// Create channel description element	$description = $xml->createElement ('description');	$count_locale = sprintf ($showing_comments_locale, $hashover->thread->totalCount - 1);	$description_value = $xml->createTextNode ($count_locale);	$description->appendChild ($description_value);	// Add channel description to channel element	$channel->appendChild ($description);	// Create channel atom link element	$atom_link = $xml->createElement ('atom:link');	$atom_url = $hashover->setup->domain . $_SERVER['PHP_SELF'] . '?url=' . urlencode ($metadata['url']);	$atom_link->setAttribute ('href', 'http://' . $atom_url);	$atom_link->setAttribute ('rel', 'self');	// Add channel atom link to channel element	$channel->appendChild ($atom_link);	// Create channel language element	$language = $xml->createElement ('language');	$language_value = $xml->createTextNode ('en-us');	$language->appendChild ($language_value);	// Add channel language to channel element	$channel->appendChild ($language);	// Create channel ttl element	$ttl = $xml->createElement ('ttl');	$ttl_value = $xml->createTextNode ('40');	$ttl->appendChild ($ttl_value);	// Add channel ttl to channel element	$channel->appendChild ($ttl);	// Add channel element to main RSS element	$rss->appendChild ($channel);	// Add item element to main RSS element	foreach ($hashover->comments['primary'] as $comment) {		parse_comments ($metadata, $comment, $rss, $xml, $hashover);	}	// Add main RSS element to XML	$xml->appendChild ($rss);	// Return RSS XML	echo preg_replace_callback ('/^(\s+)/m', function ($spaces) {		return str_repeat ("\t", mb_strlen ($spaces[1]) / 2);	}, $xml->saveXML ());	// Return statistics	echo $hashover->statistics->executionEnd ('php');}try {	// Instantiate HashOver class	$hashover = new \HashOver ('rss');	// Throw exception if API is disabled	$hashover->setup->apiCheck ('rss');	// Enable remote access	$hashover->setup->setupRemoteAccess ();	// Set page URL from GET data	$hashover->setup->setPageURL ('request');	// Initiate comment processing	$hashover->initiate ();	// Parse primary comments into usable data	$hashover->parsePrimary ();	// Attempt to get sorting method	$method = $hashover->setup->getRequest ('sorting', 'by-date');	// Sort comments by sorting method	$hashover->sortPrimary ($method);	// Create RSS feed	create_rss ($hashover);} catch (\Exception $error) {	echo Misc::displayException ($error, 'rss');}