root/trackback/files/lib/util/TrackbackUtil.class.php @ 148

Revision 148, 10.9 kB (checked in by d0nut, 5 years ago)

updatet trackback to 0.1.2 - trackback now really works with golem and co

Line 
1<?php
2// import seorewriter
3require_once(WCF_DIR.'lib/util/StringUtil.class.php');
4require_once(WCF_DIR.'lib/page/PublicSEORewriter.class.php');
5require_once(WCF_DIR.'lib/util/FileUtil.class.php');
6
7/**
8 * trackback util
9 *
10 * @author      Torben Brodt
11 * @package     de.easy-coding.wbb.trackback
12 * @license     GNU General Public License <http://opensource.org/licenses/gpl-3.0.html>
13 */
14class TrackbackUtil {
15        public static $agent = 'WBB Trackback Mod';
16        protected static $timeout_bytes = 51200;
17
18        /**
19         * fetchs necessery postdata
20         * @param postIDs
21         * @return array
22         */
23        public static function getPost($postIDs) {
24                if(!is_array($postIDs))
25                        $postIDs = array($postIDs);
26       
27                // fetch thread data
28                $sql = "SELECT          thread.*
29                        FROM            wbb".WBB_N."_post post
30                        LEFT JOIN       wbb".WBB_N."_thread thread
31                        ON              (thread.threadID=post.threadID)
32                        WHERE           postID IN (".implode(',', $postIDs).") ";
33
34                $row = WCF::getDB()->getFirstRow($sql);
35                               
36                $rewriter = new PublicSEORewriter();
37               
38                // public seo rewriter: cache
39                $rewriter->publicCacheThreads($row['threadID'], $row);
40               
41                // public seo rewriter use
42                $row['url'] = StringUtil::decodeHTML(FileUtil::addTrailingSlash(PAGE_URL).$rewriter->publicParseThreadURLs($row['threadID'], ''));
43               
44                return $row;
45        }
46       
47        /**
48         *
49         * @param postPermalink
50         * @param postID
51         * @param postTopic
52         * @param postPreview
53         * @param postUsername
54         * @param postTime
55         */
56        public static function getRDF($postPermalink, $postID, $postTopic, $postPreview, $postUsername, $postTime) {
57                $postPermalink = StringUtil::decodeHTML($postPermalink);
58                $page_url = FileUtil::addTrailingSlash(PAGE_URL);
59                return '<link rel="pingback" href="'.$page_url.'index.php?action=Pingback" />
60<!--
61<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
62        xmlns:dc="http://purl.org/dc/elements/1.1/"
63        xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
64<rdf:Description
65        rdf:about="'.$postPermalink.'"
66        dc:identifier="'.$postPermalink.'"
67        trackback:ping="index.php?action=Trackback&postID='.$postID.'"
68        dc:title="'.$postTopic.'"
69        dc:subject="TrackBack"
70        dc:description="'.$postPreview.'"
71        dc:creator="'.$postUsername.'"
72        dc:date="'.date('r', $postTime).'" />
73</rdf:RDF>
74-->';
75        }
76       
77        /**
78         * saves incoming ping/trackback
79         * @param postID
80         * @param postURL
81         * @param title
82         * @param excerpt
83         * @param url
84         * @param blog_name
85         */
86        public static function save($postID, $postURL, $title, $excerpt, $url, $blog_name) {
87                // akismet check spam
88                $isSpam = self::isSpam($title, $excerpt, $url, $blog_name);
89       
90                // insert trackback data
91                $sql = "INSERT INTO     wbb".WBB_N."_trackback
92                        (
93                                        postID,
94                                        postURL,
95                                        title,
96                                        excerpt,
97                                        url,
98                                        blog_name,
99                                        isSpam
100                        ) VALUES (
101                                        {$postID},
102                                        '".escapeString($postURL)."',
103                                        '".escapeString($title)."',
104                                        '".escapeString($excerpt)."',
105                                        '".escapeString($url)."',
106                                        '".escapeString($blog_name)."',
107                                        $isSpam
108                        );";
109
110                WBBCore::getDB()->sendQuery($sql);
111        }
112       
113        /**
114         * does track and ping operations on alien urls
115         * @param postID
116         * @param alienurl
117         * @param page_title
118         * @param author
119         * @param url
120         * @param title
121         * @param excerpt
122         */
123        public static function trackAndPing($postID, $alienurl, $page_title, $author, $url, $title, $excerpt) {
124                $content = ""; // hold as reference
125
126                // auto discovery
127                $pingbacks = self::discover_pingback_uri($alienurl, $content);
128                $trackbacks = count($pingbacks) > 0 ? array() : self::discover_trackback_uri($content, $alienurl);
129               
130                // merge pingbacks with public pingback services
131                $pingbacks = array_merge($pingbacks, explode("\n", StringUtil::unifyNewlines(MESSAGE_PINGBACK)));
132                $pingbacks = array_filter($pingbacks, create_function('$a','return !empty($a);'));
133               
134                // send pingbacks
135                foreach($pingbacks as $pingbackurl) {
136                        if(self::send_pingback($alienurl, $pingbackurl, $url)) {
137                                self::save_log($postID, $alienurl);
138                        }
139                }
140
141                // send trackbacks
142                foreach($trackbacks as $trackbackurl) {
143                        if(self::send_trackback($trackbackurl, $page_title, $author, $url, $title, $excerpt)) {
144                                self::save_log($postID, $alienurl);
145                        }
146                }
147        }
148       
149        /**
150         * akismet check
151         * @param title
152         * @param excerpt
153         * @param url
154         * @param blog_name
155         */     
156        protected static function isSpam($title, $excerpt, $url, $blog_name) {
157                if(AKISMET_API_KEY == '')
158                        return true;
159               
160                // WCF includes
161                require_once(WCF_DIR.'lib/util/AkismetUtil.class.php');
162
163                $akismet = new AkismetUtil(AKISMET_API_KEY,PAGE_URL);
164                $akismet->setCommentType('trackback');
165                $akismet->setPermalink($myurl); //absolute
166               
167                // assign post data
168                $akismet->setCommentAuthor($title);
169                $akismet->setCommentAuthorURL($url);
170                $akismet->setCommentContent($excerpt);
171
172                return $akismet->isCommentSpam();
173        }
174       
175        /**
176         * discover pingback uri
177         * @param url
178         * @param contents (reference)
179         * @return pingbacks
180         */
181        protected static function discover_pingback_uri($url, &$contents) {
182                $pingbacks = array(); // return var
183               
184                $byte_count = 0;
185                $contents = '';
186                $headers = '';
187                $pingback_str_dquote = 'rel="pingback"';
188                $pingback_str_squote = 'rel=\'pingback\'';
189                $x_pingback_str = 'x-pingback: ';
190                $pingback_href_original_pos = 27;
191
192                extract(parse_url($url), EXTR_SKIP);
193
194                if ( !isset($host) ) // Not an URL. This should never happen.
195                return false;
196
197                $path  = ( !isset($path) ) ? '/'          : $path;
198                $path .= ( isset($query) ) ? '?' . $query : '';
199                $port  = ( isset($port)  ) ? $port        : 80;
200
201                // Try to connect to the server at $host
202                $fp = @fsockopen($host, $port, $errno, $errstr, 2);
203                if ( !$fp ) // Couldn't open a connection to $host
204                        return false;
205
206                // Send the GET request
207                $request = "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: ".self::$agent." \r\n\r\n";
208                // ob_end_flush();
209                fputs($fp, $request);
210
211                // Let's check for an X-Pingback header first
212                while ( !feof($fp) ) {
213                        $line = fgets($fp, 512);
214                        if ( trim($line) == '' )
215                                break;
216                        $headers .= trim($line)."\n";
217                        $x_pingback_header_offset = strpos(strtolower($headers), $x_pingback_str);
218                        if ( $x_pingback_header_offset ) {
219                                // We got it!
220                                preg_match('#x-pingback: (.+)#is', $headers, $matches);
221                                $pingbacks[] = trim($matches[1]);
222                                return $pingbacks;
223                        }
224                        if ( strpos(strtolower($headers), 'content-type: ') ) {
225                                preg_match('#content-type: (.+)#is', $headers, $matches);
226                                $content_type = trim($matches[1]);
227                        }
228                }
229
230                if ( preg_match('#(image|audio|video|model)/#is', $content_type) ) // Not an (x)html, sgml, or xml page, no use going further
231                        return false;
232
233                while ( !feof($fp) ) {
234                        $line = fgets($fp, 1024);
235                        $contents .= trim($line);
236                        $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote);
237                        $pingback_link_offset_squote = strpos($contents, $pingback_str_squote);
238                        if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {
239                        $quote = ($pingback_link_offset_dquote) ? '"' : '\'';
240                        $pingback_link_offset = ($quote=='"') ? $pingback_link_offset_dquote : $pingback_link_offset_squote;
241                        $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset);
242                        $pingback_href_start = $pingback_href_pos+6;
243                        $pingback_href_end = @strpos($contents, $quote, $pingback_href_start);
244                        $pingback_server_url_len = $pingback_href_end - $pingback_href_start;
245                        $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len);
246                        // We may find rel="pingback" but an incomplete pingback URL
247                        if ( $pingback_server_url_len > 0 ) // We got it!
248                                $pingbacks[] = $pingback_server_url;
249                                break;
250                        }
251                        $byte_count += strlen($line);
252                        if ( $byte_count > self::$timeout_bytes ) {
253                                // It's no use going further, there probably isn't any pingback
254                                // server to find in this file. (Prevents loading large files.)
255                                break;
256                        }
257                }
258               
259                return $pingbacks;
260        }
261       
262        /**
263         * discover trackback uri
264         * @param contents
265         * @param url
266         * @return trackbacks
267         */
268        protected static function discover_trackback_uri($contents, $url) {
269                $rdf = array(); // <- holds list of RDF segments
270
271                if ($contents) {
272                        preg_match_all('/(<rdf:RDF.*?<\/rdf:RDF>)/sm', $contents, $link_rdf, PREG_SET_ORDER);
273
274                        // Loop through all rdf segments
275                        foreach ($link_rdf as $seg) {
276                                if (preg_match('|dc:identifier="' . preg_quote($url) . '"|ms', $seg[1])) {
277                                        $rdf[] = trim($seg[1]);
278                                } 
279                        } 
280                }
281                // Loop through the RDFs array and extract trackback URIs
282                $trackbacks = array(); // <- holds list of trackback URIs
283                foreach($rdf as $rdf_url) {
284                        if (preg_match('/trackback:ping="([^"]+)"/', $rdf_url, $array)) {
285                                $trackbacks[] = trim($array[1]);
286                        } 
287                } 
288
289                return $trackbacks;
290        }
291
292
293        /**
294         * Send a Pingback
295         * @param alienurl -> the main url from the destination site
296         * @param pingbackurl -> the pingback url from the destination site
297         * @param url -> the own url
298         * @return true if success
299         */
300        protected static function send_pingback($alienurl, $pingbackurl, $url) {
301                require_once(WBB_DIR.'lib/util/IXR.class.php');
302                extract(parse_url($pingbackurl), EXTR_SKIP);
303               
304                if ( !isset($host) ) // Not an URL. This should never happen.
305                        return false;
306
307                $path  = ( !isset($path) ) ? '/'          : $path;
308                $path .= ( isset($query) ) ? '?' . $query : '';
309                $port  = ( isset($port)  ) ? $port        : 80;
310
311                // using a timeout of 3 seconds should be enough to cover slow servers
312                $client = new IXR_Client($host, $path);
313                $client->timeout = 3;
314                $client->useragent = self::$agent;
315
316                // when set to true, this outputs debug messages by itself
317                $client->debug = false;
318
319                // Already registered
320                return $client->query('pingback.ping', $url, $alienurl) || (isset($client->error->code) && 48 == $client->error->code);
321        }
322
323        /**
324         * Send a Trackback
325         * @param trackbackurl
326         * @param page_title
327         * @param author
328         * @param url
329         * @param title
330         * @param excerpt
331         */
332        protected static function send_trackback($trackbackurl, $page_title, $author, $url, $title, $excerpt) {
333                $blog_name = urlencode($page_title);
334                $author = urlencode($author);
335                $title = urlencode($title);
336                $excerpt = urlencode($excerpt);
337
338                $query_string = "title=$title&url=$url&blog_name=$blog_name&excerpt=$excerpt";
339
340                $parse = parse_url($trackbackurl);
341                $http_request = 'POST ' . $parse['path'] . (isset($parse['query']) ? '?'.$parse['query'] : '') . " HTTP/1.0\r\n";
342                $http_request .= 'Host: '.$parse['host']."\r\n";
343                $http_request .= 'Content-Type: application/x-www-form-urlencoded; charset='.CHARSET."\r\n";
344                $http_request .= 'Content-Length: '.strlen($query_string)."\r\n";
345                $http_request .= "User-Agent: {self::agent}";
346                $http_request .= "\r\n\r\n";
347                $http_request .= $query_string;
348
349                $fs = @fsockopen($parse['host'], isset($parse['port'])?$parse['port']:80, $errno, $errstr, 4);
350                @fputs($fs, $http_request);
351                @fclose($fs);
352               
353                return $fs;
354        }
355       
356        /**
357         * saves log
358         * @param postID
359         * @param alienURL
360         */
361        protected static function save_log($postID, $alienurl) {
362                $sql = "INSERT INTO     wbb".WBB_N."_trackbackLog
363                        (
364                                        postID,
365                                        alienURL,
366                                        timestamp
367                        ) VALUES (
368                                        {$postID},
369                                        '".escapeString($alienurl)."',
370                                        ".time()."
371                        );";
372
373                @WBBCore::getDB()->sendQuery($sql);
374        }
375} 
376?>
377
Note: See TracBrowser for help on using the browser.