PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/system/modules/rss/mod.rss.php

https://github.com/danboy/Croissierd
PHP | 655 lines | 533 code | 64 blank | 58 comment | 45 complexity | 7ff29e546f4323555e32583530545927 MD5 | raw file
  1. <?php
  2. /*
  3. =====================================================
  4. ExpressionEngine - by EllisLab
  5. -----------------------------------------------------
  6. http://expressionengine.com/
  7. -----------------------------------------------------
  8. Copyright (c) 2003 - 2010 EllisLab, Inc.
  9. =====================================================
  10. THIS IS COPYRIGHTED SOFTWARE
  11. PLEASE READ THE LICENSE AGREEMENT
  12. http://expressionengine.com/docs/license.html
  13. =====================================================
  14. File: mod.rss.php
  15. -----------------------------------------------------
  16. Purpose: RSS generating class
  17. =====================================================
  18. */
  19. if ( ! defined('EXT'))
  20. {
  21. exit('Invalid file request');
  22. }
  23. class Rss {
  24. var $debug = FALSE;
  25. /** -------------------------------------
  26. /** RSS feed
  27. /** -------------------------------------*/
  28. // This function fetches the weblog metadata used in
  29. // the channel section of RSS feeds
  30. // Note: The item elements are generated using the weblog class
  31. function feed()
  32. {
  33. global $DB, $LOC, $LANG, $TMPL, $FNS, $OUT, $PREFS;
  34. $TMPL->encode_email = FALSE;
  35. if ($TMPL->fetch_param('debug') == 'yes')
  36. {
  37. $this->debug = TRUE;
  38. }
  39. if (USER_BLOG !== FALSE)
  40. {
  41. $weblog = USER_BLOG;
  42. }
  43. else
  44. {
  45. if ( ! $weblog = $TMPL->fetch_param('weblog'))
  46. {
  47. $LANG->fetch_language_file('rss');
  48. return $this->_empty_feed($LANG->line('no_weblog_specified'));
  49. }
  50. }
  51. /** ------------------------------------------
  52. /** Create Meta Query
  53. /** ------------------------------------------*/
  54. // Since UTC_TIMESTAMP() is what we need, but it is not available until
  55. // MySQL 4.1.1, we have to use this ever so clever SQL to figure it out:
  56. // DATE_ADD( '1970-01-01', INTERVAL UNIX_TIMESTAMP() SECOND )
  57. // -Paul
  58. $sql = "SELECT exp_weblog_titles.entry_id, exp_weblog_titles.entry_date, exp_weblog_titles.edit_date,
  59. GREATEST((UNIX_TIMESTAMP(exp_weblog_titles.edit_date) +
  60. (UNIX_TIMESTAMP(DATE_ADD( '1970-01-01', INTERVAL UNIX_TIMESTAMP() SECOND)) - UNIX_TIMESTAMP())),
  61. exp_weblog_titles.entry_date) AS last_update
  62. FROM exp_weblog_titles
  63. LEFT JOIN exp_weblogs ON exp_weblog_titles.weblog_id = exp_weblogs.weblog_id
  64. LEFT JOIN exp_members ON exp_members.member_id = exp_weblog_titles.author_id
  65. WHERE exp_weblog_titles.entry_id !=''
  66. AND exp_weblogs.site_id IN ('".implode("','", $TMPL->site_ids)."') ";
  67. if (USER_BLOG !== FALSE)
  68. {
  69. $sql .= "AND exp_weblogs.weblog_id = '".UB_BLOG_ID."' ";
  70. }
  71. else
  72. {
  73. $sql .= "AND exp_weblogs.is_user_blog = 'n' ";
  74. $xql = "SELECT weblog_id FROM exp_weblogs WHERE ";
  75. $str = $FNS->sql_andor_string($weblog, 'blog_name');
  76. if (substr($str, 0, 3) == 'AND')
  77. $str = substr($str, 3);
  78. $xql .= $str;
  79. $query = $DB->query($xql);
  80. if ($query->num_rows == 0)
  81. {
  82. $LANG->fetch_language_file('rss');
  83. return $this->_empty_feed($LANG->line('rss_invalid_weblog'));
  84. }
  85. if ($query->num_rows == 1)
  86. {
  87. $sql .= "AND exp_weblog_titles.weblog_id = '".$query->row['weblog_id']."' ";
  88. }
  89. else
  90. {
  91. $sql .= "AND (";
  92. foreach ($query->result as $row)
  93. {
  94. $sql .= "exp_weblog_titles.weblog_id = '".$row['weblog_id']."' OR ";
  95. }
  96. $sql = substr($sql, 0, - 3);
  97. $sql .= ") ";
  98. }
  99. }
  100. /** ----------------------------------------------
  101. /** We only select entries that have not expired
  102. /** ----------------------------------------------*/
  103. $timestamp = ($TMPL->cache_timestamp != '') ? $LOC->set_gmt($TMPL->cache_timestamp) : $LOC->now;
  104. if ($TMPL->fetch_param('show_future_entries') != 'yes')
  105. {
  106. $sql .= " AND exp_weblog_titles.entry_date < ".$timestamp." ";
  107. }
  108. if ($TMPL->fetch_param('show_expired') != 'yes')
  109. {
  110. $sql .= " AND (exp_weblog_titles.expiration_date = 0 OR exp_weblog_titles.expiration_date > ".$timestamp.") ";
  111. }
  112. /** ----------------------------------------------
  113. /** Add status declaration
  114. /** ----------------------------------------------*/
  115. $sql .= "AND exp_weblog_titles.status != 'closed' ";
  116. if ($status = $TMPL->fetch_param('status'))
  117. {
  118. $status = str_replace('Open', 'open', $status);
  119. $status = str_replace('Closed', 'closed', $status);
  120. $sql .= $FNS->sql_andor_string($status, 'exp_weblog_titles.status');
  121. }
  122. else
  123. {
  124. $sql .= "AND exp_weblog_titles.status = 'open' ";
  125. }
  126. /** ----------------------------------------------
  127. /** Limit to (or exclude) specific users
  128. /** ----------------------------------------------*/
  129. if ($username = $TMPL->fetch_param('username'))
  130. {
  131. // Shows entries ONLY for currently logged in user
  132. if ($username == 'CURRENT_USER')
  133. {
  134. $sql .= "AND exp_members.member_id = '".$SESS->userdata['member_id']."' ";
  135. }
  136. elseif ($username == 'NOT_CURRENT_USER')
  137. {
  138. $sql .= "AND exp_members.member_id != '".$SESS->userdata['member_id']."' ";
  139. }
  140. else
  141. {
  142. $sql .= $FNS->sql_andor_string($username, 'exp_members.username');
  143. }
  144. }
  145. // Find Edit Date
  146. $query = $DB->query($sql." ORDER BY last_update desc LIMIT 1");
  147. if ($query->num_rows > 0)
  148. {
  149. $last_update = $query->row['last_update'] + ($LOC->set_server_time() - $LOC->now);
  150. $edit_date = $query->row['edit_date'];
  151. $entry_date = $query->row['entry_date'];
  152. }
  153. $sql .= " ORDER BY exp_weblog_titles.entry_date desc LIMIT 1";
  154. $query = $DB->query($sql);
  155. if ($query->num_rows == 0)
  156. {
  157. $LANG->fetch_language_file('rss');
  158. return $this->_empty_feed($LANG->line('no_matching_entries'));
  159. }
  160. $entry_id = $query->row['entry_id'];
  161. $sql = "SELECT exp_weblogs.weblog_id, exp_weblogs.blog_title, exp_weblogs.blog_url, exp_weblogs.blog_lang, exp_weblogs.blog_encoding, exp_weblogs.blog_description,
  162. exp_weblog_titles.entry_date,
  163. exp_members.email, exp_members.username, exp_members.screen_name, exp_members.url
  164. FROM exp_weblog_titles
  165. LEFT JOIN exp_weblogs ON exp_weblog_titles.weblog_id = exp_weblogs.weblog_id
  166. LEFT JOIN exp_members ON exp_members.member_id = exp_weblog_titles.author_id
  167. WHERE exp_weblog_titles.entry_id = '$entry_id'
  168. AND exp_weblogs.site_id IN ('".implode("','", $TMPL->site_ids)."') ";
  169. $query = $DB->query($sql);
  170. foreach ($query->row as $key => $val)
  171. {
  172. $$key = $val;
  173. }
  174. $request = ( ! function_exists('getallheaders')) ? array() : @getallheaders();
  175. $start_on = '';
  176. $diffe_request = false;
  177. $feed_request = false;
  178. /** --------------------------------------------
  179. /** Check for 'diff -e' request
  180. /** --------------------------------------------*/
  181. if (isset($request['A-IM']) && stristr($request['A-IM'],'diffe') !== false)
  182. {
  183. $items_start = strpos($TMPL->tagdata, '{exp:weblog:entries');
  184. if ($items_start !== false)
  185. {
  186. // We add three, for three line breaks added later in the script
  187. $diffe_request = count(preg_split("/(\r\n)|(\r)|(\n)/", trim(substr($TMPL->tagdata,0,$items_start)))) + 3;
  188. }
  189. }
  190. /** --------------------------------------------
  191. /** Check for 'feed' request
  192. /** --------------------------------------------*/
  193. if (isset($request['A-IM']) && stristr($request['A-IM'],'feed') !== false)
  194. {
  195. $feed_request = true;
  196. $diffe_request = false;
  197. }
  198. /** --------------------------------------------
  199. /** Check for the 'If-Modified-Since' Header
  200. /** --------------------------------------------*/
  201. if ($PREFS->ini('send_headers') == 'y' && isset($request['If-Modified-Since']) && trim($request['If-Modified-Since']) != '')
  202. {
  203. $x = explode(';',$request['If-Modified-Since']);
  204. $modify_tstamp = strtotime($x['0']);
  205. // ---------------------------------------------------------
  206. // If new content *and* 'feed' or 'diffe', create start on time.
  207. // Otherwise, we send back a Not Modified header
  208. // ---------------------------------------------------------
  209. if ($last_update <= $modify_tstamp)
  210. {
  211. $OUT->http_status_header(304);
  212. @exit;
  213. }
  214. else
  215. {
  216. if ($diffe_request !== false OR $feed_request !== false)
  217. {
  218. //$start_on = $LOC->set_human_time($LOC->set_server_time($modify_tstamp), FALSE);
  219. $start_on = gmdate('Y-m-d h:i A',$LOC->set_localized_time($modify_tstamp));
  220. }
  221. }
  222. }
  223. $chunks = array();
  224. $marker = 'H94e99Perdkie0393e89vqpp';
  225. if (preg_match_all("/{exp:weblog:entries.+?{".SLASH."exp:weblog:entries}/s", $TMPL->tagdata, $matches))
  226. {
  227. for($i = 0; $i < count($matches['0']); $i++)
  228. {
  229. $TMPL->tagdata = str_replace($matches['0'][$i], $marker.$i, $TMPL->tagdata);
  230. // Remove limit if we have a start_on and dynamic_start
  231. if ($start_on != '' && stristr($matches['0'][$i],'dynamic_start="on"'))
  232. {
  233. $matches['0'][$i] = preg_replace("/limit=[\"\'][0-9]{1,5}[\"\']/", '', $matches['0'][$i]);
  234. }
  235. // Replace dynamic_start="on" parameter with start_on="" param
  236. $start_on_switch = ($start_on != '') ? 'start_on="'.$start_on.'"' : '';
  237. $matches['0'][$i] = preg_replace("/dynamic_start\s*=\s*[\"|']on[\"|']/i", $start_on_switch, $matches['0'][$i]);
  238. $chunks[$marker.$i] = $matches['0'][$i];
  239. }
  240. }
  241. /** ----------------------------------------
  242. /** Fetch all the date-related variables
  243. /** ----------------------------------------*/
  244. // We do this here to avoid processing cycles in the foreach loop
  245. $entry_date_array = array();
  246. $gmt_date_array = array();
  247. $gmt_entry_date_array = array();
  248. $edit_date_array = array();
  249. $gmt_edit_date_array = array();
  250. $date_vars = array('date', 'gmt_date', 'gmt_entry_date', 'edit_date', 'gmt_edit_date');
  251. foreach ($date_vars as $val)
  252. {
  253. if (preg_match_all("/".LD.$val."\s+format=[\"'](.*?)[\"']".RD."/s", $TMPL->tagdata, $matches))
  254. {
  255. for ($j = 0; $j < count($matches['0']); $j++)
  256. {
  257. $matches['0'][$j] = str_replace(LD, '', $matches['0'][$j]);
  258. $matches['0'][$j] = str_replace(RD, '', $matches['0'][$j]);
  259. switch ($val)
  260. {
  261. case 'date' : $entry_date_array[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
  262. break;
  263. case 'gmt_date' : $gmt_date_array[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
  264. break;
  265. case 'gmt_entry_date' : $gmt_entry_date_array[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
  266. break;
  267. case 'edit_date' : $edit_date_array[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
  268. break;
  269. case 'gmt_edit_date' : $gmt_edit_date_array[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
  270. break;
  271. }
  272. }
  273. }
  274. }
  275. foreach ($TMPL->var_single as $key => $val)
  276. {
  277. /** ----------------------------------------
  278. /** {weblog_id}
  279. /** ----------------------------------------*/
  280. if ($key == 'weblog_id')
  281. {
  282. $TMPL->tagdata = $TMPL->swap_var_single(
  283. $key,
  284. $weblog_id,
  285. $TMPL->tagdata
  286. );
  287. }
  288. /** ----------------------------------------
  289. /** {encoding}
  290. /** ----------------------------------------*/
  291. if ($key == 'encoding')
  292. {
  293. $TMPL->tagdata = $TMPL->swap_var_single(
  294. $key,
  295. $blog_encoding,
  296. $TMPL->tagdata
  297. );
  298. }
  299. /** ----------------------------------------
  300. /** {weblog_language}
  301. /** ----------------------------------------*/
  302. if ($key == 'weblog_language')
  303. {
  304. $TMPL->tagdata = $TMPL->swap_var_single(
  305. $key,
  306. $blog_lang,
  307. $TMPL->tagdata
  308. );
  309. }
  310. /** ----------------------------------------
  311. /** {weblog_description}
  312. /** ----------------------------------------*/
  313. if ($key == 'weblog_description')
  314. {
  315. $TMPL->tagdata = $TMPL->swap_var_single(
  316. $key,
  317. $blog_description,
  318. $TMPL->tagdata
  319. );
  320. }
  321. /** ----------------------------------------
  322. /** {weblog_url}
  323. /** ----------------------------------------*/
  324. if ($key == 'weblog_url')
  325. {
  326. $TMPL->tagdata = $TMPL->swap_var_single(
  327. $key,
  328. $blog_url,
  329. $TMPL->tagdata
  330. );
  331. }
  332. /** ----------------------------------------
  333. /** {weblog_name}
  334. /** ----------------------------------------*/
  335. if ($key == 'weblog_name')
  336. {
  337. $TMPL->tagdata = $TMPL->swap_var_single(
  338. $key,
  339. $blog_title,
  340. $TMPL->tagdata
  341. );
  342. }
  343. /** ----------------------------------------
  344. /** {email}
  345. /** ----------------------------------------*/
  346. if ($key == 'email')
  347. {
  348. $TMPL->tagdata = $TMPL->swap_var_single(
  349. $key,
  350. $email,
  351. $TMPL->tagdata
  352. );
  353. }
  354. /** ----------------------------------------
  355. /** {url}
  356. /** ----------------------------------------*/
  357. if ($key == 'url')
  358. {
  359. $TMPL->tagdata = $TMPL->swap_var_single(
  360. $key,
  361. $url,
  362. $TMPL->tagdata
  363. );
  364. }
  365. /** ----------------------------------------
  366. /** {date}
  367. /** ----------------------------------------*/
  368. if (isset($entry_date_array[$key]))
  369. {
  370. foreach ($entry_date_array[$key] as $dvar)
  371. $val = str_replace($dvar, $LOC->convert_timestamp($dvar, $entry_date, TRUE), $val);
  372. $TMPL->tagdata = $TMPL->swap_var_single($key, $val, $TMPL->tagdata);
  373. }
  374. /** ----------------------------------------
  375. /** GMT date - entry date in GMT
  376. /** ----------------------------------------*/
  377. if (isset($gmt_entry_date_array[$key]))
  378. {
  379. foreach ($gmt_entry_date_array[$key] as $dvar)
  380. $val = str_replace($dvar, $LOC->convert_timestamp($dvar, $entry_date, FALSE), $val);
  381. $TMPL->tagdata = $TMPL->swap_var_single($key, $val, $TMPL->tagdata);
  382. }
  383. if (isset($gmt_date_array[$key]))
  384. {
  385. foreach ($gmt_date_array[$key] as $dvar)
  386. $val = str_replace($dvar, $LOC->convert_timestamp($dvar, $entry_date, FALSE), $val);
  387. $TMPL->tagdata = $TMPL->swap_var_single($key, $val, $TMPL->tagdata);
  388. }
  389. /** ----------------------------------------
  390. /** parse "last edit" date
  391. /** ----------------------------------------*/
  392. if (isset($edit_date_array[$key]))
  393. {
  394. foreach ($edit_date_array[$key] as $dvar)
  395. $val = str_replace($dvar, $LOC->convert_timestamp($dvar, $edit_date, TRUE), $val);
  396. $TMPL->tagdata = $TMPL->swap_var_single($key, $val, $TMPL->tagdata);
  397. }
  398. /** ----------------------------------------
  399. /** "last edit" date as GMT
  400. /** ----------------------------------------*/
  401. if (isset($gmt_edit_date_array[$key]))
  402. {
  403. foreach ($gmt_edit_date_array[$key] as $dvar)
  404. $val = str_replace($dvar, $LOC->convert_timestamp($dvar, $LOC->timestamp_to_gmt($edit_date), FALSE), $val);
  405. $TMPL->tagdata = $TMPL->swap_var_single($key, $val, $TMPL->tagdata);
  406. }
  407. /** ----------------------------------------
  408. /** {author}
  409. /** ----------------------------------------*/
  410. if ($key == 'author')
  411. {
  412. $TMPL->tagdata = $TMPL->swap_var_single($val, ($screen_name != '') ? $screen_name : $username, $TMPL->tagdata);
  413. }
  414. /** ----------------------------------------
  415. /** {version}
  416. /** ----------------------------------------*/
  417. if ($key == 'version')
  418. {
  419. $TMPL->tagdata = $TMPL->swap_var_single($val, APP_VER, $TMPL->tagdata);
  420. }
  421. /** ----------------------------------------
  422. /** {trimmed_url} - used by Atom feeds
  423. /** ----------------------------------------*/
  424. if ($key == "trimmed_url")
  425. {
  426. $blog_url = (isset($blog_url) AND $blog_url != '') ? $blog_url : '';
  427. $blog_url = str_replace('http://', '', $blog_url);
  428. $blog_url = str_replace('www.', '', $blog_url);
  429. $ex = explode("/", $blog_url);
  430. $blog_url = current($ex);
  431. $TMPL->tagdata = $TMPL->swap_var_single($val, $blog_url, $TMPL->tagdata);
  432. }
  433. }
  434. if (count($chunks) > 0)
  435. {
  436. $diff_top = ($start_on != '' && $diffe_request !== false) ? "1,".($diffe_request-1)."c\n" : '';
  437. // Last Update Time
  438. $TMPL->tagdata = '<ee:last_update>'.$last_update."</ee:last_update>\n\n".$diff_top.trim($TMPL->tagdata);
  439. // Diffe stuff before items
  440. if ($diffe_request !== false)
  441. {
  442. $TMPL->tagdata = str_replace($marker.'0', "\n.\n".$diffe_request."a\n".$marker.'0', $TMPL->tagdata);
  443. $TMPL->tagdata = str_replace($marker.(count($chunks)-1), $marker.(count($chunks)-1)."\n.\n$\n-1\n;c\n", $TMPL->tagdata);
  444. }
  445. foreach ($chunks as $key => $val)
  446. {
  447. $TMPL->tagdata = str_replace($key, $val, $TMPL->tagdata);
  448. }
  449. }
  450. // 'ed' input mode is terminated by entering a single period (.) on a line
  451. $TMPL->tagdata = ($diffe_request !== false) ? trim($TMPL->tagdata)."\n.\n" : trim($TMPL->tagdata);
  452. return $TMPL->tagdata;
  453. }
  454. /* END */
  455. /** -------------------------------------
  456. /** Empty feed handler
  457. /** -------------------------------------*/
  458. function _empty_feed($error = '')
  459. {
  460. global $FNS, $TMPL;
  461. if ($error != '')
  462. {
  463. $TMPL->log_item($error);
  464. }
  465. $empty_feed = '';
  466. if (preg_match("/".LD."if empty_feed".RD."(.*?)".LD.SLASH."if".RD."/s", $TMPL->tagdata, $match))
  467. {
  468. if (stristr($match['1'], LD.'if'))
  469. {
  470. $match['0'] = $FNS->full_tag($match['0'], $TMPL->tagdata, LD.'if', LD.SLASH."if".RD);
  471. }
  472. $empty_feed = substr($match['0'], strlen(LD."if empty_feed".RD), -strlen(LD.SLASH."if".RD));
  473. $empty_feed = str_replace(LD.'error'.RD, $error, $empty_feed);
  474. }
  475. if ($empty_feed == '')
  476. {
  477. $empty_feed = $this->_default_empty_feed($error);
  478. }
  479. return $empty_feed;
  480. }
  481. /* END */
  482. /** -------------------------------------
  483. /** Default empty feed
  484. /** -------------------------------------*/
  485. function _default_empty_feed($error = '')
  486. {
  487. global $LANG, $LOC, $PREFS;
  488. $LANG->fetch_language_file('rss');
  489. $encoding = $PREFS->ini('charset');
  490. $title = $PREFS->ini('site_name');
  491. $link = $PREFS->ini('site_url');
  492. $version = APP_VER;
  493. $pubdate = date('D, d M Y H:i:s', $LOC->now).' GMT';
  494. $content = ($this->debug === TRUE && $error != '') ? $error : $LANG->line('empty_feed');
  495. return <<<HUMPTYDANCE
  496. <?xml version="1.0" encoding="{$encoding}"?>
  497. <rss version="2.0">
  498. <channel>
  499. <title>{$title}</title>
  500. <link>{$link}</link>
  501. <description></description>
  502. <docs>http://www.rssboard.org/rss-specification</docs>
  503. <generator>ExpressionEngine v{$version} http://expressionengine.com/</generator>
  504. <item>
  505. <title>{$content}</title>
  506. <description>{$content}</description>
  507. <pubDate>{$pubdate}</pubDate>
  508. </item>
  509. </channel>
  510. </rss>
  511. HUMPTYDANCE;
  512. }
  513. /* END */
  514. }
  515. // END CLASS
  516. ?>