| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | ############################################################################### |
|---|
| 4 | # Gregarius - A PHP based RSS aggregator. |
|---|
| 5 | # Copyright (C) 2003 - 2006 Marco Bonetti |
|---|
| 6 | # |
|---|
| 7 | ############################################################################### |
|---|
| 8 | # This program is free software and open source software; you can redistribute |
|---|
| 9 | # it and/or modify it under the terms of the GNU General Public License as |
|---|
| 10 | # published by the Free Software Foundation; either version 2 of the License, |
|---|
| 11 | # or (at your option) any later version. |
|---|
| 12 | # |
|---|
| 13 | # This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 15 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 16 | # more details. |
|---|
| 17 | # |
|---|
| 18 | # You should have received a copy of the GNU General Public License along |
|---|
| 19 | # with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 20 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit |
|---|
| 21 | # http://www.gnu.org/licenses/gpl.html |
|---|
| 22 | # |
|---|
| 23 | ############################################################################### |
|---|
| 24 | # E-mail: mbonetti at gmail dot com |
|---|
| 25 | # Web page: http://gregarius.net/ |
|---|
| 26 | # |
|---|
| 27 | ############################################################################### |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | function getLastModif() { |
|---|
| 32 | return getProperty('__meta__','meta.lastupdate'); |
|---|
| 33 | } |
|---|
| 34 | |
|---|
| 35 | function getETag() { |
|---|
| 36 | return md5(getLastModif().$_SERVER['PHP_SELF']); |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | function rss_error($message, $severity = RSS_ERROR_ERROR, $render = false) { |
|---|
| 41 | if ($render) { |
|---|
| 42 | echo "<p class=\"error\">$message</p>\n"; |
|---|
| 43 | return; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | if (!isset($GLOBALS['rss'])) { |
|---|
| 47 | rss_require('cls/rss.php'); |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | $GLOBALS['rss'] -> error($message, $severity); |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | /** this functions checks whether a URI exists */ |
|---|
| 54 | function getHttpResponseCode($forUri) { |
|---|
| 55 | return getUrl($forUri, 255); |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | function getContentType($link, & $contentType) { |
|---|
| 59 | $url_parts = @ parse_url($link); |
|---|
| 60 | if (empty ($url_parts["host"])) { |
|---|
| 61 | return (false); |
|---|
| 62 | } |
|---|
| 63 | if (!empty ($url_parts["path"])) { |
|---|
| 64 | $documentpath = $url_parts["path"]; |
|---|
| 65 | } else { |
|---|
| 66 | $documentpath = "/"; |
|---|
| 67 | } |
|---|
| 68 | if (!empty ($url_parts["query"])) { |
|---|
| 69 | $documentpath .= "?".$url_parts["query"]; |
|---|
| 70 | } |
|---|
| 71 | $host = $url_parts["host"]; |
|---|
| 72 | $port = (array_key_exists('port', $url_parts) ? $url_parts["port"] : "80"); |
|---|
| 73 | |
|---|
| 74 | $socket = @ fsockopen($host, $port, $errno, $errstr, 30); |
|---|
| 75 | if (!$socket) { |
|---|
| 76 | return (false); |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | $ret = false; |
|---|
| 80 | fwrite($socket, "GET ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n"); |
|---|
| 81 | while (!feof($socket)) { |
|---|
| 82 | $line = fgets($socket, 100); |
|---|
| 83 | if (preg_match("/Content-Type: (.*)/i", $line, $matches)) { |
|---|
| 84 | $contentType = $matches[1]; |
|---|
| 85 | $ret = true; |
|---|
| 86 | break; |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | return $ret; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | // basically strips folder resources from URIs. |
|---|
| 94 | // http://pear.php.net/package/HTTP_Client/ --> http://pear.php.net/ |
|---|
| 95 | function get_host($url, & $host) { |
|---|
| 96 | $ret = preg_match("/^(http:\/\/)?([^\/]+)/i", $url, $matches); |
|---|
| 97 | $host = $matches[2]; |
|---|
| 98 | |
|---|
| 99 | //ensure we have a slash |
|---|
| 100 | if (substr($host, -1) != "/") { |
|---|
| 101 | $host .= "/"; |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | return $ret; |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | /** |
|---|
| 108 | * Builds a title out of an already encoded string. |
|---|
| 109 | */ |
|---|
| 110 | function makeTitle($title) { |
|---|
| 111 | // Let us find out if the user has set a title. |
|---|
| 112 | $userTitle = _TITLE_; |
|---|
| 113 | if (getConfig('rss.output.title')) { |
|---|
| 114 | $userTitle = getConfig('rss.output.title'); |
|---|
| 115 | } |
|---|
| 116 | $ret = "". $userTitle .""; |
|---|
| 117 | if ($title) { |
|---|
| 118 | if (is_array($title)) { |
|---|
| 119 | foreach($title as $token) { |
|---|
| 120 | $ret .= " ".TITLE_SEP." ".$token; |
|---|
| 121 | } |
|---|
| 122 | } else { |
|---|
| 123 | $ret .= " ".TITLE_SEP." ".$title; |
|---|
| 124 | } |
|---|
| 125 | } |
|---|
| 126 | return $ret; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | /*** update the given feed(s) **/ |
|---|
| 130 | function update($id) { |
|---|
| 131 | $kses_allowed = getConfig('rss.input.allowed'); //getAllowedTags(); |
|---|
| 132 | $updatedIds = array (); |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | $sql = "select id, url, title, mode from ".getTable("channels"); |
|---|
| 136 | if ($id != "" && is_numeric($id)) { |
|---|
| 137 | $sql .= " where id=$id"; |
|---|
| 138 | $sql .= " and not(mode & ".RSS_MODE_DELETED_STATE.") "; |
|---|
| 139 | } else { |
|---|
| 140 | $sql .= " where not(mode & ".RSS_MODE_DELETED_STATE.") "; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | if (getConfig('rss.config.absoluteordering')) { |
|---|
| 144 | $sql .= " order by parent, position"; |
|---|
| 145 | } else { |
|---|
| 146 | $sql .= " order by parent, title"; |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | $res = rss_query($sql); |
|---|
| 150 | while (list ($cid, $url, $title, $mode) = rss_fetch_row($res)) { |
|---|
| 151 | |
|---|
| 152 | // suppress warnings because Magpie is rather noisy |
|---|
| 153 | $old_level = error_reporting(E_ERROR); |
|---|
| 154 | $rss = fetch_rss($url); |
|---|
| 155 | |
|---|
| 156 | //reset |
|---|
| 157 | error_reporting($old_level); |
|---|
| 158 | |
|---|
| 159 | if (!$rss && $id != "" && is_numeric($id)) { |
|---|
| 160 | return array (magpie_error(), array ()); |
|---|
| 161 | } |
|---|
| 162 | elseif (!$rss || !($rss->rss_origin & MAGPIE_FEED_ORIGIN_HTTP_200) ) { |
|---|
| 163 | continue; // no need to do anything if we do not get a 200 OK from the feed |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | // base URL for items in this feed. |
|---|
| 167 | if (array_key_exists('link', $rss->channel)) { |
|---|
| 168 | $baseUrl = $rss->channel['link']; |
|---|
| 169 | } else { |
|---|
| 170 | $baseUrl = $url; // The feed is invalid |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | // Keep track of guids we've handled, because some feeds (hello, |
|---|
| 174 | // Technorati!) have this insane habit of serving the same item |
|---|
| 175 | // twice in the same feed. |
|---|
| 176 | $guids = array(); |
|---|
| 177 | |
|---|
| 178 | // Allow updates in this feed? |
|---|
| 179 | $allowUpdates = getProperty($cid,'rss.input.allowupdates'); |
|---|
| 180 | if ($allowUpdates === null) { |
|---|
| 181 | $allowUpdates = getConfig('rss.input.allowupdates'); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | $itemIdsInFeed = array(); // This variable will store the item id's of the elements in the feed |
|---|
| 185 | foreach ($rss->items as $item) { |
|---|
| 186 | |
|---|
| 187 | $item = rss_plugin_hook('rss.plugins.rssitem', $item); |
|---|
| 188 | // a plugin might delete this item |
|---|
| 189 | if(!isset($item)) |
|---|
| 190 | continue; |
|---|
| 191 | |
|---|
| 192 | // item title: strip out html tags |
|---|
| 193 | $title = array_key_exists('title', $item) ? strip_tags($item['title']) : ""; |
|---|
| 194 | //$title = str_replace('& ', '& ', $title); |
|---|
| 195 | |
|---|
| 196 | |
|---|
| 197 | $description = ""; |
|---|
| 198 | // item content, if any |
|---|
| 199 | if (array_key_exists('content', $item) && is_array($item['content']) && array_key_exists('encoded', $item['content'])) { |
|---|
| 200 | $description = $item['content']['encoded']; |
|---|
| 201 | } |
|---|
| 202 | elseif (array_key_exists('description', $item)) { |
|---|
| 203 | $description = $item['description']; |
|---|
| 204 | } |
|---|
| 205 | elseif (array_key_exists('atom_content', $item)) { |
|---|
| 206 | $description = $item['atom_content']; |
|---|
| 207 | } |
|---|
| 208 | elseif (array_key_exists('summary', $item)) { |
|---|
| 209 | $description = $item['summary']; |
|---|
| 210 | } |
|---|
| 211 | else { |
|---|
| 212 | $description = ""; |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | $md5sum = ""; |
|---|
| 216 | $guid = ""; |
|---|
| 217 | |
|---|
| 218 | if(array_key_exists('guid', $item) && $item['guid'] != "") { |
|---|
| 219 | $guid = $item['guid']; |
|---|
| 220 | } |
|---|
| 221 | elseif(array_key_exists('id', $item) && $item['id'] != "") { |
|---|
| 222 | $guid = $item['id']; |
|---|
| 223 | } |
|---|
| 224 | $guid = trim($guid); |
|---|
| 225 | $guid = rss_real_escape_string($guid); |
|---|
| 226 | |
|---|
| 227 | // skip this one if it's an in-feed-dupe |
|---|
| 228 | if ($guid && isset($guids[$guid])) { |
|---|
| 229 | continue; |
|---|
| 230 | } |
|---|
| 231 | elseif($guid) { |
|---|
| 232 | $guids[$guid] = true; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | if ($description != "") { |
|---|
| 236 | $md5sum = md5($description); |
|---|
| 237 | $description = kses($description, $kses_allowed); // strip out tags |
|---|
| 238 | |
|---|
| 239 | if ($baseUrl != "") { |
|---|
| 240 | $description = relative_to_absolute($description, $baseUrl); |
|---|
| 241 | } |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | // Now let plugins modify the description |
|---|
| 245 | $description = rss_plugin_hook('rss.plugins.import.description', $description); |
|---|
| 246 | |
|---|
| 247 | |
|---|
| 248 | // link |
|---|
| 249 | if (array_key_exists('link', $item) && $item['link'] != "") { |
|---|
| 250 | $url = $item['link']; |
|---|
| 251 | } |
|---|
| 252 | elseif (array_key_exists('guid', $item) && $item['guid'] != "") { |
|---|
| 253 | $url = $item['guid']; |
|---|
| 254 | } |
|---|
| 255 | elseif (array_key_exists('link_', $item) && $item['link_'] != "") { |
|---|
| 256 | $url = $item['link_']; |
|---|
| 257 | } |
|---|
| 258 | else { |
|---|
| 259 | // fall back to something basic |
|---|
| 260 | $url = md5($title); |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | // make sure the url is properly escaped |
|---|
| 264 | $url = htmlentities($url, ENT_QUOTES ); |
|---|
| 265 | |
|---|
| 266 | $url = rss_real_escape_string($url); |
|---|
| 267 | |
|---|
| 268 | // author |
|---|
| 269 | if (array_key_exists('dc', $item) && array_key_exists('creator', $item['dc'])) { |
|---|
| 270 | // RSS 1.0 |
|---|
| 271 | $author = $item['dc']['creator']; |
|---|
| 272 | } else if (array_key_exists('author_name', $item)) { |
|---|
| 273 | // Atom 0.3 |
|---|
| 274 | $author = $item['author_name']; |
|---|
| 275 | } else { |
|---|
| 276 | $author = ""; |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | $author = trim(strip_tags($author)); |
|---|
| 280 | |
|---|
| 281 | // pubdate |
|---|
| 282 | $cDate = -1; |
|---|
| 283 | if (array_key_exists('dc', $item) && array_key_exists('date', $item['dc'])) { |
|---|
| 284 | // RSS 1.0 |
|---|
| 285 | $cDate = parse_w3cdtf($item['dc']['date']); |
|---|
| 286 | } |
|---|
| 287 | elseif (array_key_exists('pubdate', $item)) { |
|---|
| 288 | // RSS 2.0 (?) |
|---|
| 289 | // We use the second param of strtotime here as a workaround |
|---|
| 290 | // of a PHP bug with strtotime. If the pubdate field doesn't |
|---|
| 291 | // contain seconds, the strtotime function will use the current |
|---|
| 292 | // time to fill in seconds in PHP4. This interferes with the |
|---|
| 293 | // update mechanism of gregarius. See ticket #328 for the full |
|---|
| 294 | // gory details. Giving a known date as a second param to |
|---|
| 295 | // strtotime fixes this problem, hence the 0 here. |
|---|
| 296 | $cDate = strtotime($item['pubdate'], 0); |
|---|
| 297 | } |
|---|
| 298 | elseif (array_key_exists('published',$item)) { |
|---|
| 299 | // atom 1.0 |
|---|
| 300 | $cDate = parse_iso8601($item['published']); |
|---|
| 301 | } |
|---|
| 302 | elseif (array_key_exists('issued', $item)) { |
|---|
| 303 | //Atom, alternative |
|---|
| 304 | $cDate = parse_iso8601($item['issued']); |
|---|
| 305 | } |
|---|
| 306 | elseif (array_key_exists('updated', $item)) { |
|---|
| 307 | //Atom, alternative |
|---|
| 308 | $cDate = parse_iso8601($item['updated']); |
|---|
| 309 | } |
|---|
| 310 | elseif (array_key_exists('created', $item)) { |
|---|
| 311 | // atom 0.3 |
|---|
| 312 | $cDate = parse_iso8601($item['created']); |
|---|
| 313 | } |
|---|
| 314 | |
|---|
| 315 | // enclosure |
|---|
| 316 | if (array_key_exists('enclosure@url', $item) ) { |
|---|
| 317 | $enclosure = $item['enclosure@url']; |
|---|
| 318 | } else { |
|---|
| 319 | $enclosure = ""; |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | // drop items with an url exceeding our column length: we couldn't provide a |
|---|
| 323 | // valid link back anyway. |
|---|
| 324 | if (strlen($url) >= 255) { |
|---|
| 325 | continue; |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | $dbtitle = rss_real_escape_string($title); |
|---|
| 329 | if (strlen($dbtitle) >= 255) { |
|---|
| 330 | $dbtitle=substr($dbtitle,0,254); |
|---|
| 331 | } |
|---|
| 332 | |
|---|
| 333 | if ($cDate > 0) { |
|---|
| 334 | $sec = "FROM_UNIXTIME($cDate)"; |
|---|
| 335 | } else { |
|---|
| 336 | $sec = "null"; |
|---|
| 337 | } |
|---|
| 338 | |
|---|
| 339 | // check whether we already have this item |
|---|
| 340 | if ($guid) { |
|---|
| 341 | $sql = "select id, i2u.flgunread,i2u.flgdeleted, md5sum, guid, pubdate " |
|---|
| 342 | ."from " |
|---|
| 343 | .getTable('item2user') ." i2u " |
|---|
| 344 | ."left join " |
|---|
| 345 | .getTable('item') ." i " |
|---|
| 346 | ." on (i2u.fkiid=i.id) " |
|---|
| 347 | ." where cid=$cid and guid='$guid'"; |
|---|
| 348 | } else { |
|---|
| 349 | $sql = "select id, i2u.flgunread,i2u.flgdeleted, md5sum, guid, pubdate " |
|---|
| 350 | ."from " |
|---|
| 351 | .getTable('item2user') ." i2u " |
|---|
| 352 | ."left join " |
|---|
| 353 | .getTable('item') ." i " |
|---|
| 354 | ." on (i2u.fkiid=i.id) " |
|---|
| 355 | ." where cid=$cid and url='$url' and title='$dbtitle'" |
|---|
| 356 | ." and (pubdate is NULL OR pubdate=$sec)"; |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | $subres = rss_query($sql); |
|---|
| 360 | list ($indb, $unread,$deleted, $dbmd5sum, $dbGuid, $dbPubDate) = rss_fetch_row($subres); |
|---|
| 361 | |
|---|
| 362 | if ($indb) { |
|---|
| 363 | $itemIdsInFeed[] = $indb; |
|---|
| 364 | if (!$deleted && $md5sum != $dbmd5sum) { |
|---|
| 365 | // the md5sums do not match. |
|---|
| 366 | if($allowUpdates) { // Are we allowed update items in the db? |
|---|
| 367 | list ($cid, $indb, $description) = |
|---|
| 368 | rss_plugin_hook('rss.plugins.items.updated', array ($cid, $indb, $description)); |
|---|
| 369 | |
|---|
| 370 | $sql = "update ".getTable("item") |
|---|
| 371 | ." set "." description='".rss_real_escape_string($description)."', " |
|---|
| 372 | //." unread = unread | ".RSS_MODE_UNREAD_STATE |
|---|
| 373 | ." md5sum='$md5sum'" . " where cid=$cid and id=$indb"; |
|---|
| 374 | |
|---|
| 375 | rss_query($sql); |
|---|
| 376 | |
|---|
| 377 | rss_query("update " .getTable('item2user') . " i2u set i2u.flgunread=1 where i2u.fkiid=$indb"); |
|---|
| 378 | $updatedIds[] = $indb; |
|---|
| 379 | continue; |
|---|
| 380 | } |
|---|
| 381 | } |
|---|
| 382 | } else { // $indb = "" . This must be new item then. In you go. |
|---|
| 383 | |
|---|
| 384 | list ($cid, $dbtitle, $url, $description) = |
|---|
| 385 | rss_plugin_hook('rss.plugins.items.new', array ($cid, $dbtitle, $url, $description)); |
|---|
| 386 | |
|---|
| 387 | $sql = "insert into ".getTable("item") |
|---|
| 388 | ." (cid, added, title, url, enclosure," |
|---|
| 389 | ." description, author, pubdate, md5sum, guid) " |
|---|
| 390 | ." values ("."$cid, now(), '$dbtitle', " |
|---|
| 391 | ." '$url', '".rss_real_escape_string($enclosure)."', '" |
|---|
| 392 | .rss_real_escape_string($description)."', '" |
|---|
| 393 | .rss_real_escape_string($author)."', " |
|---|
| 394 | ." $sec, '$md5sum', '$guid')"; |
|---|
| 395 | |
|---|
| 396 | rss_query($sql); |
|---|
| 397 | |
|---|
| 398 | $newIid = rss_insert_id(); |
|---|
| 399 | $uid=$GLOBALS['rssuser']->getUserId(); |
|---|
| 400 | $prv=($mode & RSS_MODE_PRIVATE_STATE) ?"1":"0"; |
|---|
| 401 | rss_query( |
|---|
| 402 | "insert into " .getTable('item2user') |
|---|
| 403 | ." (fkiid,fkuid,fkcid,flgunread,flgprivate) " |
|---|
| 404 | ." values ($newIid, $uid, $cid, 1, $prv) " |
|---|
| 405 | ); |
|---|
| 406 | |
|---|
| 407 | $itemIdsInFeed[] = $newIid; |
|---|
| 408 | $updatedIds[] = $newIid; |
|---|
| 409 | rss_plugin_hook('rss.plugins.items.newiid',array($newIid,$item,$cid)); |
|---|
| 410 | } // end handling of this item |
|---|
| 411 | |
|---|
| 412 | } // end handling of all the items in this feed |
|---|
| 413 | $sql = "update " .getTable("channels") . " set "." itemsincache = '" |
|---|
| 414 | . serialize($itemIdsInFeed) . "' where id=$cid"; |
|---|
| 415 | rss_query($sql); |
|---|
| 416 | |
|---|
| 417 | |
|---|
| 418 | } // end handling all the feeds we were asked to handle |
|---|
| 419 | |
|---|
| 420 | if ($id != "" && is_numeric($id)) { |
|---|
| 421 | if ($rss) { |
|---|
| 422 | // when everything went well, return the error code |
|---|
| 423 | // and numer of new items |
|---|
| 424 | return array ($rss->rss_origin, $updatedIds); |
|---|
| 425 | } else { |
|---|
| 426 | return array (-1, array ()); |
|---|
| 427 | } |
|---|
| 428 | } else { |
|---|
| 429 | return array (-1, $updatedIds); |
|---|
| 430 | } |
|---|
| 431 | } |
|---|
| 432 | |
|---|
| 433 | function getRootFolder() { |
|---|
| 434 | $sql = "select id from ".getTable("folders")."where name = '' order by position asc limit 1"; |
|---|
| 435 | list($root) = rss_fetch_row(rss_query($sql)); |
|---|
| 436 | |
|---|
| 437 | if (!$root) { |
|---|
| 438 | $root = 0; |
|---|
| 439 | } |
|---|
| 440 | |
|---|
| 441 | return $root; |
|---|
| 442 | } |
|---|
| 443 | |
|---|
| 444 | function add_channel($url, $folderid = 0, $title_=null,$descr_=null,$tags = null) { |
|---|
| 445 | if (!$url || strlen($url) <= 7) { |
|---|
| 446 | return array (-2, "Invalid URL $url"); |
|---|
| 447 | } |
|---|
| 448 | if (!is_numeric($folderid)) { |
|---|
| 449 | return array (-2, "Invalid folderid $folderid"); |
|---|
| 450 | } |
|---|
| 451 | |
|---|
| 452 | $url = sanitize(str_replace('&','&',$url), RSS_SANITIZER_URL); |
|---|
| 453 | |
|---|
| 454 | $urlDB = rss_real_escape_string($url); //htmlentities($url); |
|---|
| 455 | |
|---|
| 456 | $res = rss_query("select count(*) as channel_exists from ".getTable("channels")." where url='$urlDB'"); |
|---|
| 457 | list ($channel_exists) = rss_fetch_row($res); |
|---|
| 458 | if ($channel_exists > 0) { |
|---|
| 459 | // fatal |
|---|
| 460 | return array (-2, "Looks like you are already subscribed to this channel"); |
|---|
| 461 | } |
|---|
| 462 | |
|---|
| 463 | $res = rss_query("select 1+max(position) as np from ".getTable("channels")); |
|---|
| 464 | list ($np) = rss_fetch_row($res); |
|---|
| 465 | |
|---|
| 466 | if (!$np) { |
|---|
| 467 | $np = "0"; |
|---|
| 468 | } |
|---|
| 469 | |
|---|
| 470 | // Here we go! |
|---|
| 471 | //error_reporting(E_ALL); |
|---|
| 472 | $old_level = error_reporting(E_ERROR); |
|---|
| 473 | $rss = fetch_rss($url); |
|---|
| 474 | error_reporting($old_level); |
|---|
| 475 | |
|---|
| 476 | |
|---|
| 477 | if ($rss) { |
|---|
| 478 | if ($title_) { |
|---|
| 479 | $title = rss_real_escape_string($title_); |
|---|
| 480 | } |
|---|
| 481 | elseif (is_object($rss) && array_key_exists('title#', $rss->channel)) { |
|---|
| 482 | if (array_key_exists('title', $rss->channel)) { |
|---|
| 483 | $title = rss_real_escape_string($rss->channel['title']); |
|---|
| 484 | } else { |
|---|
| 485 | $title = " "; |
|---|
| 486 | } |
|---|
| 487 | } |
|---|
| 488 | else { |
|---|
| 489 | $title = ""; |
|---|
| 490 | } |
|---|
| 491 | |
|---|
| 492 | if (is_object($rss) && array_key_exists('link', $rss->channel)) { |
|---|
| 493 | $siteurl = rss_real_escape_string(htmlentities($rss->channel['link'])); |
|---|
| 494 | } else { |
|---|
| 495 | $siteurl = ""; |
|---|
| 496 | } |
|---|
| 497 | |
|---|
| 498 | if ($descr_) { |
|---|
| 499 | $descr = rss_real_escape_string($descr_); |
|---|
| 500 | } |
|---|
| 501 | elseif (is_object($rss) && array_key_exists('description', $rss->channel)) { |
|---|
| 502 | $descr = rss_real_escape_string($rss->channel['description']); |
|---|
| 503 | } |
|---|
| 504 | else { |
|---|
| 505 | $descr = ""; |
|---|
| 506 | } |
|---|
| 507 | |
|---|
| 508 | //lets see if this server has a favicon |
|---|
| 509 | $icon = ""; |
|---|
| 510 | if (getConfig('rss.output.showfavicons')) { |
|---|
| 511 | // if we got nothing so far, lets try to fall back to |
|---|
| 512 | // favicons |
|---|
| 513 | if ($icon == "" && $siteurl != "") { |
|---|
| 514 | $match = get_host($siteurl, $host); |
|---|
| 515 | $uri = "http://".$host."favicon.ico"; |
|---|
| 516 | if ($match && getContentType($uri, $contentType)) { |
|---|
| 517 | if (preg_match("/image\/x-icon/", $contentType)) { |
|---|
| 518 | $icon = $uri; |
|---|
| 519 | } |
|---|
| 520 | } |
|---|
| 521 | } |
|---|
| 522 | } |
|---|
| 523 | |
|---|
| 524 | $private = preg_match('|(https?://)([^:]+:[^@]+@)(.+)$|',$url); |
|---|
| 525 | |
|---|
| 526 | if ($title != "") { |
|---|
| 527 | $title = strip_tags($title); |
|---|
| 528 | $descr = strip_tags($descr); |
|---|
| 529 | |
|---|
| 530 | // add channel to root folder by default |
|---|
| 531 | if(!$folderid) { |
|---|
| 532 | $folderid = getRootFolder(); |
|---|
| 533 | } |
|---|
| 534 | |
|---|
| 535 | list($title,$urlDB,$siteurl,$folderid,$descr,$icon) = |
|---|
| 536 | rss_plugin_hook('rss.plugins.feed.new', |
|---|
| 537 | array ($title,$urlDB,$siteurl,$folderid,$descr,$icon)); |
|---|
| 538 | |
|---|
| 539 | $mode = RSS_MODE_UNREAD_STATE; |
|---|
| 540 | if ($private) { |
|---|
| 541 | $mode |= RSS_MODE_PRIVATE_STATE; |
|---|
| 542 | } |
|---|
| 543 | |
|---|
| 544 | $sql = "insert into ".getTable("channels") |
|---|
| 545 | ." (title, url, siteurl, parent, descr, dateadded, icon, position, mode, daterefreshed)" |
|---|
| 546 | ." values ('$title', '$urlDB', '$siteurl', $folderid, '$descr', now(), '$icon', $np, $mode, '0000-00-00 00:00:00')"; |
|---|
| 547 | |
|---|
| 548 | rss_query($sql); |
|---|
| 549 | $newid = rss_insert_id(); |
|---|
| 550 | |
|---|
| 551 | if ($icon && cacheFavicon($icon)) { |
|---|
| 552 | rss_query("update " . getTable("channels") . " set icon='blob:".$icon."'" |
|---|
| 553 | ." where id=$newid"); |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | if($tags != ""){ |
|---|
| 557 | __exp__submitTag($newid,$tags,"'channel'"); |
|---|
| 558 | } |
|---|
| 559 | |
|---|
| 560 | return array ($newid, ""); |
|---|
| 561 | |
|---|
| 562 | } else { |
|---|
| 563 | // non-fatal, will look further |
|---|
| 564 | return array (-1, "I'm sorry, I couldn't extract a valid RSS feed from <a href=\"$url\">$url</a>."); |
|---|
| 565 | } |
|---|
| 566 | } else { |
|---|
| 567 | global $MAGPIE_ERROR; |
|---|
| 568 | $retError = "I'm sorry, I couldn't retrieve <a href=\"$url\">$url</a>."; |
|---|
| 569 | if ($MAGPIE_ERROR) { |
|---|
| 570 | $retError .= "\n<br />$MAGPIE_ERROR\n"; |
|---|
| 571 | } |
|---|
| 572 | // non-fatal, will look further |
|---|
| 573 | return array (-1, $retError); |
|---|
| 574 | } |
|---|
| 575 | } |
|---|
| 576 | |
|---|
| 577 | /** |
|---|
| 578 | * Replaces relative urls with absolute ones for anchors and images |
|---|
| 579 | * Credits: Julien Mudry |
|---|
| 580 | */ |
|---|
| 581 | function relative_to_absolute($content, $feed_url) { |
|---|
| 582 | preg_match('/(http|https|ftp):\/\//', $feed_url, $protocol); |
|---|
| 583 | $server_url = preg_replace("/(http|https|ftp|news):\/\//", "", $feed_url); |
|---|
| 584 | $server_url = preg_replace("/\/.*/", "", $server_url); |
|---|
| 585 | |
|---|
| 586 | if ($server_url == '') { |
|---|
| 587 | return $content; |
|---|
| 588 | } |
|---|
| 589 | |
|---|
| 590 | if (isset($protocol[0])) { |
|---|
| 591 | $new_content = preg_replace('/href="\//', 'href="'.$protocol[0].$server_url.'/', $content); |
|---|
| 592 | $new_content = preg_replace('/src="\//', 'src="'.$protocol[0].$server_url.'/', $new_content); |
|---|
| 593 | } else { |
|---|
| 594 | $new_content = $content; |
|---|
| 595 | } |
|---|
| 596 | return $new_content; |
|---|
| 597 | } |
|---|
| 598 | |
|---|
| 599 | /** |
|---|
| 600 | * parse an ISO 8601 date, losely based on parse_w3cdtf from MagpieRSS |
|---|
| 601 | */ |
|---|
| 602 | function parse_iso8601($date_str) { |
|---|
| 603 | # regex to match wc3dtf |
|---|
| 604 | $pat = "/(\d{4})-?(\d{2})-?(\d{2})T?(\d{2}):?(\d{2})(:?(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/"; |
|---|
| 605 | |
|---|
| 606 | if (preg_match($pat, $date_str, $match)) { |
|---|
| 607 | list |
|---|