| 1 | <?php |
|---|
| 2 | ############################################################################### |
|---|
| 3 | # Gregarius - A PHP based RSS aggregator. |
|---|
| 4 | # Copyright (C) 2003 - 2006 Marco Bonetti |
|---|
| 5 | # |
|---|
| 6 | ############################################################################### |
|---|
| 7 | # This program is free software and open source software; you can redistribute |
|---|
| 8 | # it and/or modify it under the terms of the GNU General Public License as |
|---|
| 9 | # published by the Free Software Foundation; either version 2 of the License, |
|---|
| 10 | # or (at your option) any later version. |
|---|
| 11 | # |
|---|
| 12 | # This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 15 | # more details. |
|---|
| 16 | # |
|---|
| 17 | # You should have received a copy of the GNU General Public License along |
|---|
| 18 | # with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit |
|---|
| 20 | # http://www.gnu.org/licenses/gpl.html |
|---|
| 21 | # |
|---|
| 22 | ############################################################################### |
|---|
| 23 | # E-mail: mbonetti at gmail dot com |
|---|
| 24 | # Web page: http://gregarius.net/ |
|---|
| 25 | # |
|---|
| 26 | ############################################################################### |
|---|
| 27 | |
|---|
| 28 | require_once('init.php'); |
|---|
| 29 | |
|---|
| 30 | function getOpml($url) { |
|---|
| 31 | $arr = parse_weblogsDotCom($url); |
|---|
| 32 | |
|---|
| 33 | if (!$arr) { |
|---|
| 34 | return false; |
|---|
| 35 | } else { |
|---|
| 36 | return $arr; |
|---|
| 37 | } |
|---|
| 38 | } |
|---|
| 39 | |
|---|
| 40 | /**** mbi: from http://www.stargeek.com/php_scripts.php?script=20&cat=blog */ |
|---|
| 41 | function parse_weblogsDotCom($url) { |
|---|
| 42 | /* |
|---|
| 43 | Grab weblogs.com list of recently updated RSS feeds |
|---|
| 44 | $blogs is array() of feeds |
|---|
| 45 | NAME name |
|---|
| 46 | URL address |
|---|
| 47 | WHEN seconds since ping |
|---|
| 48 | */ |
|---|
| 49 | |
|---|
| 50 | global $blogs,$folder,$inOpmlfolder, $inOpmlItem; |
|---|
| 51 | $folder = __('Root'); |
|---|
| 52 | |
|---|
| 53 | $inOpmlfolder = $inOpmlItem = false; |
|---|
| 54 | $opml = getUrl($url); |
|---|
| 55 | $opml = str_replace("\r", '', $opml); |
|---|
| 56 | $opml = str_replace("\n", '', $opml); |
|---|
| 57 | |
|---|
| 58 | $xp = xml_parser_create() or xml_error("couldn't create parser"); |
|---|
| 59 | |
|---|
| 60 | xml_set_element_handler($xp, '_xml_startElement', '_xml_endElement') |
|---|
| 61 | or xml_error("couldnt set XML handlers"); |
|---|
| 62 | |
|---|
| 63 | xml_parse($xp, $opml, true) or xml_error("failed parsing xml at line ".xml_get_current_line_number().": " . xml_error_string()); |
|---|
| 64 | xml_parser_free($xp) or xml_error("failed freeing the parser"); |
|---|
| 65 | return $blogs; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | function xml_error($error_msg){ |
|---|
| 69 | rss_error($error_msg, RSS_ERROR_ERROR,true); |
|---|
| 70 | echo("\n</div>\n</body></html>\n"); |
|---|
| 71 | die(); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | function _xml_startElement($xp, $element, $attr) { |
|---|
| 75 | global $blogs,$folder,$inOpmlfolder, $inOpmlItem; |
|---|
| 76 | if (strcasecmp('outline', $element)) { |
|---|
| 77 | return; |
|---|
| 78 | } |
|---|
| 79 | //$attr['__opml_folder__'] = $folder; |
|---|
| 80 | if (!array_key_exists('XMLURL',$attr) && (array_key_exists('TEXT',$attr)||array_key_exists('TITLE',$attr)) ) { |
|---|
| 81 | //some opml use title instead of text to define a folder (ex: newzcrawler) |
|---|
| 82 | $folder = $attr['TEXT']?$attr['TEXT']:$attr['TITLE']; |
|---|
| 83 | $inOpmlfolder = true; |
|---|
| 84 | $inOpmlItem = false; |
|---|
| 85 | //echo "start of folder $folder\n"; |
|---|
| 86 | } else { |
|---|
| 87 | $inOpmlItem = true; |
|---|
| 88 | //echo "start of item $folder/".$attr['TEXT']."\n"; |
|---|
| 89 | if ($folder != '') { |
|---|
| 90 | $blogs[$folder][] = $attr; |
|---|
| 91 | } else { |
|---|
| 92 | $blogs[] = $attr; |
|---|
| 93 | } |
|---|
| 94 | } |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | function _xml_endElement($xp, $element) { |
|---|
| 98 | global $blogs,$folder,$inOpmlfolder, $inOpmlItem; |
|---|
| 99 | if (strcasecmp( $element, "outline") === 0) { |
|---|
| 100 | if (!$inOpmlItem && $inOpmlfolder) { |
|---|
| 101 | //echo "end of folder $folder\n"; |
|---|
| 102 | // end of folder element! |
|---|
| 103 | $inOpmlfolder = false; |
|---|
| 104 | $folder = __('Root'); |
|---|
| 105 | } else { |
|---|
| 106 | // end of item element |
|---|
| 107 | $inOpmlItem = false; |
|---|
| 108 | //echo "end of item\n"; |
|---|
| 109 | } |
|---|
| 110 | } |
|---|
| 111 | return; |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | /** OPML Export */ |
|---|
| 115 | /** OPML2.0 RFC: http://techno-weenie.com/archives/2003/04/01/003067.php */ |
|---|
| 116 | /** OPML1.0 Specs: http://opml.scripting.com/spec */ |
|---|
| 117 | |
|---|
| 118 | // This is a pretty lame opml 1.1 generation routine, in that it is not |
|---|
| 119 | // recursive, but instead relies on the fact that we only have one level |
|---|
| 120 | // of folders. |
|---|
| 121 | // Output should be valid xml. (*fingers crossed*) |
|---|
| 122 | if (array_key_exists('act',$_REQUEST)) { |
|---|
| 123 | |
|---|
| 124 | $rs = rss_query( "select fid,tag from " .getTable('tag') ." t " |
|---|
| 125 | . "inner join " . getTable('metatag') ." mt on mt.tid=t.id" |
|---|
| 126 | ." where ttype='channel'"); |
|---|
| 127 | $cats=array(); |
|---|
| 128 | while(list($cid,$tag) = rss_fetch_row($rs)) { |
|---|
| 129 | if (!isset($cats[$cid])) { |
|---|
| 130 | $cats[$cid]=array(); |
|---|
| 131 | } |
|---|
| 132 | $cats[$cid][]=$tag; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | $sql = "select c.id, c.title, c.url, c.siteurl, d.name, c.parent, c.descr " |
|---|
| 137 | ." from ". getTable("channels") . " c " |
|---|
| 138 | ."inner join " . getTable("folders") ." d on d.id = c.parent"; |
|---|
| 139 | |
|---|
| 140 | if (hidePrivate()) { |
|---|
| 141 | $sql .=" where not(c.mode & " . RSS_MODE_PRIVATE_STATE .") "; |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | // note: should we export deprecated feeds? |
|---|
| 145 | |
|---|
| 146 | if (getConfig('rss.config.absoluteordering')) { |
|---|
| 147 | $sql .= " order by d.position asc, c.position asc"; |
|---|
| 148 | } else { |
|---|
| 149 | $sql .=" order by d.name asc, c.title asc"; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | $res = rss_query($sql); |
|---|
| 153 | |
|---|
| 154 | $dateRes = rss_query("select max(dateadded) from " . getTable("channels")); |
|---|
| 155 | list($dateModif) = rss_fetch_row($dateRes); |
|---|
| 156 | $dateLabel = date("r", strtotime($dateModif)); |
|---|
| 157 | |
|---|
| 158 | header("Content-Type: text/xml"); |
|---|
| 159 | echo "<?xml version=\"1.0\" encoding=\"" . getConfig('rss.output.encoding') . "\"?>\n" |
|---|
| 160 | ."<?xml-stylesheet type=\"text/xsl\" href=\"".getPath()."css/opml.xsl\"?>\n" |
|---|
| 161 | ."<!-- Generated by "._TITLE_. " " . _VERSION_ ." -->\n" |
|---|
| 162 | ."<opml version=\"2.0\">\n"; |
|---|
| 163 | |
|---|
| 164 | echo "\t<head>\n" |
|---|
| 165 | ."\t\t<title>"._TITLE_." OPML Feed</title>\n" |
|---|
| 166 | ."\t\t<dateModified>$dateLabel</dateModified>\n" |
|---|
| 167 | ."\t</head>\n" |
|---|
| 168 | ."\t<body>\n"; |
|---|
| 169 | |
|---|
| 170 | $prev_parent=0; |
|---|
| 171 | while (list($id, $title, $url, $siteurl, $name, $parent, $descr) = rss_fetch_row($res)) { |
|---|
| 172 | $descr_ = htmlspecialchars ($descr); |
|---|
| 173 | $descr_ = trim(preg_replace('/(\r\n|\r|\n)/', ' ', $descr_)); |
|---|
| 174 | |
|---|
| 175 | $title_ = htmlspecialchars($title); |
|---|
| 176 | |
|---|
| 177 | $url_ = preg_replace('|(https?://)([^:]+:[^@]+@)(.+)$|','\1\3',$url); |
|---|
| 178 | $url_ = htmlspecialchars($url_); |
|---|
| 179 | |
|---|
| 180 | $siteurl_ = preg_replace('|(https?://)([^:]+:[^@]+@)(.+)$|','\1\3',$siteurl); |
|---|
| 181 | $siteurl_ = htmlspecialchars($siteurl_); |
|---|
| 182 | |
|---|
| 183 | $name_ = htmlspecialchars($name); |
|---|
| 184 | |
|---|
| 185 | if ($parent != $prev_parent) { |
|---|
| 186 | if ($prev_parent != 0) { |
|---|
| 187 | echo "\t\t</outline>\n"; |
|---|
| 188 | } |
|---|
| 189 | $prev_parent = $parent; |
|---|
| 190 | echo "\t\t<outline text=\"$name_\">\n"; |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | if ($parent > 0) { |
|---|
| 194 | echo "\t"; |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | echo "\t\t<outline text=\"$title_\" description=\"$descr_\" type=\"rss\""; |
|---|
| 198 | if ($siteurl != "") { |
|---|
| 199 | echo " htmlUrl=\"$siteurl_\""; |
|---|
| 200 | } |
|---|
| 201 | if (isset($cats[$id]) && count($cats[$id])) { |
|---|
| 202 | echo " category=\"" . implode(",",$cats[$id]) ."\""; |
|---|
| 203 | } |
|---|
| 204 | echo " xmlUrl=\"$url_\" />\n"; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | if ($prev_parent > 0) { |
|---|
| 208 | echo "\t</outline>\n"; |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | echo "\t</body>\n</opml>\n"; |
|---|
| 212 | } |
|---|
| 213 | ?> |
|---|