| Textpattern | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /* 4 This is Textpattern 5 Copyright 2005 by Dean Allen - all rights reserved. 6 7 Use of this software denotes acceptance of the Textpattern license agreement 8 9 $HeadURL: https://textpattern.googlecode.com/svn/releases/4.5.4/source/textpattern/publish/rss.php $ 10 $LastChangedRevision: 4011 $ 11 12 */ 13 14 15 // ------------------------------------------------------------- 16 function rss() 17 { 18 global $prefs,$thisarticle; 19 set_error_handler('feedErrorHandler'); 20 ob_clean(); 21 extract($prefs); 22 23 extract(doSlash(gpsa(array('limit','area')))); 24 25 // build filter criteria from a comma-separated list of sections and categories 26 $feed_filter_limit = get_pref('feed_filter_limit', 10); 27 $section = gps('section'); 28 $category = gps('category'); 29 if (!is_scalar($section) || !is_scalar($category)) { 30 txp_die('Not Found', 404); 31 } 32 33 $section = ($section ? array_slice(array_unique(do_list($section)), 0, $feed_filter_limit) : array()); 34 $category = ($category ? array_slice(array_unique(do_list($category)), 0, $feed_filter_limit) : array()); 35 $st = array(); 36 foreach ($section as $s) 37 { 38 $st[] = fetch_section_title($s); 39 } 40 $ct = array(); 41 foreach ($category as $c) 42 { 43 $ct[] = fetch_category_title($c); 44 } 45 46 $sitename .= ($section) ? ' - '.join(' - ', $st) : ''; 47 $sitename .= ($category) ? ' - '.join(' - ', $ct) : ''; 48 $dn = explode('/',$siteurl); 49 $mail_or_domain = ($use_mail_on_feeds_id)? eE($blog_mail_uid):$dn[0]; 50 51 // feed header 52 $out[] = tag('http://textpattern.com/?v='.$version, 'generator'); 53 $out[] = tag(doSpecial($sitename),'title'); 54 $out[] = tag(hu,'link'); 55 $out[] = '<atom:link href="'.pagelinkurl(array('rss'=>1,'area'=>$area,'section'=>$section,'category'=>$category,'limit'=>$limit)).'" rel="self" type="application/rss+xml" />'; 56 $out[] = tag(doSpecial($site_slogan),'description'); 57 $last = fetch('unix_timestamp(val)','txp_prefs','name','lastmod'); 58 $out[] = tag(safe_strftime('rfc822',$last),'pubDate'); 59 $out[] = callback_event('rss_head'); 60 61 // feed items 62 $articles = array(); 63 $section = doSlash($section); 64 $category = doSlash($category); 65 66 if (!$area or $area=='article') { 67 68 $sfilter = (!empty($section)) ? "and Section in ('".join("','", $section)."')" : ''; 69 $cfilter = (!empty($category))? "and (Category1 in ('".join("','", $category)."') or Category2 in ('".join("','", $category)."'))" : ''; 70 $limit = ($limit) ? $limit : $rss_how_many; 71 $limit = intval(min($limit,max(100,$rss_how_many))); 72 73 $frs = safe_column("name", "txp_section", "in_rss != '1'"); 74 if ($frs) foreach($frs as $f) $query[] = "and Section != '".doSlash($f)."'"; 75 $query[] = $sfilter; 76 $query[] = $cfilter; 77 78 $expired = ($publish_expired_articles) ? '' : ' and (now() <= Expires or Expires = '.NULLDATETIME.') '; 79 $rs = safe_rows_start( 80 "*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires, ID as thisid", 81 "textpattern", 82 "Status = 4 ".join(' ',$query). 83 "and Posted < now()".$expired."order by Posted desc limit $limit" 84 ); 85 86 if($rs) { 87 while ($a = nextRow($rs)) { 88 extract($a); 89 populateArticleData($a); 90 91 $cb = callback_event('rss_entry'); 92 93 $a['posted'] = $uPosted; 94 95 $permlink = permlinkurl($a); 96 $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink)); 97 $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink)); 98 99 if ($syndicate_body_or_excerpt) { 100 # short feed: use body as summary if there's no excerpt 101 if (!trim($summary)) 102 $summary = $content; 103 $content = ''; 104 } 105 106 if ($show_comment_count_in_feed) { 107 $count = ($comments_count > 0) ? ' ['.$comments_count.']' : ''; 108 } else $count = ''; 109 110 $Title = escape_title(strip_tags($Title)).$count; 111 112 $thisauthor = get_author_name($AuthorID); 113 114 $item = tag($Title,'title').n. 115 (trim($summary) ? tag(n.escape_cdata($summary).n,'description').n : ''). 116 (trim($content) ? tag(n.escape_cdata($content).n,'content:encoded').n : ''). 117 tag($permlink,'link').n. 118 tag(safe_strftime('rfc822',$a['posted']),'pubDate').n. 119 tag(htmlspecialchars($thisauthor),'dc:creator').n. 120 tag('tag:'.$mail_or_domain.','.$feed_time.':'.$blog_uid.'/'.$uid,'guid', ' isPermaLink="false"').n. 121 $cb; 122 123 $articles[$ID] = tag($item,'item'); 124 125 $etags[$ID] = strtoupper(dechex(crc32($articles[$ID]))); 126 $dates[$ID] = $uPosted; 127 128 } 129 } 130 } elseif ($area=='link') { 131 132 $cfilter = ($category) ? "category in ('".join("','", $category)."')" : '1'; 133 $limit = ($limit) ? $limit : $rss_how_many; 134 $limit = intval(min($limit,max(100,$rss_how_many))); 135 136 $rs = safe_rows_start("*, unix_timestamp(date) as uDate", "txp_link", "$cfilter order by date desc limit $limit"); 137 138 if ($rs) { 139 while ($a = nextRow($rs)) { 140 extract($a); 141 $item = 142 tag(doSpecial($linkname),'title').n. 143 tag(doSpecial($description),'description').n. 144 tag(doSpecial($url),'link').n. 145 tag(safe_strftime('rfc822',$uDate),'pubDate'); 146 $articles[$id] = tag($item,'item'); 147 148 $etags[$id] = strtoupper(dechex(crc32($articles[$id]))); 149 $dates[$id] = $date; 150 } 151 } 152 } 153 154 if (!$articles) { 155 if ($section) { 156 if (safe_field('name', 'txp_section', "name in ('".join("','", $section)."')") == false) { 157 txp_die(gTxt('404_not_found'), '404'); 158 } 159 } elseif ($category) { 160 switch ($area) { 161 case 'link': 162 if (safe_field('id', 'txp_category', "name = '$category' and type = 'link'") == false) { 163 txp_die(gTxt('404_not_found'), '404'); 164 } 165 break; 166 167 case 'article': 168 default: 169 if (safe_field('id', 'txp_category', "name in ('".join("','", $category)."') and type = 'article'") == false) { 170 txp_die(gTxt('404_not_found'), '404'); 171 } 172 break; 173 } 174 } 175 } else { 176 //turn on compression if we aren't using it already 177 if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) { 178 // make sure notices/warnings/errors don't fudge up the feed 179 // when compression is used 180 $buf = ''; 181 while ($b = @ob_get_clean()) 182 $buf .= $b; 183 @ob_start('ob_gzhandler'); 184 echo $buf; 185 } 186 187 handle_lastmod(); 188 $hims = serverset('HTTP_IF_MODIFIED_SINCE'); 189 $imsd = ($hims) ? strtotime($hims) : 0; 190 191 if (is_callable('apache_request_headers')) { 192 $headers = apache_request_headers(); 193 if (isset($headers["A-IM"])) { 194 $canaim = strpos($headers["A-IM"], "feed"); 195 } else { 196 $canaim = false; 197 } 198 } else { 199 $canaim = false; 200 } 201 202 $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH')); 203 204 $cutarticles = false; 205 206 if ($canaim !== false) { 207 foreach($articles as $id=>$thing) { 208 if (strpos($hinm, $etags[$id]) !== false) { 209 unset($articles[$id]); 210 $cutarticles = true; 211 $cut_etag = true; 212 } 213 214 if ($dates[$id] < $imsd) { 215 unset($articles[$id]); 216 $cutarticles = true; 217 $cut_time = true; 218 } 219 } 220 } 221 222 if (isset($cut_etag) && isset($cut_time)) { 223 header("Vary: If-None-Match, If-Modified-Since"); 224 } else if (isset($cut_etag)) { 225 header("Vary: If-None-Match"); 226 } else if (isset($cut_time)) { 227 header("Vary: If-Modified-Since"); 228 } 229 230 $etag = @join("-",$etags); 231 232 if (strstr($hinm, $etag)) { 233 txp_status_header('304 Not Modified'); 234 exit(0); 235 } 236 237 if ($cutarticles) { 238 //header("HTTP/1.1 226 IM Used"); 239 //This should be used as opposed to 200, but Apache doesn't like it. 240 //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200. 241 header("Cache-Control: no-store, im"); 242 header("IM: feed"); 243 } 244 } 245 246 $out = array_merge($out, $articles); 247 248 header("Content-Type: application/rss+xml; charset=utf-8"); 249 if (isset($etag)) header('ETag: "'.$etag.'"'); 250 return 251 '<?xml version="1.0" encoding="utf-8"?>'.n. 252 '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">'.n. 253 tag(join(n,$out),'channel').n. 254 '</rss>'; 255 } 256 257 258 // DEPRECATED FUNCTIONS 259 // included for backwards compatibility with older plugins only 260 function rss_safe_hed($toUnicode) { 261 262 if (version_compare(phpversion(), "5.0.0", ">=")) { 263 $str = html_entity_decode($toUnicode, ENT_QUOTES, "UTF-8"); 264 } else { 265 $trans_tbl = get_html_translation_table(HTML_ENTITIES); 266 foreach($trans_tbl as $k => $v) { 267 $ttr[$v] = utf8_encode($k); 268 } 269 $str = strtr($toUnicode, $ttr); 270 } 271 return $str; 272 } 273 274 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title