root/trackback/requirements/de.easy-coding.wcf.trackback/files/lib/util/TrackbackUtil.class.php @ 815

Revision 815, 10.6 kB (checked in by d0nut, 4 years ago)

update for trackback

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