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