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

Revision 137, 10.4 kB (checked in by d0nut, 5 years ago)

fixed empty lines query

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