// Here's my embarrassing ass source code. It is public domain, do with it what you will
/*ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(E_ALL);*/
if($_GET['downloadsource']=='yes'){// just serve the source code as plain text and exit
header('Content-Type: text/plain');
echofile_get_contents('rssfilter.php');
die();
}
$feed=$_GET['feed'];
$filter=$_GET['filter'];
$filtertype=$_GET['type'];
$useregex=false;
if($_GET['regex']=='yes'or$_GET['regex']=='y'){
$useregex=true;
}
functionrss_testforfilter($item){// I wrote two different functions for filtering RSS and Atom feeds under the assumption that they would be radically different
// in some way. The only real difference ended up being how the categories are stored within the category tags. I could probably
// consolidate them into one function, but these boolean expressions are big and complicated and I'm too scared to touch it now.
global$useregex;// PHP is silly and makes you re-declare global variables if you want to use them inside functions.
global$filter;
foreach($item->categoryas$category){// loops through all the <category> tags and returns true if any of them contain the filter string
if(
(!$useregexandstrpos($category,$filter)!==false)or// Don't use regex and filter string is found
($useregexandpreg_match($filter,$category))// DO use regex and filter expression is found
){
returntrue;
}
}
if(
(!$useregexand(strpos($item->description,$filter)!==falseorstrpos($item->title,$filter)!==false))or// Don't use regex and filter string is found
($useregexand(preg_match($filter,$item->description)orpreg_match($filter,$item->title)))// DO use regex and filter expression is found
){
returntrue;
}
returnfalse;
}
functionatom_testforfilter($entry){
global$useregex;
global$filter;
foreach($entry->categoryas$category){// loops through all the <category> tags and returns true if any of them contain the filter string
if(
(!$useregexandstrpos($category['term'],$filter)!==false)or// Don't use regex and filter string is found
($useregexandpreg_match($filter,$category['term']))// DO use regex and filter expression is found
){
returntrue;
}
}
if(
(!$useregexand(strpos($entry->description,$filter)!==falseorstrpos($entry->title,$filter)!==false))or// Don't use regex and filter string is found
($useregexand(preg_match($filter,$entry->description)orpreg_match($filter,$entry->title)))// DO use regex and filter expression is found
){
returntrue;
}
returnfalse;
}
if($feed// A basic check to make sure the URL is formed properly. It doesn't actually check for a valid URL or valid regex.
and$filter// If this check fails, the HTML document below this gets served.
and($filtertype==="white"or$filtertype==="black")
){
header('Content-Type: text/xml');// Not sure if I actually need to do this, but it seems like good practice and it makes Chromium display the XML tree all nice.
$content=simplexml_load_string(file_get_contents($feed));// I've encountered a problem where something between the server this command pulls from and this script seems to
// be caching the result. I'm guessing it's some kind of Nginx configuration error, but I'm not sure. Maybe I
// should be using a different function to do this? rss-bridge uses the cURL library, which I know because I had
// to install it myself.
if($content->getName()=='rss'){// Here I just assume everything not explicitly an RSS feed is an Atom feed. I am 100% certain there is an edge case I'm missing here.
echo'<rss version="2.0"><channel>';// This is the most embarrassing part of this code by far. I wanted to do this by looping over all the entries
echo$content->channel->title->asXML();// in the XML object and specifically removing the ones that didn't pass the filter *from* the object, but
echo$content->channel->link->asXML();// I couldn't for the life of me get that to work, so I settled for the next best thing: just echoing all the
echo$content->channel->description->asXML();// fields that are part of the spec out to a brand new XML document and then adding all the entries that did
echo$content->channel->language->asXML();// pass. I mean, if it works it works, but sorry to anyone that was using some nonstandard feature here.