PageRenderTime 46ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/forum/gym_sitemaps/includes/gym_rss.php

https://github.com/GreyTeardrop/socionicasys-forum
PHP | 714 lines | 549 code | 5 blank | 160 comment | 128 complexity | 85f02cc21660749a1bfddf4fd8e01b78 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-3.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. *
  4. * @package phpBB SEO GYM Sitemaps
  5. * @version $Id: gym_rss.php 314 2011-06-27 08:21:34Z dcz $
  6. * @copyright (c) 2006 - 2010 www.phpbb-seo.com
  7. * @license http://opensource.org/osi3.0/licenses/lgpl-license.php GNU Lesser General Public License
  8. *
  9. */
  10. // First basic security
  11. if ( !defined('IN_PHPBB') ) {
  12. exit;
  13. }
  14. require_once($phpbb_root_path . 'gym_sitemaps/includes/gym_sitemaps.' . $phpEx);
  15. /**
  16. * gym_rss Class
  17. * www.phpBB-SEO.com
  18. * @package phpBB SEO
  19. */
  20. class gym_rss extends gym_sitemaps {
  21. var $rss_config = array();
  22. /**
  23. * constuctor
  24. */
  25. function gym_rss() {
  26. global $phpbb_seo, $phpEx, $config, $user;
  27. global $db, $auth;
  28. $this->gym_sitemaps('rss');
  29. // init output
  30. $this->output_data['showstats'] = (boolean) ($this->gym_config['gym_showstats'] || $this->gym_config['rss_showstats']);
  31. // Check the main vars
  32. $this->init_get_vars();
  33. // url without IDs like forum feed url in case the phpBB SEO mod are used and set so
  34. // and basic parameter for url such as blabla/news/digest/long/module-rss.xml => gymrss.php?module=blabla&news&digest&long
  35. if ( isset($_GET['nametoid']) && !empty($_GET['nametoid']) && isset($_GET['modulename']) && !empty($_GET['modulename']) && empty($this->actions['module_main']) && empty($this->actions['module_sub']) ) {
  36. $module_name = trim(strtolower($_GET['modulename']));
  37. // is the module available ?
  38. if (in_array($module_name, $this->actions['action_modules'])) {
  39. $this->actions['module_main'] = $module_name;
  40. // Do we get an id (?module=id)
  41. if ($id = @array_search(trim($_GET['nametoid']), $phpbb_seo->cache_config[$module_name]) ) {
  42. $this->actions['module_sub'] = intval($id);
  43. } else { // Pass the variable to the script ?module_name=$_GET['nametoid']
  44. $this->actions['module_sub'] = trim(utf8_htmlspecialchars(str_replace(array("\n", "\r"), '', $_GET['nametoid'])));
  45. }
  46. }
  47. }
  48. if (empty($this->actions['action_modules'])) {
  49. $this->gym_error(404, '', __FILE__, __LINE__);
  50. }
  51. // Set last mod time from DB, will only be used as his for general feeds and channel lists
  52. // put it into phpbb config for the dynamic property.
  53. $config_name = $this->actions['action_type'] . '_' . (!empty($this->actions['module_main']) ? $this->actions['module_main'] . '_' : '') . 'last_mod_time';
  54. if (@$config[$config_name] < $config['board_startdate']) {
  55. set_config($config_name, $user->time_now, 1);
  56. }
  57. $this->output_data['last_mod_time'] = intval($config[$config_name]);
  58. // Init the output class
  59. $this->gym_init_output();
  60. // Setup the output
  61. $this->cache_config = array_merge(
  62. // Global
  63. $this->cache_config,
  64. // Other stuff required here
  65. array(
  66. 'cache_enable' => (boolean) $this->set_module_option('cache_on', $this->override['cache']),
  67. 'cache_auto_regen' => (boolean) $this->set_module_option('cache_auto_regen', $this->override['cache']),
  68. 'cache_force_gzip' => (boolean) $this->set_module_option('cache_force_gzip', $this->override['cache']),
  69. 'cache_born' => $this->output_data['last_mod_time'],
  70. 'cache_max_age' => round($this->set_module_option('cache_max_age', $this->override['cache']),2) * 3600,
  71. 'cache_file_ext' => ( $this->gym_output->gzip_config['gzip'] || $this->gym_config['rss_cache_force_gzip'] ) ? '.xml.gz' : '.xml',
  72. )
  73. );
  74. // Can you believe it, sprintf is faster than straight parsing.
  75. $this->style_config = array(
  76. 'rss_header' => '<'.'?xml version="1.0" encoding="utf-8"?'.'>%s' . "\n" . '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"' . "\n\t" . 'xmlns:content="http://purl.org/rss/1.0/modules/content/"' . "\n\t" . 'xmlns:atom="http://www.w3.org/2005/Atom">' . "\n" . '<!-- Generated by Google Yahoo MSN Sitemaps and RSS %s - &#169; 2006, ' . date('Y') . ' www.phpBB-SEO.com -->',
  77. 'rss_footer' => "\n\t" . '</channel>' . "\n" . '</rss>',
  78. 'rss_item_tpl' => "\n\t\t" . '<item>' . "\n\t\t\t" . '<title>%1$s</title>'. "\n\t\t\t" . '<link>%2$s</link>%3$s' . "\n\t\t\t" . '<description>%4$s</description>%8$s' . "\n\t\t\t" . '<source url="%5$s">%6$s</source>' . "\n\t\t\t" . '<guid isPermaLink="true">%7$s</guid>' . "\n\t\t" . '</item>',
  79. 'rsschan_tpl' => "\n\t" . '<channel>' . "\n\t\t" . '<title>%1$s</title>' . "\n\t\t" . '<link>%2$s</link>' . "\n\t\t" . '<description>%3$s</description>%4$s' . "\n\t\t" . '%5$s' . "\n\t\t" . '<docs>http://blogs.law.harvard.edu/tech/rss</docs>' . "\n\t\t" . '<generator>Google Yahoo MSN Sitemaps and RSS ' . $this->gym_config['gym_version'] . ' - &#169; 2006, ' . date('Y') . ' www.phpBB-SEO.com</generator>%6$s' . "\n\t\t" . '<atom:link href="%7$s" rel="self" type="application/rss+xml" />%8$s',
  80. 'rsschan_input_tpl' => "\n\t\t" . '<textInput>' . "\n\t\t\t" . '<title>%1$s</title>' . "\n\t\t\t" . '<description>%2$s</description>' . "\n\t\t\t" . '<link>%3$s</link>' . "\n\t\t\t" . '<name>%4$s</name>' . "\n\t\t" . '</textInput>' . "\n",
  81. 'rsschan_img_tpl' => '<image>' . "\n\t\t\t" . '<title>%1$s</title>' . "\n\t\t\t" . '<url>%2$s</url>' . "\n\t\t\t" . '<link>%3$s</link>' . "\n\t\t" . '</image>',
  82. 'chan_lastbuildate_tpl' => "\n\t\t" . '<lastBuildDate>%1$s</lastBuildDate>',
  83. 'chan_ttl_tpl' => "\n\t\t" . '<ttl>%1$s</ttl>',
  84. 'item_pubdate_tpl' => "\n\t\t\t" . '<pubDate>%1$s</pubDate>',
  85. 'item_creator_tpl' => "\n\t\t\t" . '<dc:creator>%1$s</dc:creator>',
  86. 'xslt_style' => '',
  87. 'stats_genlist' => "\n" . '<!-- URL list generated in %s s %s - %s sql - %s URLs listed -->',
  88. 'stats_start' => "\n" . '<!-- Output started from cache after %s s - %s sql -->',
  89. 'stats_nocache' => "\n" . '<!-- Output ended after %s s %s -->',
  90. 'stats_end' => "\n" . '<!-- Output from cache ended up after %s s - %s sql -->',
  91. );
  92. $rss_limit_time = (int) $this->set_module_option('limit_time', $this->override['limit']);
  93. $rss_lang = trim($this->set_module_option('lang', $this->gym_config['rss_override']));
  94. $this->rss_config = array( 'rss_c_info' => ( !empty($this->gym_config['rss_c_info'])) ? "\n\t\t" . '<copyright>' . $this->xml_encode($this->gym_config['rss_c_info']) . '</copyright>' : '',
  95. 'rss_xslt' => ( $this->gym_config['rss_xslt'] ) ? true : false,
  96. 'rss_force_xslt' => ( $this->gym_config['rss_xslt'] && $this->gym_config['rss_force_xslt'] ) ? true : false,
  97. 'rss_lang' => ( !empty($rss_lang) ) ? "\n\t\t" . '<language>' . $this->xml_encode($rss_lang) . '</language>' : '',
  98. 'rss_url' => $phpbb_seo->sslify($this->gym_config['rss_url'], $phpbb_seo->ssl['use'], false),
  99. 'rss_yahoo_appid' => ( !empty($this->gym_config['rss_yahoo_appid']) ) ? trim($this->gym_config['rss_yahoo_appid']) : '',
  100. // module specific settings we should often need in module
  101. // Some are used here to filter the allowed actions, will go to main default if unset in the module
  102. 'rss_url_limit' => (int) $this->set_module_option('url_limit', $this->override['limit']),
  103. 'rss_sql_limit' => (int) $this->set_module_option('sql_limit', $this->override['limit']),
  104. 'rss_limit_time' => ( $rss_limit_time >= 0 ) ? $rss_limit_time*3600*24 : 0,
  105. 'rss_modrewrite' => (int) $this->set_module_option('modrewrite', $this->override['modrewrite']),
  106. 'rss_modrtype' => (int) $this->set_module_option('modrtype', $this->override['modrewrite']),
  107. 'rss_sitename' => $this->set_module_option('sitename'),
  108. 'rss_site_desc' => $this->set_module_option('site_desc'),
  109. 'rss_logo_url' => $this->path_config['gym_img_url'] . trim($this->set_module_option('logo_url'), '/'),
  110. 'rss_image_url' => $this->path_config['gym_img_url'] . trim($this->set_module_option('image_url'), '/'),
  111. 'rss_sort' => $this->set_module_option('sort', $this->override['sort']),
  112. 'rss_allow_auth' => (boolean) $this->set_module_option('allow_auth', $this->gym_config['rss_override']),
  113. 'rss_cache_auth' => (boolean) $this->set_module_option('cache_auth', $this->gym_config['rss_override']),
  114. 'rss_allow_content' => (boolean) $this->set_module_option('allow_content', $this->gym_config['rss_override']),
  115. 'rss_allow_news' => (boolean) $this->set_module_option('allow_news', $this->gym_config['rss_override']),
  116. 'rss_news_update' => round($this->set_module_option('news_update', $this->gym_config['rss_override']), 2) * 3600,
  117. 'rss_allow_profile' => (boolean) $this->set_module_option('allow_profile', $this->gym_config['rss_override']),
  118. 'rss_allow_profile_links' => (boolean) $this->set_module_option('allow_profile_links', $this->gym_config['rss_override']),
  119. 'rss_sumarize' => (int) $this->set_module_option('sumarize', $this->gym_config['rss_override']),
  120. 'rss_sumarize_method' => trim($this->set_module_option('sumarize_method', $this->gym_config['rss_override'])),
  121. 'rss_allow_short' => (boolean) $this->set_module_option('allow_short', $this->gym_config['rss_override']),
  122. 'rss_allow_long' => (boolean) $this->set_module_option('allow_long', $this->gym_config['rss_override']),
  123. 'rss_allow_bbcode' => (boolean) $this->set_module_option('allow_bbcode', $this->gym_config['rss_override']),
  124. 'rss_strip_bbcode' => trim($this->set_module_option('strip_bbcode', $this->gym_config['rss_override'])),
  125. 'rss_allow_links' => (boolean) $this->set_module_option('allow_links', $this->gym_config['rss_override']),
  126. 'rss_allow_emails' => (boolean) $this->set_module_option('allow_emails', $this->gym_config['rss_override']),
  127. 'rss_allow_smilies' => (boolean) $this->set_module_option('allow_smilies', $this->gym_config['rss_override']),
  128. 'rss_yahoo_notify' => (boolean) $this->set_module_option('yahoo_notify', $this->gym_config['rss_override']),
  129. 'rss_nohtml' => (boolean) $this->set_module_option('nohtml', $this->gym_config['rss_override']),
  130. //@TODO add acp option for this ?
  131. 'rss_display_author' => /*(boolean) $this->set_module_option('display_author', $this->gym_config['rss_override'])*/ true,
  132. 'rss_yahoo_notify_url' => '',
  133. 'rss_msg_filters' => array(),
  134. 'rss_auth_msg' => '',
  135. 'rss_do_explain' => false,
  136. );
  137. $this->rss_config['rss_auth_guest'] = ($this->rss_config['rss_allow_auth'] && $user->data['is_registered']) ? false : true;
  138. $this->cache_config['do_cache'] = $this->rss_config['rss_auth_guest'] ? true : $this->rss_config['rss_cache_auth'];
  139. // remind for later
  140. $this->rss_config['rss_profile_mode'] = $this->rss_config['rss_allow_profile_links'] ? 'full' : 'no_profile';
  141. // Check the rss specific vars and do basic set_up for msg output
  142. $this->init_rss_vars();
  143. if (!$this->rss_config['rss_auth_guest']) {
  144. $this->rss_config['rss_auth_msg'] = "\n" . ( ($this->actions['rss_channel_list'] || empty($this->actions['module_sub']) || $this->actions['module_sub'] == 'channels') ? sprintf($user->lang['RSS_AUTH_SOME_USER'], $user->data['username'] ) : sprintf($user->lang['RSS_AUTH_THIS_USER'], $user->data['username'] ) ) . "\n";
  145. }
  146. // Are we going to explain ?
  147. if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report')) {
  148. $this->rss_config['rss_do_explain'] = true;
  149. $this->cache_config['do_cache'] = false;
  150. }
  151. $this->rss_output();
  152. if ($this->rss_config['rss_do_explain']) {
  153. $db->sql_report('display');
  154. } else {
  155. $this->gym_output->do_output();
  156. }
  157. return;
  158. }
  159. /**
  160. * init_rss_vars()
  161. * Set up the specific rss modules GET vars.
  162. * @access private
  163. */
  164. function init_rss_vars() {
  165. global $user, $phpEx, $phpbb_seo;
  166. // Let's now check out if it's a GYM 1.x URL
  167. if ($this->gym_config['rss_1xredir'] && !empty($_GET['gym1x'])) {
  168. $this->actions['gym1x_newurl'] = '/' . (isset($_GET['m']) ? 'digest/' : '' ) . (isset($_GET['l']) ? 'long/' : (isset($_GET['s']) ? 'short/' : '' ) );
  169. $this->actions['gym1x_newurl'] = empty($this->actions['module_main']) ? 'rss' . $this->actions['gym1x_newurl'] . 'rss.xml' : (empty($_GET['gymtitle']) ? 'rss' . $this->actions['gym1x_newurl'] . (!empty($this->actions['module_sub']) ? $this->actions['module_sub'] . '/' : '' ) . $this->actions['module_main'] . '.xml' : $phpbb_seo->set_url($_GET['gymtitle'], (int) $this->actions['module_sub'], 'forum') . $this->actions['gym1x_newurl'] . $this->actions['module_main'] . '.xml');
  170. // nothing else needed for this
  171. return;
  172. }
  173. $this->actions['rss_content'] = $this->actions['rss_short_list'] = $this->actions['rss_long_list'] = $this->actions['rss_channel_list'] = $this->actions['rss_news_list'] = false;
  174. $this->rss_config['extra_title'] = $this->url_config['extra_params_full'] = $this->url_config['extra_params'] = '';
  175. $this->url_config['rss_announces_path'] = $phpbb_seo->seo_static['global_announce'] . '/';
  176. // Channel list
  177. if ( ( $module_sub_chan = ($this->actions['module_sub'] === 'channels' ? true : false) ) || (isset($_GET['channels']) && empty($this->actions['module_main']) ) ) {
  178. $this->actions['rss_channel_list'] = true;
  179. $this->rss_config['extra_title'] = ' - ' . $user->lang['RSS_CHAN_LIST_TITLE'];
  180. if ($this->rss_config['rss_modrewrite'] || !$module_sub_chan) {
  181. $this->url_config['extra_params_full'] .= 'channels/';
  182. }
  183. }
  184. // News = first message only
  185. if ( isset($_GET['news']) && $this->rss_config['rss_allow_news']) {
  186. $this->actions['rss_news_list'] = true;
  187. $this->rss_config['extra_title'] .= ' - ' . $user->lang['RSS_NEWS'];
  188. $this->url_config['extra_params_full'] .= 'news/';
  189. $this->url_config['extra_params'] .= 'news/';
  190. if (!empty($this->rss_config['rss_news_update'])) {
  191. $this->cache_config['cache_max_age'] = $this->rss_config['rss_news_update'];
  192. }
  193. unset($_GET['channels']); // no channel listing
  194. }
  195. // Do we output text ?
  196. if ( isset($_GET['digest']) && $this->rss_config['rss_allow_content'] ) {
  197. $this->actions['rss_content'] = true;
  198. $this->rss_config['extra_title'] .= ' - ' . $user->lang['RSS_CONTENT'];
  199. $this->url_config['extra_params_full'] .= 'digest/';
  200. $this->url_config['extra_params'] .= 'digest/';
  201. $this->rss_config['rss_url_limit'] = intval($this->set_module_option('url_limit_msg', $this->gym_config['rss_override']));
  202. $this->rss_config['rss_sql_limit'] = intval($this->set_module_option('sql_limit_msg', $this->gym_config['rss_override']));
  203. }
  204. // Custom limits short
  205. if ( isset($_GET['short']) && $this->rss_config['rss_allow_short'] ) {
  206. $this->actions['rss_short_list'] = true;
  207. $this->rss_config['extra_title'] .= ' - ' . $user->lang['RSS_SHORT'];
  208. $this->url_config['extra_params_full'] .= 'short/';
  209. $this->url_config['extra_params'] .= 'short/';
  210. $this->rss_config['rss_url_limit'] = $this->actions['rss_content'] ? intval($this->rss_config['rss_url_limit']/3) : intval($this->set_module_option('url_limit_short', $this->gym_config['rss_override']));
  211. $this->rss_config['rss_sql_limit'] = $this->actions['rss_content'] ? intval($this->rss_config['rss_url_limit']/2) : intval($this->set_module_option('sql_limit_short', $this->gym_config['rss_override']));
  212. }
  213. // Custom limits long
  214. if ( isset($_GET['long']) && !$this->actions['rss_short_list'] && $this->rss_config['rss_allow_long'] ) {
  215. $this->actions['rss_long_list'] = true;
  216. $this->rss_config['extra_title'] .= ' - ' . $user->lang['RSS_LONG'];
  217. $this->url_config['extra_params_full'] .= 'long/';
  218. $this->url_config['extra_params'] .= 'long/';
  219. $this->rss_config['rss_url_limit'] = $this->actions['rss_content'] ? intval($this->rss_config['rss_url_limit']*3) : intval($this->set_module_option('url_limit_long', $this->gym_config['rss_override']));
  220. $this->rss_config['rss_sql_limit'] = $this->actions['rss_content'] ? intval($this->rss_config['rss_url_limit']*2) : intval($this->set_module_option('sql_limit_long', $this->gym_config['rss_override']));
  221. }
  222. // Adjust variable a bit
  223. if ($this->actions['rss_content'] ) { // requested and auth
  224. $this->rss_config['rss_msg_filters'] = $this->set_msg_strip($this->rss_config['rss_strip_bbcode']);
  225. }
  226. $this->url_config['extra_params_delimE'] = $this->url_config['extra_paramsE'] = '';
  227. $this->url_config['extra_params_delimQ'] = $this->url_config['extra_paramsQ'] = '';
  228. $this->url_config['rss_vpath'] = '';
  229. if ($this->rss_config['rss_modrewrite']) {
  230. $this->actions['extra_params'] = $this->url_config['extra_params'];
  231. $this->actions['extra_params_full'] = $this->url_config['extra_params_full'];
  232. $this->url_config['extra_params_delimE'] = '/';
  233. $this->url_config['extra_params_delimQ'] = '?';
  234. $this->url_config['rss_vpath'] = 'rss/'; // virtual rss path for forum RSS feed URLs etc ...
  235. $this->url_config['rss_default'] = 'rss.xml' . $this->url_config['gzip_ext_out'] ;
  236. if (!empty($this->url_config['extra_params'])) {
  237. $this->url_config['extra_paramsE'] = $this->url_config['extra_params'];
  238. $this->url_config['extra_paramsQ'] = $this->url_config['extra_params_delimQ'] . $this->url_config['extra_params'];
  239. }
  240. } else {
  241. $this->url_config['extra_params'] = str_replace('/', '&amp;', trim($this->url_config['extra_params'], '/'));
  242. $this->actions['extra_params_full'] = str_replace('/', '&amp;', trim($this->url_config['extra_params_full'], '/'));
  243. $this->url_config['extra_params_delimE'] = '&amp;';
  244. $this->url_config['extra_params_delimQ'] = '?';
  245. if (!empty($this->url_config['extra_params'])) {
  246. $this->url_config['extra_paramsE'] = $this->url_config['extra_params_delimE'] . $this->url_config['extra_params'];
  247. $this->url_config['extra_paramsQ'] = $this->url_config['extra_params_delimQ'] . $this->url_config['extra_params'];
  248. }
  249. }
  250. }
  251. /**
  252. * forum_rss_url() builds rss forum url with proper options
  253. * Suffixe is not added here, to properly deal with pagination
  254. */
  255. function forum_rss_url($forum_name, $forum_id) {
  256. global $phpbb_seo;
  257. return !empty($phpbb_seo->cache_config['forum'][$forum_id]) ? $phpbb_seo->cache_config['forum'][$forum_id] : $phpbb_seo->format_url( $forum_name, 'forum' ) . $this->url_config['rss_forum_delim'] . $forum_id;
  258. }
  259. /**
  260. * rss_output() will build all rss output
  261. * @access private
  262. */
  263. function rss_output() {
  264. global $phpEx, $db, $config, $phpbb_root_path, $user, $phpbb_seo;
  265. // Initialize SQL cycling : do not query for more than required
  266. $this->rss_config['rss_sql_limit'] = ($this->rss_config['rss_sql_limit'] > $this->rss_config['rss_url_limit']) ? $this->rss_config['rss_url_limit'] : $this->rss_config['rss_sql_limit'];
  267. // XSLT styling
  268. if ($this->rss_config['rss_xslt']) {
  269. // here we could go further and allow user style to be used, would need to parse the cache a bit,
  270. // but, unlike Google sitemaps, RSS feeds are decently small for that.
  271. $this->style_config['xslt_style'] = "\n" . '<'.'?xml-stylesheet type="text/xsl" href="' . $phpbb_seo->seo_path['phpbb_url'] . 'gym_sitemaps/gym_style.' . $phpEx . '?action-rss,type-xsl,lang-' . $config['default_lang'] . ',theme_id-' . $config['default_style'] . '" media="screen, projection" ?'.'>';
  272. $blanc_fix = '';
  273. if ($this->rss_config['rss_force_xslt']) {
  274. // FF 2 and IE7 only look for the first 500 chars to decide if it's rss or not
  275. // and impose their private styling
  276. for ($i=0; $i<550; $i++) {
  277. $blanc_fix .= ' ';
  278. }
  279. $blanc_fix = "\n" . '<!-- Some spaces ' . $blanc_fix . ' to force xlst -->';
  280. }
  281. $this->style_config['xslt_style'] .= $blanc_fix;
  282. }
  283. // Remove guid for channels
  284. if ($this->actions['rss_channel_list']) {
  285. $this->style_config['rss_item_tpl'] = str_replace("\n\t\t\t" . '<guid isPermaLink="true">%s</guid>', '', $this->style_config['rss_item_tpl']);
  286. }
  287. // custom url transition message
  288. if (!empty($this->actions['gym1x_newurl'])) {
  289. $chan_title = $user->lang['RSS_1XREDIR'] . ' - ' . $this->gym_config['rss_sitename'];
  290. $chan_desc = $user->lang['RSS_1XREDIR_MSG'] . ' : ' . $this->parse_link($this->actions['gym1x_newurl']) . "\n" . $this->gym_config['rss_site_desc'];
  291. $rss_new_url = $this->rss_config['rss_url'] . $this->actions['gym1x_newurl'];
  292. $this->output_data['data'] = sprintf($this->style_config['rss_header'], $this->style_config['xslt_style'], $this->gym_config['gym_version'] );
  293. $this->parse_channel($chan_title, $chan_desc, $rss_new_url, $this->output_data['last_mod_time'], $this->rss_config['rss_image_url'], $rss_new_url);
  294. $this->parse_item($chan_title, $chan_desc, $rss_new_url, $rss_new_url, '', $this->output_data['last_mod_time']);
  295. $this->output_data['data'] .= $this->style_config['rss_footer'];
  296. return;
  297. }
  298. // module action
  299. if (in_array($this->actions['module_main'], $this->actions['action_modules'])) { // List item from the module
  300. $module_class = $this->actions['action_type'] . '_' . $this->actions['module_main'];
  301. $this->load_module($module_class, 'rss_module');
  302. if ( empty($this->output_data['url_sofar']) ) {
  303. $this->gym_error(404, 'GYM_TOO_FEW_ITEMS', __FILE__, __LINE__);
  304. }
  305. $this->output_data['data'] = sprintf($this->style_config['rss_header'], $this->style_config['xslt_style'], $this->gym_config['gym_version'] ) . $this->output_data['data'] . $this->style_config['rss_footer'];
  306. } else { // Add items from installed modules
  307. $site_title = $this->gym_config['rss_sitename'];
  308. $site_desc = $this->gym_config['rss_site_desc'] . "\n";
  309. if ($this->actions['rss_channel_list']) {
  310. $chan_source = $this->rss_config['rss_url'] . $this->url_config['rss_vpath'] . (($this->rss_config['rss_modrewrite']) ? (!empty($this->url_config['extra_params']) ? $this->url_config['extra_params'] : '') : $this->url_config['rss_default'] . $this->url_config['extra_params_delimQ'] . $this->actions['extra_params_full']);
  311. $site_title_full = $site_title . $this->rss_config['extra_title'];
  312. $site_desc .= $user->lang['RSS_CHAN_LIST_DESC'] . "\n";
  313. } else {
  314. $chan_source = $this->rss_config['rss_url'] . $this->url_config['rss_vpath'] . (($this->rss_config['rss_modrewrite']) ? (!empty($this->url_config['extra_params']) ? $this->url_config['extra_params'] : '') . $this->url_config['rss_default'] : $this->url_config['rss_default'] . $this->url_config['extra_paramsQ']);
  315. $site_title_full = $site_title . $this->rss_config['extra_title'];
  316. }
  317. $this->seo_kill_dupes($chan_source);
  318. $this->parse_channel($site_title_full, $site_desc, $this->rss_config['rss_url'], $this->output_data['last_mod_time'], $this->rss_config['rss_image_url'], $chan_source);
  319. // Since we are going to cycle through modules, we need to ajust URL limit and counting a bit
  320. // URL limit, we take the last xx items from each feed
  321. // where xx is the URL limit divided by the number of feeds
  322. $this->rss_config['rss_url_limit'] = !empty($this->actions['action_modules']) ? intval($this->rss_config['rss_url_limit'] / count($this->actions['action_modules'])) : 0;
  323. if ( empty($this->rss_config['rss_url_limit']) ) {
  324. $this->gym_error(404, 'GYM_TOO_FEW_ITEMS', __FILE__, __LINE__);
  325. }
  326. // start the modules
  327. // We are working on all available modules
  328. $this->load_modules('rss_main');
  329. $this->output_data['url_sofar'] = $this->output_data['url_sofar_total'];
  330. if ( empty($this->output_data['url_sofar']) ) {
  331. $this->gym_error(404, 'GYM_TOO_FEW_ITEMS', __FILE__, __LINE__);
  332. }
  333. $this->output_data['data'] = sprintf($this->style_config['rss_header'], $this->style_config['xslt_style'], $this->gym_config['gym_version'] ) . $this->output_data['data'] . $this->style_config['rss_footer'];
  334. }
  335. if ( $this->rss_config['rss_yahoo_notify'] && ($this->output_data['time'] >= ($this->cache_config['cache_born'] + $this->cache_config['cache_max_age'])) ) {
  336. $this->rss_yahoo_notify();
  337. }
  338. return;
  339. }
  340. /**
  341. * parse_channel() adds the channel info to the output
  342. */
  343. function parse_channel($chan_title, $chan_desc, $chan_link, $lastBuildDate = 0, $chan_image = '', $chan_source = '') {
  344. global $config, $user;
  345. // Misc SQL Explain
  346. global $auth;
  347. if ( !empty($chan_source) && $auth->acl_get('a_') && defined('DEBUG_EXTRA')) {
  348. if (!empty($_REQUEST['explain'])) {
  349. return;
  350. }
  351. if (empty($user->lang['GYM_SQLEXPLAIN_MSG'])) {
  352. $user->add_lang('gym_sitemaps/gym_common');
  353. }
  354. $report_url = $chan_source . (strpos($chan_source, '?') !== false ? '&amp;' : '?') . 'explain=1';
  355. $this->actions['sql_report_msg'] = "\n<i style=\"color:#CC0000\">" . sprintf($user->lang['GYM_SQLEXPLAIN_MSG'], $this->parse_link($report_url , $user->lang['GYM_SQLEXPLAIN'])) . '</i>';
  356. }
  357. $lastBuildDate = intval($lastBuildDate);
  358. if ( $lastBuildDate > $config['board_startdate']) {
  359. $this->output_data['last_mod_time'] = $lastBuildDate;
  360. if (( $this->cache_config['cache_max_age'] + $lastBuildDate) <= $this->output_data['time']) {
  361. $ttl_time = (int) ($this->cache_config['cache_max_age'] / 60);
  362. } else {
  363. $ttl_time = ( $this->cache_config['cache_max_age'] + $lastBuildDate) - $this->output_data['time'];
  364. }
  365. $ttl = sprintf($this->style_config['chan_ttl_tpl'], intval( ( $ttl_time / 60)) );
  366. $lastBuildDate = sprintf($this->style_config['chan_lastbuildate_tpl'], gmdate('D, d M Y H:i:s \G\M\T', intval($lastBuildDate)));
  367. } else {
  368. $lastBuildDate = '';
  369. $ttl = '';
  370. }
  371. $chan_image = !empty($chan_image) ? sprintf($this->style_config['rsschan_img_tpl'], $this->xml_encode($chan_title), $chan_image, $chan_link) : '';
  372. $input = !empty($chan_source) ? sprintf($this->style_config['rsschan_input_tpl'], $this->xml_encode($user->lang['RSS_2_LINK'] . ' : ' . $chan_title), $this->xml_encode($chan_desc . $user->lang['RSS_2_LINK']), $chan_source, 'gym_sitemaps') : '';
  373. $this->output_data['data'] .= sprintf($this->style_config['rsschan_tpl'], $this->xml_encode($chan_title), $chan_link, $this->xml_encode($chan_desc . $this->rss_config['rss_auth_msg'] . $this->actions['sql_report_msg']), $lastBuildDate, $chan_image, $ttl, $chan_source, $input);
  374. }
  375. /**
  376. * parse_item() adds the item info to the output
  377. */
  378. function parse_item($item_title, $item_desc, $item_link, $item_source, $item_source_title = '', $pubDate = 0, $author = false) {
  379. global $config;
  380. $pubDate = $pubDate > $config['board_startdate'] ? sprintf($this->style_config['item_pubdate_tpl'], gmdate('D, d M Y H:i:s \G\M\T', intval($pubDate))) : '';
  381. $item_desc = $this->rss_config['rss_nohtml'] ? strip_tags($item_desc) : $item_desc;
  382. $item_source_title = !empty($item_source_title) ? $item_source_title : $item_title;
  383. $author = $author ? sprintf($this->style_config['item_creator_tpl'], $this->xml_encode($author)) : '';
  384. $this->output_data['data'] .= sprintf($this->style_config['rss_item_tpl'], $this->xml_encode($item_title), $item_link, $pubDate, $this->xml_encode($item_desc . $this->rss_config['rss_auth_msg']), $item_source, $this->xml_encode($item_source_title), $item_link, $author);
  385. $this->output_data['url_sofar']++;
  386. }
  387. /**
  388. * prepare_for_output($topic, $key = '')
  389. * will put together BBcodes and smilies before the output
  390. * @param array $topic
  391. * @access private
  392. */
  393. function prepare_for_output($topic, $key = '') {
  394. global $config, $user, $phpbb_seo;
  395. static $bbcode;
  396. static $patterns;
  397. static $replaces;
  398. $bbcode_uid = $topic['bbcode_uid' . $key];
  399. $bitfield = $topic['bbcode_bitfield' . $key];
  400. $message_title = !empty($topic['post_subject' . $key]) ? $topic['post_subject' . $key] : $topic['topic_title'];
  401. $message_title = censor_text($message_title);
  402. $message = '<b>' . $message_title . '</b>' . "\n\n" . $topic['post_text' . $key];
  403. if (!isset($patterns)) {
  404. if ( !empty($this->rss_config['rss_msg_filters']['pattern']) ) {
  405. $patterns = $this->rss_config['rss_msg_filters']['pattern'];
  406. $replaces = $this->rss_config['rss_msg_filters']['replace'];
  407. } else {
  408. $patterns = $replaces = array();
  409. }
  410. }
  411. if (!empty($patterns)) {
  412. $message = preg_replace($patterns, $replaces, $message);
  413. }
  414. if ($this->rss_config['rss_sumarize'] > 0 ) {
  415. $message = $this->summarize( $message, $this->rss_config['rss_sumarize'], $this->rss_config['rss_sumarize_method'] );
  416. // Clean broken tag at the end of the message
  417. $message = preg_replace('`\<[^\<\>]*$`i', ' ...', $message);
  418. // Close broken bbcode tags requiring it
  419. $this->close_bbcode_tags($message, $bbcode_uid);
  420. }
  421. $message = censor_text($message);
  422. if (!$this->rss_config['rss_nohtml']) {
  423. if ($bitfield && $this->rss_config['rss_allow_bbcode']) {
  424. if (!class_exists('bbcode')) {
  425. global $phpbb_root_path, $phpEx;
  426. include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
  427. }
  428. if (empty($bbcode)) {
  429. $bbcode = new bbcode($bitfield);
  430. } else {
  431. $bbcode->bbcode($bitfield);
  432. }
  433. if ( !$this->rss_config['rss_allow_links'] ) {
  434. $message = preg_replace("`\[/?url(=.*)?\]`i", "", $message);
  435. }
  436. $bbcode->bbcode_second_pass($message, $bbcode_uid);
  437. }
  438. // Parse smilies
  439. $message = $this->smiley_text($message, !($this->rss_config['rss_allow_smilies'] && $topic['enable_smilies' . $key]));
  440. if ($this->rss_config['rss_sumarize'] > 0 ) {
  441. // last clean up
  442. static $_find = array('`\<\!--[^\<\>]+--\>`Ui', '`\[\/?[^\]\[]*\]`Ui');
  443. $message = preg_replace($_find, '', $message);
  444. $message .= "\n\n" . '<a href="' . $topic['topic_url' . $key] . '"><b>' . $user->lang['RSS_MORE'] . ' ...</b></a>'. "\n\n";
  445. }
  446. } else {
  447. $message = strip_tags(preg_replace('`\[\/?[^\]\[]*\]`Ui', '', $message));
  448. }
  449. return "\n" . $message;
  450. }
  451. /**
  452. * close_bbcode_tags(&$message, $uid, $bbcodelist)
  453. * will tend to do it nicely ;-)
  454. * Will close the bbcode tags requiring it in the list (quote|b|u|i|color|*|list)
  455. * Beware, bo not reduce $bbcodelist without knowing what you are doing
  456. */
  457. function close_bbcode_tags(&$message, $uid, $bbcodelist = 'quote|b|u|i|color|*|list') {
  458. $open_lists = $close_lists = array();
  459. $bbcodelist = str_replace('|*', '|\*', $bbcodelist);
  460. $open_count = preg_match_all('`\[(' . $bbcodelist . ')(\=([a-z0-9]{1}))?[^\]\[]*\:' . $uid . '\]`i', $message, $open_matches);
  461. $close_count = preg_match_all('`\[/(' . $bbcodelist . ')(\:([a-z]{1}))?[^\]\[]*\:' . $uid . '\]`i', $message, $close_matches);
  462. if ($open_count == $close_count) { // No need to go further
  463. return;
  464. }
  465. if (!empty($open_matches[1])) {
  466. $open_list = array_count_values($open_matches[1]);
  467. $close_list = !empty($close_matches[1]) ? array_count_values($close_matches[1]) : array();
  468. $list_to_close = array();
  469. if (isset($open_list['list'])) {
  470. foreach ($open_matches[1] as $k => $v) {
  471. if ($v == 'list') {
  472. $open_lists[] = !empty($open_matches[3][$k]) ? 'o' : 'u';
  473. }
  474. }
  475. if (!empty($close_matches[1])) {
  476. foreach ($close_matches[1] as $k => $v) {
  477. if ($v == 'list') {
  478. $close_lists[] = !empty($close_matches[3][$k]) ? 'o' : 'u';
  479. }
  480. }
  481. }
  482. $list_to_close = array_reverse(array_diff_assoc($open_lists, $close_lists));
  483. }
  484. unset($open_list['*'], $open_list['list']);
  485. foreach ($open_list as $bbcode => $total) {
  486. if (empty($close_list[$bbcode]) || $close_list[$bbcode] < $total) {
  487. // close the tags
  488. $diff = empty($close_list[$bbcode]) ? $total : $total - $close_list[$bbcode];
  489. $message .= str_repeat("[/$bbcode:$uid]", $diff);
  490. }
  491. }
  492. // Close the lists if required
  493. foreach ($list_to_close as $ltype) {
  494. $message .= "[/*:m:$uid][/list:$ltype:$uid]";
  495. }
  496. }
  497. return;
  498. }
  499. /**
  500. * set_msg_strip($bbcode_list) will build up the unauthed bbcode list
  501. * $bbcode_list = 'code:0,img:1,quote';
  502. * $bbcode_list = 'all';
  503. * 1 means the bbcode and it's content will be striped.
  504. * all means all bbcodes.
  505. * $returned_list = array('patern' => $matching_patterns, 'replace' => $replace_patterns);
  506. * @access private
  507. */
  508. function set_msg_strip($bbcode_list) {
  509. $patterns = $replaces = array();
  510. // Now the bbcodes
  511. if (!$this->rss_config['rss_allow_bbcode'] || preg_match('`all\:?([0-1]*)`i', $bbcode_list, $matches)) {
  512. if ( (@$matches[1] != 1 ) ) {
  513. $patterns[] = '`\[\/?[a-z0-9\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:[0-9a-z]{5,})\]`i';
  514. $replaces[] = '';
  515. } else {
  516. $patterns[] = '`\[([a-z0-9\*\+\-]+)((=|:)[^\:\]]*)?\:[0-9a-z]{5,}\].*\[/(?1)(:?[^\:\]]*)?\:[0-9a-z]{5,}\]`Usi';
  517. $replaces[] = "{ \\1 }";
  518. }
  519. $patterns[] = '`<[^>]*>(.*<[^>]*>)?`Usi'; // All html
  520. $replaces[] = '';
  521. } else {
  522. // Take care about links & emails
  523. if ( !$this->rss_config['rss_allow_links'] ) {
  524. if ( !$this->rss_config['rss_allow_emails'] ) { // Saves couple RegEx
  525. $email_find = '[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*[a-z]+';
  526. $email_replace = 'str_replace(array("@", "."), array(" AT ", " DOT "),"\\1")';
  527. $email_option = 'e';
  528. } else {
  529. $email_find = '.*?';
  530. $email_replace = "\\1";
  531. $email_option = '';
  532. }
  533. $patterns[] = '`<!\-\- ([lmw]+) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->`i';
  534. $replaces[] = "\\2";
  535. $patterns[] = '`\[/?url[^\]\[]*\]`i';
  536. $replaces[] = '';
  537. $patterns[] = '`<!\-\- e \-\-><a href="mailto:(' . $email_find . ')">.*?</a><!\-\- e \-\->`i' . $email_option;
  538. $replaces[] = $email_replace;
  539. }
  540. if ( !$this->rss_config['rss_allow_emails'] && $this->rss_config['rss_allow_links'] ) {
  541. $patterns[] = '`<!\-\- e \-\-><a href="mailto:([a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*[a-z]+)">.*?</a><!\-\- e \-\->`ei';
  542. $replaces[] = 'str_replace(array("@", "."), array(" AT ", " DOT "),"\\1")';
  543. }
  544. $exclude_list = ( empty($bbcode_list) ? array() : explode(',', $bbcode_list) );
  545. $RegEx_unset = $RegEx_remove = '';
  546. foreach ($exclude_list as $key => $value ) { // Group the RegEx
  547. $value = trim($value);
  548. if (preg_match("`[a-z0-9]+(\:([0-1]*))?`i", $value, $matches) ) {
  549. $values = (strpos($value, ':') !== false) ? explode(':', $value) : array($value);
  550. if ( (@$matches[2] != 1 ) ) {
  551. $RegEx_unset .= (!empty($RegEx_unset) ? '|' : '' ) . $values[0];
  552. } else {
  553. $RegEx_remove .= (!empty($RegEx_remove) ? '|' : '' ) . $values[0];
  554. }
  555. }
  556. }
  557. if (!empty($RegEx_remove) ) {
  558. $patterns[] = '`\[(' . $RegEx_remove . ')((=|:)[^\:\]]*)?\:[0-9a-z]{5,}\].*\[/(?1)(:?[^\:\]]*)?\:[0-9a-z]{5,}\]`Usi';
  559. $replaces[] = "{ \\1 }";
  560. }
  561. if (!empty($RegEx_unset) ) {
  562. $patterns[] = '`\[/?(' . $RegEx_unset . ')(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:[0-9a-z]{5,})\]`i';
  563. $replaces[] = '';
  564. }
  565. }
  566. return array('pattern' => $patterns, 'replace' => $replaces);
  567. }
  568. /**
  569. * Some text formating functions for text output
  570. * un_htmlspecialchars()
  571. * @access private
  572. */
  573. function un_htmlspecialchars($text) {
  574. return preg_replace(array('#&gt;#', '#&lt;#', '#&quot;#', '#&amp;#'), array('>', '<', '"', '&'), $text);
  575. }
  576. /**
  577. * Summarize method selector
  578. * @access private
  579. */
  580. function summarize($string, $limit, $method = 'lines') {
  581. switch ($method) {
  582. case 'words':
  583. return $this->word_limit($string, $limit);
  584. break;
  585. case 'chars':
  586. return $this->char_limit($string, $limit);
  587. break;
  588. case 'lines':
  589. default:
  590. return $this->line_limit($string, $limit);
  591. break;
  592. }
  593. }
  594. /**
  595. * Cut the text by lines
  596. * @access private
  597. */
  598. function line_limit($string, $limit = 10, $ellipsis = ' ...') {
  599. return count($lines = preg_split("`[\n\r]+`", ltrim($string), $limit + 1)) > $limit ? rtrim(utf8_substr($string, 0, utf8_strlen($string) - utf8_strlen(end($lines)))) . $ellipsis : $string;
  600. }
  601. /**
  602. * Cut the text according to the number of words.
  603. * Borrowed from www.php.net http://www.php.net/preg_replace
  604. * @access private
  605. */
  606. function word_limit($string, $limit = 50, $ellipsis = ' ...') {
  607. return count($words = preg_split('`\s+`', ltrim($string), $limit + 1)) > $limit ? rtrim(utf8_substr($string, 0, utf8_strlen($string) - utf8_strlen(end($words)))) . $ellipsis : $string;
  608. }
  609. /**
  610. * Cut the text according to the number of characters.
  611. * Borrowed from www.php.net http://www.php.net/preg_replace
  612. * @access private
  613. */
  614. function char_limit($string, $limit = 100, $ellipsis = ' ...') {
  615. return utf8_strlen($fragment = utf8_substr($string, 0, $limit + 1 - utf8_strlen($ellipsis))) < utf8_strlen($string) + 1 ? preg_replace('`\s*\S*$`', '', $fragment) . $ellipsis : $string;
  616. }
  617. // --> Yahoo! Notification functions <--
  618. /**
  619. * rss_yahoo_notify($url) will handle yahoo notification of new content
  620. * @access private
  621. */
  622. function rss_yahoo_notify($url = '') {
  623. global $user, $config, $phpbb_seo;
  624. $url = !empty($url) ? str_replace('&amp;', '&', $url) : (!empty($this->url_config['rss_yahoo_notify_url']) ? $this->url_config['rss_yahoo_notify_url'] : '');
  625. $url = trim($url);
  626. if (empty($url) || !$this->rss_config['rss_yahoo_notify'] || empty($this->rss_config['yahoo_appid'])) {
  627. return;
  628. }
  629. // No more than 200 pings a day!
  630. if (@$config['gym_pinged_today'] > 200) {
  631. // @TODO add logs about this ?
  632. return;
  633. }
  634. $skip = array('://localhost', '://127.0.0.1', '://192.168.', '://169.254.');
  635. foreach ($skip as $_skip) {
  636. if (utf8_strpos($url, $_skip) !== false) {
  637. // @TODO add logs about this ?
  638. return;
  639. }
  640. }
  641. // If ssl is not forced, always ping with http urls
  642. $url = $phpbb_seo->sslify($url, $phpbb_seo->ssl['forced']);
  643. $not_curl= true;
  644. $timout = 3;
  645. // The Yahoo! Web Services request
  646. // Based on the Yahoo! developper hints : http://developer.yahoo.com/php/
  647. $request = "http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=" . urlencode($this->rss_config['yahoo_appid']) . '&url=' . urlencode($url);
  648. if (function_exists('curl_exec')) {
  649. $not_curl= false;
  650. // Initialize the session
  651. $session = curl_init($request);
  652. // Set curl options
  653. curl_setopt($session, CURLOPT_HEADER, false);
  654. curl_setopt($session, CURLOPT_USERAGENT, 'GYM Sitemaps &amp; RSS / www.phpBB-SEO.com');
  655. curl_setopt($session, CURLOPT_TIMEOUT, $timout);
  656. curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
  657. // Make the request
  658. $response = curl_exec($session);
  659. // Close the curl session
  660. curl_close($session);
  661. // Get HTTP Status code from the response
  662. $status_codes = array();
  663. preg_match('/\d\d\d/', $response, $status_code);
  664. $status_code = $status_codes[0];
  665. // Get the XML from the response, bypassing the header
  666. if (!($xml = strstr($response, '<?xml'))) {
  667. $xml = null;
  668. $not_curl= true;
  669. }
  670. } else if ( $not_curl && function_exists('file_get_contents') ) {
  671. ini_set('user_agent','GYM Sitemaps &amp; RSS / www.phpBB-SEO.com');
  672. ini_set('default_socket_timeout', $timout);
  673. // Make the request
  674. if ($xml = file_get_contents($request)) {
  675. // Retrieve HTTP status code
  676. list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);
  677. } else {
  678. // $user->lang['RSS_YAHOO_NO_METHOD'] = sprintf($user->lang['RSS_YAHOO_NO_METHOD'], $request, $xml);
  679. $this->gym_error(503, 'RSS_YAHOO_NO_METHOD', __FILE__, __LINE__);
  680. }
  681. }
  682. // Check the XML return message
  683. // Do it this way here in case curl actually returned no header
  684. // but did get the proper answer.
  685. if (!strpos($xml, 'success')) {
  686. // Check the HTTP Status code
  687. switch( $status_code ) {
  688. case 200: // Success
  689. set_config('gym_pinged_today', @$config['gym_pinged_today'] + 1, 1);
  690. break;
  691. case 503:
  692. $this->gym_error(500, 'RSS_YAHOO_503', __FILE__, __LINE__);
  693. break;
  694. case 403:
  695. $this->gym_error(500, 'RSS_YAHOO_403', __FILE__, __LINE__);
  696. break;
  697. case 400:
  698. // $user->lang['RSS_YAHOO_400_MSG'] = sprintf($user->lang['RSS_YAHOO_400_MSG'], $request, $xml);
  699. $this->gym_error(500,'RSS_YAHOO_400', __FILE__, __LINE__);
  700. break;
  701. default:
  702. // $user->lang['RSS_YAHOO_ERROR_MSG'] = sprintf($user->lang['RSS_YAHOO_400_MSG'], $status_code, $request, $xml);
  703. $this->gym_error(500, 'RSS_YAHOO_500', __FILE__, __LINE__);
  704. }
  705. }
  706. return;
  707. }
  708. }
  709. ?>