2 // $Id: trackback.php,v 1.7 2004/12/18 14:32:58 henoheno Exp $
5 * (C) 2003-2004 PukiWiki Developer Team
6 * (C) 2003, Katsumi Saito <katsumi@jo1upk.ymt.prug.or.jp>
9 * http://localhost/pukiwiki/pukiwiki.php?FrontPage ¤ÈÌÀ³Î¤Ë»ØÄꤷ¤Ê¤¤¤È
10 * TrackBack ID ¤Î¼èÆÀ¤Ï¤Ç¤¤Ê¤¤
12 * tb_get_id($page) Get TrackBack Ping ID from page name
13 * tb_id2page($tb_id) Get page name from TrackBack Ping ID
14 * tb_get_filename($page) Get file name of TrackBack Ping data
15 * tb_count($page) Count the number of TrackBack Pings included for the page
16 * // pukiwiki.skin.LANG.php
17 * tb_send($page, $data) Send TrackBack Ping(s) automatically // file.php
18 * tb_delete($page) Remove TrackBack Ping data // edit.inc.php
19 * tb_get($file, $key = 1) TrackBack Ping ¥Ç¡¼¥¿ÆþÎÏ
20 * tb_get_rdf($page) ʸ¾ÏÃæ¤ËËä¤á¹þ¤à¤¿¤á¤Îrdf¤ò¥Ç¡¼¥¿¤òÀ¸À® // pukiwiki.php
21 * tb_get_url($url) ʸ½ñ¤òGET¤·¡¢Ëä¤á¹þ¤Þ¤ì¤¿TrackBack Ping URL¤ò¼èÆÀ
22 * class TrackBack_XML XML¤«¤éTrackBack Ping ID¤ò¼èÆÀ¤¹¤ë¥¯¥é¥¹
23 * == Referer Âбþʬ ==
24 * ref_save($page) Save or update referer data // pukiwiki.php
27 define('PLUGIN_TRACKBACK_VERSION', 'PukiWiki/TrackBack 0.2');
29 // Get TrackBack Ping ID from page name
30 function tb_get_id($page)
35 // Get page name from TrackBack Ping ID
36 function tb_id2page($tb_id)
38 static $pages, $cache = array();
40 if (isset($cache[$tb_id])) return $cache[$tb_id];
42 if (! isset($pages)) $pages = get_existpages();
44 foreach ($pages as $page) {
45 $_tb_id = tb_get_id($page);
46 $cache[$_tb_id] = $page;
48 if ($tb_id == $_tb_id) return $cache[$tb_id];
51 $cache[$tb_id] = FALSE;
53 return $cache[$tb_id]; // Not found
56 // Get file name of TrackBack Ping data
57 function tb_get_filename($page, $ext = '.txt')
59 return TRACKBACK_DIR . encode($page) . $ext;
62 // Count the number of TrackBack Pings included for the page
63 function tb_count($page, $ext = '.txt')
65 $filename = tb_get_filename($page, $ext);
66 return file_exists($filename) ? count(file($filename)) : 0;
69 // Send TrackBack Ping(s) automatically
70 // $plus = Newly added lines may include URLs
71 // $minus = Removed lines may include URLs
72 function tb_send($page, $plus, $minus = '')
74 global $script, $trackback;
76 if (! $trackback) return;
78 // Disable 'max execution time' (php.ini: max_execution_time)
79 if (ini_get('safe_mode') == '0') set_time_limit(0);
81 // Get URLs from <a>(anchor) tag from convert_html()
83 $plus = convert_html($plus); // WARNING: heavy and may cause side-effect
84 preg_match_all('#href="(https?://[^"]+)"#', $plus, $links, PREG_PATTERN_ORDER);
85 $links = array_unique($links[1]);
87 // Reject from minus list
90 $minus = convert_html($minus); // WARNING: heavy and may cause side-effect
91 preg_match_all('#href="(https?://[^"]+)"#', $minus, $links_m, PREG_PATTERN_ORDER);
92 $links_m = array_unique($links_m[1]);
94 $links = array_diff($links, $links_m);
97 // Reject own URL (Pattern _NOT_ started with '$script' and '?')
98 $links = preg_grep('/^(?!' . preg_quote($script, '/') . '\?)./', $links);
101 if (! is_array($links) || empty($links)) return;
103 $r_page = rawurlencode($page);
104 $excerpt = strip_htmltag(convert_html(get_source($page)));
106 // Sender's information
108 'title' => $page, // Title = It's page name
109 'url' => "$script?$r_page", // will be rawurlencode() at send phase
110 'excerpt' => mb_strimwidth(preg_replace("/[\r\n]/", ' ', $excerpt), 0, 255, '...'),
111 'blog_name' => PLUGIN_TRACKBACK_VERSION,
112 'charset' => SOURCE_ENCODING // Ping text encoding (Not defined)
115 foreach ($links as $link) {
116 $tb_id = tb_get_url($link); // Get Trackback ID from the URL
117 if (empty($tb_id)) continue; // Trackback is not supported
119 $result = http_request($tb_id, 'POST', '', $putdata);
120 // FIXME: Create warning notification space at pukiwiki.skin!
124 // Remove TrackBack Ping data
125 function tb_delete($page)
127 $filename = tb_get_filename($page);
128 if (file_exists($filename)) @unlink($filename);
131 // TrackBack Ping ¥Ç¡¼¥¿ÆþÎÏ
132 function tb_get($file, $key = 1)
134 if (! file_exists($file)) return array();
137 $fp = @fopen($file, 'r');
138 set_file_buffer($fp, 0);
141 while ($data = @fgetcsv($fp, 8192, ',')) {
143 $result[rawurldecode($data[$key])] = $data;
151 // ʸ¾ÏÃæ¤Ë trackback:ping ¤òËä¤á¹þ¤à¤¿¤á¤Î¥Ç¡¼¥¿¤òÀ¸À®
152 function tb_get_rdf($page)
156 if (! $trackback) return '';
158 $r_page = rawurlencode($page);
159 $tb_id = tb_get_id($page);
160 // $dcdate = substr_replace(get_date('Y-m-d\TH:i:sO', $time), ':', -2, 0);
163 $_script = get_script_uri(); // Get absolute path
167 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
168 xmlns:dc="http://purl.org/dc/elements/1.1/"
169 xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
171 rdf:about="$_script?$r_page"
172 dc:identifier="$_script?$r_page"
174 trackback:ping="$_script?tb_id=$tb_id" />
180 // ʸ½ñ¤òGET¤·¡¢Ëä¤á¹þ¤Þ¤ì¤¿TrackBack Ping url¤ò¼èÆÀ
181 function tb_get_url($url)
183 // ¥×¥í¥¥·¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ë¥Û¥¹¥È¤Ë¤Ïping¤òÁ÷¿®¤·¤Ê¤¤
184 $parse_url = parse_url($url);
185 if (empty($parse_url['host']) || via_proxy($parse_url['host']))
188 $data = http_request($url);
189 if ($data['rc'] !== 200) return '';
192 if (! preg_match_all('#<rdf:RDF[^>]*>(.*?)</rdf:RDF>#si', $data['data'],
193 $matches, PREG_PATTERN_ORDER))
196 $obj = new TrackBack_XML();
197 foreach ($matches[1] as $body) {
198 $tb_url = $obj->parse($body, $url);
199 if ($tb_url !== FALSE) return $tb_url;
205 // Ëä¤á¹þ¤Þ¤ì¤¿¥Ç¡¼¥¿¤«¤é TrackBack Ping url¤ò¼èÆÀ¤¹¤ë¥¯¥é¥¹
211 function parse($buf, $url)
215 $this->tb_url = FALSE;
217 $xml_parser = xml_parser_create();
218 if ($xml_parser === FALSE) return FALSE;
220 xml_set_element_handler($xml_parser, array(& $this, 'start_element'),
221 array(& $this, 'end_element'));
223 if (! xml_parse($xml_parser, $buf, TRUE)) {
224 /* die(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),
232 return $this->tb_url;
235 function start_element($parser, $name, $attrs)
237 if ($name !== 'RDF:DESCRIPTION') return;
239 $about = $url = $tb_url = '';
240 foreach ($attrs as $key=>$value) {
242 case 'RDF:ABOUT' : $about = $value; break;
243 case 'DC:IDENTIFER' : /*FALLTHROUGH*/
244 case 'DC:IDENTIFIER' : $url = $value; break;
245 case 'TRACKBACK:PING': $tb_url = $value; break;
248 if ($about == $this->url || $url == $this->url)
249 $this->tb_url = $tb_url;
252 function end_element($parser, $name) {}
255 // Save or update referer data
256 function ref_save($page)
260 if (! $referer || empty($_SERVER['HTTP_REFERER'])) return TRUE;
262 $url = $_SERVER['HTTP_REFERER'];
264 // Validate URI (Ignore own)
265 $parse_url = parse_url($url);
266 if (empty($parse_url['host']) || $parse_url['host'] == $_SERVER['HTTP_HOST'])
269 if (! is_dir(TRACKBACK_DIR)) die('No such directory: TRACKBACK_DIR');
270 if (! is_writable(TRACKBACK_DIR)) die('Permission denied: TRACKBACK_DIR');
272 // Update referer data
273 if (ereg("[,\"\n\r]", $url))
274 $url = '"' . str_replace('"', '""', $url) . '"';
276 $filename = tb_get_filename($page, '.ref');
277 $data = tb_get($filename, 3);
278 $d_url = rawurldecode($url);
279 if (! isset($data[$d_url])) {
280 // 0:ºÇ½ª¹¹¿·Æü»þ, 1:½é²óÅÐÏ¿Æü»þ, 2:»²¾È¥«¥¦¥ó¥¿,
281 // 3:Referer ¥Ø¥Ã¥À, 4:ÍøÍѲÄÈݥե饰(1¤Ï͸ú)
282 $data[$d_url] = array(UTIME, UTIME, 0, $url, 1);
284 $data[$d_url][0] = UTIME;
287 $fp = fopen($filename, 'w');
288 if ($fp === FALSE) return FALSE;
289 set_file_buffer($fp, 0);
292 foreach ($data as $line)
293 fwrite($fp, join(',', $line) . "\n");