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

Revision 78, 9.3 kB (checked in by d0nut, 6 years ago)

license updates to version 3 of GPL and LGPL

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