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