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