OSDN Git Service

BugTrack/727 Added 'Cacel' button into edit form
[pukiwiki/pukiwiki.git] / lib / trackback.php
1 <?php
2 // $Id: trackback.php,v 1.2 2004/10/10 12:49:56 henoheno Exp $
3 /*
4  * PukiWiki TrackBack ¥×¥í¥°¥é¥à
5  * (C) 2003, Katsumi Saito <katsumi@jo1upk.ymt.prug.or.jp>
6  * License: GPL
7  *
8  * http://localhost/pukiwiki/pukiwiki.php?FrontPage ¤ÈÌÀ³Î¤Ë»ØÄꤷ¤Ê¤¤¤È
9  * TrackBack ID ¤Î¼èÆÀ¤Ï¤Ç¤­¤Ê¤¤
10  *
11  * tb_get_id($page)        TrackBack Ping ID¤ò¼èÆÀ
12  * tb_id2page($tb_id)      TrackBack Ping ID ¤«¤é¥Ú¡¼¥¸Ì¾¤ò¼èÆÀ
13  * tb_get_filename($page)  TrackBack Ping ¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë̾¤ò¼èÆÀ
14  * tb_count($page)         TrackBack Ping ¥Ç¡¼¥¿¸Ä¿ô¼èÆÀ  // pukiwiki.skin.LANG.php
15  * tb_send($page, $data)   TrackBack Ping Á÷¿®  // file.php
16  * tb_delete($page)        TrackBack Ping ¥Ç¡¼¥¿ºï½ü  // edit.inc.php
17  * tb_get($file, $key = 1) TrackBack Ping ¥Ç¡¼¥¿ÆþÎÏ
18  * tb_get_rdf($page)       Ê¸¾ÏÃæ¤ËËä¤á¹þ¤à¤¿¤á¤Îrdf¤ò¥Ç¡¼¥¿¤òÀ¸À® // pukiwiki.php
19  * tb_get_url($url)        Ê¸½ñ¤òGET¤·¡¢Ëä¤á¹þ¤Þ¤ì¤¿TrackBack Ping URL¤ò¼èÆÀ
20  * class TrackBack_XML     XML¤«¤éTrackBack Ping ID¤ò¼èÆÀ¤¹¤ë¥¯¥é¥¹
21  * == Referer Âбþʬ ==
22  * ref_save($page)         Referer ¥Ç¡¼¥¿Êݸ(¹¹¿·) // pukiwiki.php
23  */
24
25 // TrackBack Ping ID¤ò¼èÆÀ
26 function tb_get_id($page)
27 {
28         return md5($page);
29 }
30
31 // TrackBack Ping ID ¤«¤é¥Ú¡¼¥¸Ì¾¤ò¼èÆÀ
32 function tb_id2page($tb_id)
33 {
34         static $pages, $cache = array();
35
36         if (isset($cache[$tb_id])) return $cache[$tb_id];
37
38         if (! isset($pages)) $pages = get_existpages();
39
40         foreach ($pages as $page) {
41                 $_tb_id = tb_get_id($page);
42                 $cache[$_tb_id] = $page;
43                 unset($pages[$page]);
44                 if ($_tb_id == $tb_id) return $page;
45         }
46
47         return FALSE; // Not found
48 }
49
50 // TrackBack Ping ¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë̾¤ò¼èÆÀ
51 function tb_get_filename($page, $ext = '.txt')
52 {
53         return TRACKBACK_DIR . encode($page) . $ext;
54 }
55
56 // TrackBack Ping ¥Ç¡¼¥¿¸Ä¿ô¼èÆÀ
57 function tb_count($page, $ext = '.txt')
58 {
59         $filename = tb_get_filename($page, $ext);
60         return file_exists($filename) ? count(file($filename)) : 0;
61 }
62
63 // TrackBack Ping Á÷¿®
64 function tb_send($page, $data)
65 {
66         global $script, $trackback;
67
68         if (! $trackback) return;
69
70         // ½èÍý¼Â¹Ô»þ´ÖÀ©¸Â(php.ini ¥ª¥×¥·¥ç¥ó max_execution_time )
71         if (ini_get('safe_mode') == '0') set_time_limit(0);
72
73         $data = convert_html($data);
74
75         // convert_html() ÊÑ´¹·ë²Ì¤Î <a> ¥¿¥°¤«¤é URL Ãê½Ð
76         preg_match_all('#href="(https?://[^"]+)"#', $data, $links, PREG_PATTERN_ORDER);
77
78         // ¼«¥Û¥¹¥È($script¤Ç»Ï¤Þ¤ëurl)¤ò½ü¤¯
79         $links = preg_grep("/^(?!".preg_quote($script,'/')."\?)./", $links[1]);
80
81         // ¥ê¥ó¥¯Ìµ¤·¤Ï½ªÎ»
82         if (! is_array($links) || empty($links)) return;
83
84         $r_page = rawurlencode($page);
85         $excerpt = strip_htmltag(convert_html(get_source($page)));
86
87         // ¼«Ê¸½ñ¤Î¾ðÊó
88         $putdata = array(
89                 'title'     => $page, // ¥¿¥¤¥È¥ë¤Ï¥Ú¡¼¥¸Ì¾
90                 'url'       => "$script?$r_page", // Á÷¿®»þ¤ËºÆÅÙ¡¢rawurlencode ¤µ¤ì¤ë
91                 'excerpt'   => mb_strimwidth(preg_replace("/[\r\n]/", ' ', $excerpt), 0, 255, '...'),
92                 'blog_name' => 'PukiWiki/TrackBack 0.1',
93                 'charset'   => SOURCE_ENCODING // Á÷¿®Â¦Ê¸»ú¥³¡¼¥É(̤´ûÄê)
94         );
95
96         foreach ($links as $link) {
97                 // URL ¤«¤é TrackBack ID ¤ò¼èÆÀ¤¹¤ë
98                 $tb_id = tb_get_url($link);
99                 if (empty($tb_id)) continue; // Trackback is not supported
100
101                 $result = http_request($tb_id, 'POST', '', $putdata);
102                 // FIXME: ¥¨¥é¡¼½èÍý¤ò¹Ô¤Ã¤Æ¤â¡¢¤¸¤ã¡¢¤É¤¦¤¹¤ë¡©¤À¤·¤Ê¤¡...
103         }
104 }
105
106 // TrackBack Ping ¥Ç¡¼¥¿ºï½ü
107 function tb_delete($page)
108 {
109         $filename = tb_get_filename($page);
110         if (file_exists($filename))
111                 @unlink($filename);
112 }
113
114 // TrackBack Ping ¥Ç¡¼¥¿ÆþÎÏ
115 function tb_get($file, $key = 1)
116 {
117         if (! file_exists($file)) return array();
118
119         $result = array();
120         $fp = @fopen($file, 'r');
121         set_file_buffer($fp, 0);
122         flock($fp, LOCK_EX);
123         rewind($fp);
124         while ($data = @fgetcsv($fp, 8192, ',')) {
125                 // $data[$key] = URL
126                 $result[rawurldecode($data[$key])] = $data;
127         }
128         flock($fp, LOCK_UN);
129         fclose ($fp);
130
131         return $result;
132 }
133
134 // Ê¸¾ÏÃæ¤Ë trackback:ping ¤òËä¤á¹þ¤à¤¿¤á¤Î¥Ç¡¼¥¿¤òÀ¸À®
135 function tb_get_rdf($page)
136 {
137         global $trackback;
138
139         if (! $trackback) return '';
140
141         $r_page = rawurlencode($page);
142         $tb_id  = tb_get_id($page);
143         // $dcdate = substr_replace(get_date('Y-m-d\TH:i:sO', $time), ':', -2, 0);
144         // dc:date="$dcdate"
145
146         $_script = get_script_uri(); // Get absolute path
147
148         return <<<EOD
149 <!--
150 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
151   xmlns:dc="http://purl.org/dc/elements/1.1/"
152   xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
153  <rdf:Description
154    rdf:about="$_script?$r_page"
155    dc:identifier="$_script?$r_page"
156    dc:title="$page"
157    trackback:ping="$_script?tb_id=$tb_id" />
158 </rdf:RDF>
159 -->
160 EOD;
161 }
162
163 // Ê¸½ñ¤òGET¤·¡¢Ëä¤á¹þ¤Þ¤ì¤¿TrackBack Ping url¤ò¼èÆÀ
164 function tb_get_url($url)
165 {
166         // ¥×¥í¥­¥·¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ë¥Û¥¹¥È¤Ë¤Ïping¤òÁ÷¿®¤·¤Ê¤¤
167         $parse_url = parse_url($url);
168         if (empty($parse_url['host']) || via_proxy($parse_url['host']))
169                 return '';
170
171         $data = http_request($url);
172         if ($data['rc'] !== 200) return '';
173
174         if (! preg_match_all('#<rdf:RDF[^>]*>(.*?)</rdf:RDF>#si', $data['data'],
175             $matches, PREG_PATTERN_ORDER))
176                 return '';
177
178         $obj = new TrackBack_XML();
179         foreach ($matches[1] as $body) {
180                 $tb_url = $obj->parse($body, $url);
181                 if ($tb_url !== FALSE) return $tb_url;
182         }
183
184         return '';
185 }
186
187 // Ëä¤á¹þ¤Þ¤ì¤¿¥Ç¡¼¥¿¤«¤é TrackBack Ping url¤ò¼èÆÀ¤¹¤ë¥¯¥é¥¹
188 class TrackBack_XML
189 {
190         var $url;
191         var $tb_url;
192
193         function parse($buf, $url)
194         {
195                 // ½é´ü²½
196                 $this->url    = $url;
197                 $this->tb_url = FALSE;
198
199                 $xml_parser = xml_parser_create();
200                 if ($xml_parser === FALSE) return FALSE;
201
202                 xml_set_element_handler($xml_parser, array(& $this, 'start_element'),
203                         array(& $this, 'end_element'));
204
205                 if (! xml_parse($xml_parser, $buf, TRUE)) {
206 /*                      die(sprintf('XML error: %s at line %d in %s',
207                                 xml_error_string(xml_get_error_code($xml_parser)),
208                                 xml_get_current_line_number($xml_parser),
209                                 $buf
210                         ));
211 */
212                         return FALSE;
213                 }
214
215                 return $this->tb_url;
216         }
217
218         function start_element($parser, $name, $attrs) {
219                 if ($name !== 'RDF:DESCRIPTION') return;
220
221                 $about = $url = $tb_url = '';
222                 foreach ($attrs as $key=>$value) {
223                         switch ($key) {
224                         case 'RDF:ABOUT':
225                                 $about = $value;
226                                 break;
227                         case 'DC:IDENTIFER':
228                         case 'DC:IDENTIFIER':
229                                 $url = $value;
230                                 break;
231                         case 'TRACKBACK:PING':
232                                 $tb_url = $value;
233                                 break;
234                         }
235                 }
236                 if ($about == $this->url || $url == $this->url) {
237                         $this->tb_url = $tb_url;
238                 }
239         }
240
241         function end_element($parser, $name) {}
242 }
243
244 // Referer ¥Ç¡¼¥¿Êݸ(¹¹¿·)
245 function ref_save($page)
246 {
247         global $referer;
248
249         if (! $referer || empty($_SERVER['HTTP_REFERER'])) return;
250
251         $url = $_SERVER['HTTP_REFERER'];
252
253         // URI ¤ÎÂÅÅöÀ­É¾²Á
254         // ¼«¥µ¥¤¥ÈÆâ¤Î¾ì¹ç¤Ï½èÍý¤·¤Ê¤¤
255         $parse_url = parse_url($url);
256         if (empty($parse_url['host']) || $parse_url['host'] == $_SERVER['HTTP_HOST'])
257                 return;
258
259         // TRACKBACK_DIR ¤Î¸ºß¤È½ñ¤­¹þ¤ß²Äǽ¤«¤Î³Îǧ
260         if (! is_dir(TRACKBACK_DIR))      die(TRACKBACK_DIR.': No such directory');
261         if (! is_writable(TRACKBACK_DIR)) die(TRACKBACK_DIR.': Permission denied');
262
263         // Referer ¤Î¥Ç¡¼¥¿¤ò¹¹¿·
264         if (ereg("[,\"\n\r]", $url))
265                 $url = '"' . str_replace('"', '""', $url) . '"';
266
267         $filename = tb_get_filename($page, '.ref');
268         $data     = tb_get($filename, 3);
269         $d_url    = rawurldecode($url);
270         if (! isset($data[$d_url])) {
271                 // 0:ºÇ½ª¹¹¿·Æü»þ, 1:½é²óÅÐÏ¿Æü»þ, 2:»²¾È¥«¥¦¥ó¥¿, 3:Referer ¥Ø¥Ã¥À, 4:ÍøÍѲÄÈݥե饰(1¤ÏÍ­¸ú)
272                 $data[$d_url] = array(UTIME, UTIME, 0, $url, 1);
273         }
274         $data[$d_url][0] = UTIME;
275         $data[$d_url][2]++;
276
277         $fp = fopen($filename, 'w');
278         if ($fp === FALSE) return 1;    
279         set_file_buffer($fp, 0);
280         flock($fp, LOCK_EX);
281         rewind($fp);
282         foreach ($data as $line) {
283                 fwrite($fp, join(',', $line) . "\n");
284         }
285         flock($fp, LOCK_UN);
286         fclose($fp);
287
288         return 0;
289 }
290 ?>