1 (edited by mysterioz 2005-04-04 00:59)

Topic: Generate an OPML of your RSS feeds

Here is the code I used to generate an OPML page from my forums. It creates an outline of the categories and forum structure and is loosely based on the rss 2.0 mod.

You need to change the variable $rot (root) to be the url to your forums. In the function putHeader you must edit the owner name and email. If you are not using the rss 2.0 script with forums and category feeds, you will need to make many changes so I recomend you just install the mod.

Copy & paste the code below, make the changes above and save as "opml.php" or something similar in your PUN_ROOT directory.

KNOWN PROBLEMS: I am not that great with sql, and somebody could probably make this use a single query to save time, but OPML files shouldn't be pinged as often as rss feeds, so there shouldn't be a problem. There are probably some global declarations that can be deleted from the functions, too.

Live example

<?php
// use cashing, prevents header problems
ob_start();

define('PUN_ROOT', './');
@include PUN_ROOT.'config.php';

// If PUN isn't defined, config.php is missing or corrupt
if (!defined('PUN'))
    exit('The file \'config.php\' doesn\'t exist or is corrupt. Please run install.php to install PunBB first.');

// Disable error reporting for uninitialized variables
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// Turn off magic_quotes_runtime
set_magic_quotes_runtime(0);

// change this variable now!

$rot="http://www.path.to.you.forums.com/forums/";


// Load the functions script
require PUN_ROOT.'include/functions.php';
require PUN_ROOT.'include/parser.php';

// Load DB abstraction layer and try to connect
require PUN_ROOT.'include/dblayer/common_db.php';

// Get the forum config
$result = $db->query('SELECT * FROM '.$db->prefix.'config') or error('Unable to fetch forum config', __FILE__, __LINE__, $db->error());
while ($cur_config_item = $db->fetch_row($result))
    $pun_config[$cur_config_item[0]] = $cur_config_item[1];

// Make sure we (guests) have permission to read the forums
$result = $db->query('SELECT g_read_board FROM '.$db->prefix.'groups WHERE g_id=3') or error('Unable to fetch group info', __FILE__, __LINE__, $db->error());
if ($db->result($result) == '0')
    exit('No permission');


// Attempt to load the common language file
@include PUN_ROOT.'lang/'.$pun_config['o_default_lang'].'/common.php';
if (!isset($lang_common)) exit('There is no valid language pack \''.$pun_config['o_default_lang'].'\' installed. Please reinstall a language of that name.');



    
putHeader();

$result = $db->query("SELECT id, cat_name, disp_position
         FROM ".$db->prefix."categories ORDER BY disp_position ASC") 
     or error('Unable to fetch categories', __FILE__, __LINE__, $db->error());;

echo "<body>\n";


while ($cur = $db->fetch_row($result)) {
    putCat($cur);
}

echo "</body>\n";
echo "</opml>\n";

// get feed into $feed
$feed = ob_get_contents();
ob_end_clean();

// create ETAG (hash of feed)
$eTag = '"'.md5($feed).'"';
header('Etag: '.$eTag);

// compare Etag to what we got
if ($eTag == $_SERVER['HTTP_IF_NONE_MATCH']) {    
    header("HTTP/1.0 304 Not Modified");
    header('Content-Length: 0');
} else {
    // dump feed
    header('Content-type: application/xml; charset=ISO-8859-1');
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Cache-Control: post-check=0, pre-check=0", false);
    echo $feed;
}


function putHeader() { 
    global $lang_common,$pun_config;
    echo '<'.'?xml version="1.0" encoding="ISO-8859-1"?'.'>'."\n";
    echo "<opml version=\"1.0\">\n";
    echo "<head>\n";
    echo "<title>".entity_to_decimal_value(htmlspecialchars($pun_config['o_board_title']))."</title>\n";

//
// change these 2 below
//
    echo "<ownerName>".entity_to_decimal_value(htmlspecialchars("Enter the name of the owner here"))."</ownerName>\n";
    echo "<ownerEmail>".entity_to_decimal_value(htmlspecialchars("you@your-email.com"))."</ownerEmail>\n";

//
// end changes
//
    echo "<dateCreated>".entity_to_decimal_value(htmlspecialchars(date("D, d M Y H:i:s T")))."</dateCreated>\n";
    echo "<dateModified>".entity_to_decimal_value(htmlspecialchars(date("D, d M Y H:i:s T")))."</dateModified>\n";
    echo "</head>\n";
    
} 

function putCat($cur) {
    global $lang_common,$pun_config, $rot, $db;
    
    echo '<outline text="'.entity_to_decimal_value(htmlspecialchars($cur[1])).'" type="rss" url="'.$rot.'rss.php?cid='.$cur[0].'" >'."\n";
    
    $result2 = $db->query("SELECT id, forum_name, disp_position
         FROM ".$db->prefix."forums 
                 WHERE cat_id=".$cur[0]."
         ORDER BY disp_position ASC") 
                 or error('Unable to fetch forums', __FILE__, __LINE__, $db->error());;
    
    while ($res = $db->fetch_row($result2)) {
    putForum($res);
    }

    echo "</outline>\n";
} 

function putForum($res) {
    global $lang_common,$pun_config, $rot;
    echo '<outline text="'.entity_to_decimal_value(htmlspecialchars($res[1])).'" type="rss" url="'.$rot.'rss.php?fid='.$res[0].'" />'."\n";
}



/* entity to unicode decimal value */


function entity_to_decimal_value($string){
    static $entities_dec = false;
    if (!is_array($entities_dec)) {
        $entities_named       = array(" ","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ","ƒ","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","•","…","?","?","?","?","?","?","?","™","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",""","&","<",">","Œ","œ","Š","š","Ÿ","ˆ","˜","?","?","?","?","?","?","?","–","—","‘","’","‚","“","”","„","†","‡","‰","‹","›","€","&apos;");
        $entities_decimal     = array(" ","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",""","&","<",">","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","'");
        if (function_exists('array_combine')) 
            $entities_dec=array_combine($entities_named,$entities_decimal);
        else {
            $i=0;
            foreach ($entities_named as $_entities_named) $entities_dec[$_entities_named]=$entities_decimal[$i++];
        }
    }
    return preg_replace( "/&[A-Za-z]+;/", " ", strtr($string,$entities_dec) );
}

?>

2 (edited by shinko_metsuo 2005-04-04 00:57)

Re: Generate an OPML of your RSS feeds

nice mod

a bit of bugs in it <.<

Re: Generate an OPML of your RSS feeds

That's kind of cool. I'm not entirely sure what you would use it for though.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

Re: Generate an OPML of your RSS feeds

OPML, or Outline Processor Markup Language, is an xml standard for creating nested outlines. It is used by rss news-readers to index and import a list of rss feeds. To make it open in a news-reader, you should try

<a href="feed:opml.php">OPML</a>

According to my research, opml files will only open properly in newsreaders if the extension is opml. So the recomendation here is after you have finished your forums outline, you copy the output from opml.php into a text file and upload it to your server with extension ".opml" and add the feed link to your forums.

OPML can also be added to the header tag of you forums template using the <link rel="">

<link rel="opml" type="application/opml+xml" title="Forums" href="http://myweb.com/forums/opml.php" />

That should work for auto-discovery.

If you have more rss feeds, a blog, etc., you can create a second opml by copying the other opml, and adding the links at the top

copy & paste head from /forums/opml.php here
<outline text="Blog" type="rss" url="http://myweb.com/">
  <outline text="Topic 1" type="rss" url="">
</outline>
The rest of your forums/opml.php file copied here

Then you can save it as whatever.opml and put a feed:whatever.opml link to it on the front page of your site and in the header of your page.

OPML can be used for a lot more. I would love to see you use it it the Wiki plugin you are working on. The entire outline of the wiki could be entered/imported/exported in OPML. By using the type="" reference, you can refer to images, video, etc. There is also a desc tag for adding more text descriptions text.

More fun with punbb and xml comming soon :-)