1<?php 2 3/** 4 * Trackback server for use with the DokuWiki Linkback Plugin. 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Gina Haeussge <osd@foosel.net> 8 * @link http://wiki.foosel.net/snippets/dokuwiki/linkback 9 */ 10 11if (!defined('DOKU_INC')) 12 define('DOKU_INC', realpath(dirname(__FILE__) . '/../../../../') . '/'); 13 14if (!defined('NL')) 15 define('NL', "\n"); 16 17require_once (DOKU_INC . 'inc/init.php'); 18require_once (DOKU_INC . 'inc/common.php'); 19require_once (DOKU_INC . 'inc/events.php'); 20require_once (DOKU_INC . 'inc/pluginutils.php'); 21require_once (DOKU_PLUGIN . 'linkback/tools.php'); 22require_once (DOKU_PLUGIN . 'linkback/http.php'); 23 24class TrackbackServer { 25 26 // helper instance 27 var $tools; 28 29 /** 30 * Construct helper and process request. 31 */ 32 function __construct() { 33 $this->tools =& plugin_load('tools', 'linkback'); 34 $this->_process(); 35 } 36 37 /** 38 * Process trackback request. 39 */ 40 function _process() { 41 42 // Plugin not enabled? Quit 43 if (plugin_isdisabled('linkback')) { 44 $this->_printTrackbackError('Trackbacks disabled.'); 45 return; 46 } 47 48 // Trackbacks not enabled? Quit 49 if (!$this->tools->getConf('enable_trackback')) { 50 $this->_printTrackbackError('Trackbacks disabled.'); 51 return; 52 } 53 54 55 // No POST request? Quit 56 if ($_SERVER['REQUEST_METHOD'] != 'POST') { 57 $this->_printTrackbackError('Trackback was not received via HTTP POST.'); 58 return; 59 } 60 61 // get ID 62 $ID = substr($_SERVER['PATH_INFO'], 1); 63 64 $file = metaFN($ID, '.linkbacks'); 65 $data = array ( 66 'send' => false, 67 'receive' => false, 68 'display' => false, 69 'sentpings' => array (), 70 'receivedpings' => array (), 71 'number' => 0, 72 73 ); 74 75 if (@ file_exists($file)) 76 $data = unserialize(io_readFile($file, false)); 77 78 // target is not trackback-enabled? Quit 79 if (!$data['receive']) { 80 $this->_printTrackbackError('Trackbacks not enabled for this resource.'); 81 return; 82 } 83 84 // construct unique id for trackback 85 $lid = md5($_REQUEST['url']); 86 $linkback = array ( 87 'lid' => $lid, 88 'title' => strip_tags($_REQUEST['title']), 89 'url' => $_REQUEST['url'], 90 'excerpt' => strip_tags($_REQUEST['excerpt']), 91 'raw_excerpt' => $_REQUEST['excerpt'], 92 'blog_name' => strip_tags($_REQUEST['blog_name']), 93 'received' => time(), 94 'submitter_ip' => $_SERVER['REMOTE_ADDR'], 95 'submitter_useragent' => $_SERVER['HTTP_USER_AGENT'], 96 'submitter_referer' => $_SERVER['HTTP_REFERER'], 97 'type' => 'trackback', 98 'show' => true, 99 ); 100 $log = array( 101 date('Y/m/d H:i', time()) . ': Received trackback from ' . $linkback['url'] . ' (' . $linkback['lid'] . ')', 102 ); 103 104 // Given URL is not an url? Quit 105 if (!preg_match("#^([a-z0-9\-\.+]+?)://.*#i", $linkback['url'])) { 106 $log[] = "\tTrackback URL is invalid"; 107 if ($this->tools->getConf('log_processing')) 108 $this->tools->addProcessLogEntry($log); 109 $this->_printTrackbackError('Given trackback URL is not an URL.'); 110 return; 111 } 112 113 // Trackback already done? Quit 114 if ($data['receivedpings'][$lid]) { 115 $log[] = "\tTrackback already received"; 116 if ($this->tools->getConf('log_processing')) 117 $this->tools->addProcessLogEntry($log); 118 $this->_printTrackbackError('Trackback already received.'); 119 return; 120 } 121 122 // Source does not exist? Quit 123 $page = $this->tools->getPage($linkback['url']); 124 if (!$page['success'] && ($page['status'] < 200 || $page['status'] >= 300)) { 125 $log[] = "\tLinked page cannot be reached, status " .$page['status']; 126 if ($this->tools->getConf('log_processing')) 127 $this->tools->addProcessLogEntry($log); 128 $this->_printTrackbackError('Linked page cannot be reached ('.$page['error'].').'); 129 return; 130 } 131 132 // Prepare event for Antispam plugins 133 $evt_data = array ( 134 'linkback' => $linkback, 135 'page' => $page, 136 'target' => wl($ID, '', true), 137 'show' => true, 138 'log' => $log, 139 ); 140 $event = new Doku_Event('ACTION_LINKBACK_RECEIVED', $evt_data); 141 if ($event->advise_before()) { 142 $linkback['show'] = $evt_data['show']; 143 if ($this->tools->getConf('usefavicon')) { 144 $linkback['favicon'] = $this->tools->getFavicon($linkback['url'], $page['body']); 145 } 146 147 // add trackback 148 $data['receivedpings'][$lid] = $linkback; 149 if ($linkback['show']) 150 $data['number']++; 151 152 io_saveFile($file, serialize($data)); 153 $this->tools->addLogEntry($linkback['received'], $ID, 'cl', '', $linkback['lid']); 154 $this->tools->notify($ID, $linkback); 155 $this->_printTrackbackSuccess(); 156 } else { 157 $this->_printTrackbackError('Trackback denied: Spam.'); 158 } 159 if ($this->tools->getConf('log_processing')) 160 $this->tools->addProcessLogEntry($evt_data['log']); 161 $event->advise_after(); 162 } 163 164 /** 165 * Print trackback success xml. 166 */ 167 function _printTrackbackSuccess() { 168 echo '<?xml version="1.0" encoding="iso-8859-1"?>' . NL . 169 '<response>' . NL . 170 '<error>0</error>' . NL . 171 '</response>'; 172 } 173 174 /** 175 * Print trackback error xml. 176 */ 177 function _printTrackbackError($reason = '') { 178 echo '<?xml version="1.0" encoding="iso-8859-1"?>' . NL . 179 '<response>' . NL . 180 '<error>1</error>' . NL . 181 '<message>' . $reason . '</message>' . NL . 182 '</response>'; 183 } 184 185} 186 187$server = new TrackbackServer(); 188