source: trunk/xmlrpc.php @ 1798

Revision 1798, 10.4 KB checked in by driehle, 3 years ago (diff)

Moved Jlog 1.5 branch into trunk/ as we will focus on Jlog 1.5 development in the future

  • Property svn:keywords set to Date Rev Author HeadURL
Line 
1<?php
2
3/**
4 * Jlog
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 *
20 * $HeadURL$
21 * $Rev$
22 * $Author$
23 * $Date$
24 **/
25
26require_once('./config.inc.php');
27require_once(JLOG_LIBPATH . '/bootstrap.php');
28
29
30
31 $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
32 if(!defined('JLOG_BASEPATH')) require_once('.'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'prepend.inc.php');
33 require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'ixr-library.inc.php');
34 require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'jlogHTTP_Request.php');
35
36
37    if(defined("JLOG_ADMIN") === false) {
38        function ping($args) {
39
40            $pingback = new Jlog_GetPingback(JLOG_DB_CONTENT, JLOG_DB_COMMENTS, JLOG_PATH, new_sid());
41            $pingback->get_ping($args);
42            if($pingback->validate()) {
43                $pingback->write_to_db();
44                return "Thanks for your ping.";
45            }
46        }
47        $server = new IXR_Server(array('pingback.ping' => 'ping'));
48    }
49
50class Jlog_GetPingback {
51
52    var $errors = array();        // array
53    var $method = "";             // string
54    var $sourceURI = "";          // string
55    var $targetURI = array();     // array incl: orginal, parsed [array from parse_url()], y, m, url
56    var $title = "";              // string
57    var $sid = "";                // string
58
59    function Jlog_GetPingback($db_content, $db_comments, $path, $sid = NULL) {
60        $this->db_content = $db_content;
61        $this->db_comments = $db_comments;
62        $this->path = $path;
63        if($sid != NULL) $this->sid = $sid;
64    }
65
66    function get_ping($uris) {
67
68        $ymurls = array();
69        $tmp_host_got = "";
70        $tmp_host_path_parsed = array();
71        $tmp_host_path = "";
72
73        $this->sourceURI = trim($uris[0]);
74        $this->targetURI['orginal'] = trim(str_replace(array('&quot;','&lt;', '&gt;', '&amp;'), array('"', '<', '>', '&'), $uris[1]));
75        $this->targetURI['parsed'] = parse_url($this->targetURI['orginal']);
76        $tmp_host_got = str_replace('www.', '', $this->targetURI['parsed']['host']).$this->targetURI['parsed']['path'];
77        $tmp_host_path_parsed = parse_url($this->path);
78        $tmp_host_path = str_replace('www.', '', $tmp_host_path_parsed['host']).'/log.php';
79
80        if(!empty($this->targetURI['parsed']['query']) AND ($tmp_host_got == $tmp_host_path)) {
81
82            $ymurls = explode('&', $this->targetURI['parsed']['query']);
83            $this->_counter = count($ymurls);
84
85            foreach($ymurls AS $ymurl) {
86                if(substr($ymurl, 0, 2) == 'y=') $this->targetURI['y'] = substr($ymurl, 2);
87                elseif(substr($ymurl, 0, 2) == 'm=') $this->targetURI['m'] = substr($ymurl, 2);
88                elseif(substr($ymurl, 0, 4) == 'url=') $this->targetURI['url'] = substr($ymurl, 4);
89            }
90        }
91        else {
92            ### Plugin Hook
93            global $plugins;
94            $tmp_URI = $plugins->callHook('xmlrpcPermalink', $this->targetURI['orginal']);
95           
96            $regex = "#^".$this->path."/([0-9]{4})/?([0-9]{2})/?([a-z0-9_\-]+)$#";
97            preg_match($regex, $tmp_URI, $matches);
98            $this->targetURI['y'] = $matches[1];
99            $this->targetURI['m'] = $matches[2];
100            $this->targetURI['url'] = $matches[3];
101        }
102
103    }
104
105    function validate() {
106
107
108        if(!strpos($this->targetURI['orginal'], str_replace(array('http://', 'https://'), '', str_replace('www.', '', $this->path))))
109            $this->send_error(0, 'Target URI ('.$this->targetURI['orginal'].') is not this page: '.$this->path);
110
111
112        // is there such a post?
113        $sql = "SELECT  id, allowpingback FROM ".$this->db_content." WHERE
114                        YEAR(date)  = '".escape_for_mysql($this->targetURI['y'])."' AND
115                        MONTH(date) = '".escape_for_mysql($this->targetURI['m'])."' AND
116                        url         = '".escape_for_mysql($this->targetURI['url'])."' AND
117                        section     = 'weblog'
118                  LIMIT 1";
119        $blog = new Query($sql);
120       if($blog->error()) $this->send_error(0, 'Could not read my database.');
121        $blogrow = $blog->fetch();
122
123        if($blog->numRows() != 1) $this->send_error(32, 'The specified target URI does not exist.'.$this->targetURI['orginal']);
124        if($blogrow['allowpingback'] === 0) $this->send_error(33, 'The specified target URI cannot be used as a target. It it is not a pingback-enabled resource.');
125        else $this->reference = $blogrow['id'];
126
127        $s =& new HTTP_Request($this->sourceURI);
128        if(PEAR::isError($s->sendRequest())) $this->send_error(16, 'The source URI does not exist.');
129        else {
130            $source = $s->getResponseBody();
131            $source = strip_tags(str_replace('<!DOCTYPE','<DOCTYPE', $source), '<title><a>');
132
133            if (!$this->isLinkInHTML($this->targetURI['orginal'], $source))
134                $this->send_error(17, 'The source URI does not contain a link to the target URI, and so cannot be used as a source.');
135
136            preg_match('|<title>([^<]*?)</title>|is', $source, $title);
137
138            if(! $utf8 = preg_match ('/charset\s*=\s*utf-8/i', $s->getResponseHeader("Content-Type")))
139                $utf8 = 'application/xhtml+xml' == strtolower(trim($s->getResponseHeader("Content-Type")));
140
141            // since text in database is utf8 encoded, we need to *en*code the title to utf8 if it isn't already, not *de*code it
142            $this->title = empty($title[1]) ? $this->sourceURI : html_entity_decode($utf8 ? $title[1] : utf8_encode($title[1]));
143        }
144
145        $sql = "SELECT COUNT(*) AS ping FROM ".$this->db_comments." WHERE
146                    reference = '".escape_for_mysql($blogrow['id'])."' AND
147                    homepage = '".escape_for_mysql($this->sourceURI)."' AND
148                    name = '".escape_for_mysql($this->title)."' AND
149                    type = 'pingback'
150                  LIMIT 1";
151        $p = new Query($sql);
152        if($p->error()) $this->send_error(0, 'Could not read my database.');
153        $f = $p->fetch();
154
155        if($f['ping'] > 0) $this->send_error(48, 'The pingback has already been registered.');
156
157        if(count($this->errors) > 0) return false;
158        else return true;
159    }
160
161    function write_to_db() {
162        $sql = "INSERT INTO ".$this->db_comments." (
163            sid,
164            name,
165            homepage,
166            reference,
167            date,
168            type
169          )
170           VALUES (
171            '".escape_for_mysql($this->sid)."',
172            '".escape_for_mysql($this->title)."',
173            '".escape_for_mysql($this->sourceURI)."',
174            '".escape_for_mysql($this->reference)."',
175            NOW(),
176            'pingback'
177           )";
178        $ping = new Query($sql);
179
180       if($ping->error()) $this->send_error(0, 'Could not write to database.');
181
182    }
183   
184    function send_error($nr, $string) {
185        $this->errors[] = $nr." ".$string;
186        $error = new IXR_Error($nr, $string);
187        $this->send_xml($error->getXml());
188    }
189   
190    function get_errors() {
191        return $this->errors;
192    }
193   
194    function send_xml($xml) {
195        header('Connection: close');
196        header('Content-Length: '.strlen($xml));
197        header('Content-Type: text/xml');
198        header('Date: '.date('r'));
199        echo $xml;
200        exit;
201    }
202
203    function isLinkInHTML($search, $html) {
204        preg_match_all('#<a[^>]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)</a>#Ui', $html, $matches);
205        $links =  array_unique(array_merge($matches[2], $matches[3]));
206
207        foreach($links as $link) {
208            if($search === str_replace('&amp;', '&', $link)) return true;
209        }
210        return false;
211    }
212
213}
214
215class Jlog_SendPingback {
216
217    var $pageslinkedto = array();
218    var $useragent = "";
219
220    function Jlog_SendPingback($html, $pagelinkedfrom, $useragent) {
221        // neet to prevent &amp; in url
222        $this->pagelinkedfrom = htmlspecialchars_decode($pagelinkedfrom);
223        $this->useragent = $useragent;
224
225        preg_match_all('#<a[^>]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)</a>#Ui', $html, $matches);
226        $pageslinkedto = array();
227        $pageslinkedto = array_unique(array_merge($matches[2], $matches[3]));
228        $count = count($pageslinkedto);
229        for($i = 0; $count > $i; $i++) {
230            if(substr($pageslinkedto[$i], 0, 4) !== "http") unset($pageslinkedto[$i]);
231            // htmlspecialchars_decode is easier than str_replace
232            else $pageslinkedto[$i] = htmlspecialchars_decode($pageslinkedto[$i]);
233        }
234        $this->pageslinkedto = $pageslinkedto;
235    }
236
237    function doPingbacks() {
238        foreach($this->pageslinkedto as $pagelinkedto) {
239            $feedback[] = $this->send($pagelinkedto);
240        }
241        return $feedback;
242    }
243
244    function send($pagelinkedto) {
245
246        $s =& new HTTP_Request($pagelinkedto);
247        if(PEAR::isError($s->sendRequest())) return $pagelinkedto." &mdash; Error: The source URI does not exist.";
248        else {
249            $xmlrpcserver = $s->getResponseHeader("X-Pingback");
250            if(!empty($xmlrpcserver));
251            else {
252                if(preg_match('<link rel="pingback" href="([^"]+)" ?/?>', $s->getResponseBody(), $matches)) {
253                    $xmlrpcserver = $matches[1];
254                }
255                else return $pagelinkedto." &mdash; This is not a pingback-enabled resource.";
256            }
257
258            $client = new IXR_Client($xmlrpcserver);
259            $client->timeout = 3;
260            $client->useragent = $this->useragent;
261
262            // when set to true, this outputs debug messages by itself
263            $client->debug = false;
264
265            if (! $client->query('pingback.ping', $this->pagelinkedfrom, $pagelinkedto ) )
266                return $pagelinkedto." &mdash; Error: ".$client->getErrorMessage();
267
268            else return $pagelinkedto." &mdash; ".$client->getResponse();
269        }
270    }
271
272}
273
274// eof
Note: See TracBrowser for help on using the repository browser.