OSDN Git Service

BugTrack2/139: Correct. Deleted a first space at preview.
[pukiwiki/pukiwiki.git] / plugin / showrss.inc.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone
3 // $Id: showrss.inc.php,v 1.17 2005/04/09 03:18:06 henoheno Exp $
4 //  Id:showrss.inc.php,v 1.40 2003/03/18 11:52:58 hiro Exp
5 //
6 // Show RSS of remote site plugin
7
8 /*
9  * Created by hiro_do3ob@yahoo.co.jp
10  * Modified by PANDA <panda@arino.jp>, and PukiWiki Developers Team
11  * Licence: GPL, same as PukiWiki
12  * This plugin needs 'PHP xml extension'
13  */
14
15 // Show this plugin is enable or not for this PukiWiki
16 function plugin_showrss_action()
17 {
18         $xml_extension      = extension_loaded('xml');
19         $mbstring_extension = extension_loaded('mbstring');
20
21         $xml_msg      = $xml_extension      ? 'xml extension is loaded'      : 'COLOR(RED){xml extension is not loaded}';
22         $mbstring_msg = $mbstring_extension ? 'mbstring extension is loaded' : 'COLOR(RED){mbstring extension is not loaded}';
23         $showrss_info  =
24                 '| xml parser | ' . $xml_msg      . ' |' . "\n" .
25                 '| multibyte  | ' . $mbstring_msg . ' |' . "\n";
26
27         return array('msg' => 'showrss_info', 'body' => convert_html($showrss_info));
28 }
29
30 function plugin_showrss_convert()
31 {
32         if (func_num_args() == 0) {
33                 return '<p>showrss: no parameter(s).</p>' . "\n";
34         } else if (! extension_loaded('xml')) {
35                 return '<p>showrss: xml extension is not loaded</p>' . "\n";
36         }
37
38         $array  = func_get_args();
39         $rssurl = $tmplname = $usecache = $usetimestamp = '';
40
41         switch (func_num_args()) {
42         case 4: $usetimestamp = trim($array[3]);
43         case 3: $usecache     = $array[2];
44         case 2: $tmplname     = strtolower(trim($array[1]));
45         case 1: $rssurl       = trim($array[0]);
46         }
47
48         if (! is_url($rssurl))
49                 return '<p>showrss: syntax error. ' . htmlspecialchars($rssurl) . '</p>' . "\n";
50
51         $class = 'ShowRSS_html_' . $tmplname;
52         if (! class_exists($class)) $class = 'ShowRSS_html';
53
54         list($rss, $time) = plugin_showrss_get_rss($rssurl, $usecache);
55         if ($rss === FALSE)
56                 return '<p>showrss: cannot get rss from server.</p>' . "\n";
57
58         $obj = new $class($rss);
59
60         $timestamp = '';
61         if ($usetimestamp > 0) {
62                 $time = get_date('Y/m/d H:i:s',$time);
63                 $timestamp = '<p style="font-size:10px; font-weight:bold">Last-Modified:' . $time . '</p>';
64         }
65         return $obj->toString($timestamp);
66 }
67
68 // Create HTML from RSS array()
69 class ShowRSS_html
70 {
71         var $items = array();
72         var $class = '';
73
74         function ShowRSS_html($rss)
75         {
76                 foreach ($rss as $date=>$items) {
77                         foreach ($items as $item) {
78                                 $link  = $item['LINK'];
79                                 $title = $item['TITLE'];
80                                 $passage = get_passage($item['_TIMESTAMP']);
81                                 $link = '<a href="' . $link . '" title="' .  $title . ' ' .
82                                         $passage . '" rel="nofollow">' . $title . '</a>';
83                                 $this->items[$date][] = $this->format_link($link);
84                         }
85                 }
86         }
87
88         function format_link($link)
89         {
90                 return $link . '<br />' . "\n";
91         }
92
93         function format_list($date, $str)
94         {
95                 return $str;
96         }
97
98         function format_body($str)
99         {
100                 return $str;
101         }
102
103         function toString($timestamp)
104         {
105                 $retval = '';
106                 foreach ($this->items as $date=>$items)
107                         $retval .= $this->format_list($date, join('', $items));
108                 $retval = $this->format_body($retval);
109                 return <<<EOD
110 <div{$this->class}>
111 $retval$timestamp
112 </div>
113 EOD;
114         }
115 }
116
117 class ShowRSS_html_menubar extends ShowRSS_html
118 {
119         var $class = ' class="small"';
120
121         function format_link($link) {
122                 return '<li>' . $link . '</li>' . "\n";
123         }
124
125         function format_body($str) {
126                 return '<ul class="recent_list">' . "\n" . $str . '</ul>' . "\n";
127         }
128 }
129
130 class ShowRSS_html_recent extends ShowRSS_html
131 {
132         var $class = ' class="small"';
133
134         function format_link($link) {
135                 return '<li>' . $link . '</li>' . "\n";
136         }
137
138         function format_list($date, $str) {
139                 return '<strong>' . $date . '</strong>' . "\n" .
140                         '<ul class="recent_list">' . "\n" . $str . '</ul>' . "\n";
141         }
142 }
143
144 // Get RSS
145 function plugin_showrss_get_rss($target, $usecache)
146 {
147         $buf = '';
148         $time = NULL;
149         if ($usecache) {
150                 // Remove expired cache
151                 plugin_showrss_cache_expire($usecache);
152
153                 // Get the cache not expired
154                 $filename = CACHE_DIR . encode($target) . '.tmp';
155                 if (is_readable($filename)) {
156                         $buf  = join('', file($filename));
157                         $time = filemtime($filename) - LOCALZONE;
158                 }
159         }
160
161         if ($time === NULL) {
162                 // Newly get RSS
163                 $data = http_request($target);
164                 if ($data['rc'] !== 200)
165                         return array(FALSE, 0);
166
167                 $buf = $data['data'];
168                 $time = UTIME;
169
170                 // Save RSS into cache
171                 if ($usecache) {
172                         $fp = fopen($filename, 'w');
173                         fwrite($fp, $buf);
174                         fclose($fp);
175                 }
176         }
177
178         // Parse
179         $obj = new ShowRSS_XML();
180         return array($obj->parse($buf),$time);
181 }
182
183 // Remove cache if expired limit exeed
184 function plugin_showrss_cache_expire($usecache)
185 {
186         $expire = $usecache * 60 * 60; // Hour
187         $dh = dir(CACHE_DIR);
188         while (($file = $dh->read()) !== FALSE) {
189                 if (substr($file, -4) != '.tmp') continue;
190                 $file = CACHE_DIR . $file;
191                 $last = time() - filemtime($file);
192                 if ($last > $expire) unlink($file);
193         }
194         $dh->close();
195 }
196
197 // Get RSS and array() them
198 class ShowRSS_XML
199 {
200         var $items;
201         var $item;
202         var $is_item;
203         var $tag;
204         var $encoding;
205
206         function parse($buf)
207         {
208                 $this->items   = array();
209                 $this->item    = array();
210                 $this->is_item = FALSE;
211                 $this->tag     = '';
212
213                 // Detect encoding
214                 $this->encoding = mb_detect_encoding($buf);
215                 if (! in_array(strtolower($this->encoding), array('us-ascii', 'iso-8859-1', 'utf-8'))) {
216                         $buf = mb_convert_encoding($buf, 'utf-8', $this->encoding);
217                         $this->encoding = 'utf-8';
218                 }
219                 $xml_parser = xml_parser_create($this->encoding);
220                 xml_set_element_handler($xml_parser, array(& $this, 'start_element'), array(& $this, 'end_element'));
221                 xml_set_character_data_handler($xml_parser, array(& $this, 'character_data'));
222
223                 if (! xml_parse($xml_parser, $buf, 1)) {
224                         return(sprintf('XML error: %s at line %d in %s',
225                                 xml_error_string(xml_get_error_code($xml_parser)),
226                                 xml_get_current_line_number($xml_parser), $buf));
227                 }
228                 xml_parser_free($xml_parser);
229
230                 return $this->items;
231         }
232
233         function escape($str)
234         {
235                 // Unescape already-escaped chars (&lt;, &gt;, &amp;, ...) in RSS body before htmlspecialchars()
236                 $str = strtr($str, array_flip(get_html_translation_table(ENT_COMPAT)));
237                 // Escape
238                 $str = htmlspecialchars($str);
239                 // Encoding conversion
240                 $str = mb_convert_encoding($str, SOURCE_ENCODING, $this->encoding);
241                 return trim($str);
242         }
243
244         // Tag start
245         function start_element($parser, $name, $attrs)
246         {
247                 if ($this->is_item) {
248                         $this->tag     = $name;
249                 } else if ($name == 'ITEM') {
250                         $this->is_item = TRUE;
251                 }
252         }
253
254         // Tag end
255         function end_element($parser, $name)
256         {
257                 if (! $this->is_item || $name != 'ITEM') return;
258
259                 $item = array_map(array(& $this, 'escape'), $this->item);
260                 $this->item = array();
261
262                 if (isset($item['DC:DATE'])) {
263                         $time = plugin_showrss_get_timestamp($item['DC:DATE']);
264                         
265                 } else if (isset($item['PUBDATE'])) {
266                         $time = plugin_showrss_get_timestamp($item['PUBDATE']);
267                         
268                 } else if (isset($item['DESCRIPTION']) &&
269                         ($description = trim($item['DESCRIPTION'])) != '' &&
270                         ($time = strtotime($description)) != -1) {
271                                 $time -= LOCALZONE;
272
273                 } else {
274                         $time = time() - LOCALZONE;
275                 }
276                 $item['_TIMESTAMP'] = $time;
277                 $date = get_date('Y-m-d', $item['_TIMESTAMP']);
278
279                 $this->items[$date][] = $item;
280                 $this->is_item        = FALSE;
281         }
282
283         function character_data($parser, $data)
284         {
285                 if (! $this->is_item) return;
286                 if (! isset($this->item[$this->tag])) $this->item[$this->tag] = '';
287                 $this->item[$this->tag] .= $data;
288         }
289 }
290
291 function plugin_showrss_get_timestamp($str)
292 {
293         if (($str = trim($str)) == '')
294                 return UTIME;
295
296         $matches = array();
297         if (! preg_match('/(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(([+-])(\d{2}):(\d{2}))?/', $str, $matches)) {
298                 $time = strtotime($str);
299                 return ($time == -1) ? UTIME : $time - LOCALZONE;
300         }
301         $str  = $matches[1];
302         $time = strtotime($matches[1] . ' ' . $matches[2]);
303         if (! empty($matches[3])) {
304                 $diff = ($matches[5] * 60 + $matches[6]) * 60;
305                 $time += ($matches[4] == '-' ? $diff : -$diff);
306         }
307         return $time;
308 }
309 ?>