* @link http://wiki.foosel.net/snippets/dokuwiki/linkback */ require_once (DOKU_PLUGIN . 'linkback/http.php'); class tools_plugin_linkback extends DokuWiki_Plugin { /** * Retrieves a favicon for the given page. */ function getFavicon($url, $page) { $urlparts = parse_url($url); $regex = '!!'; if (preg_match($regex, $page, $match)) { $icon = $match[2]; if (!preg_match("#^(http://)?[^/]+#i", $icon)) { $icon = $urlparts['scheme'] . '://' . $urlparts['host'] . (($icon[0]) == '/' ? '' : '/') . $icon; } return $icon; } $icon = $urlparts['scheme'] . '://' . $urlparts['host'] . '/favicon.ico'; $http_client = new LinkbackHTTPClient(); $http_client->sendRequest($icon, array (), 'HEAD'); if ($http_client->status == 200) return $icon; else return $this->getConf('favicon_default'); } /** * Retrieves $conf['range']kB of $url and returns headers and retrieved body. */ function getPage($url) { $range = $this->getConf('range') * 1024; $http_client = new LinkbackHTTPClient(); $http_client->headers['Range'] = 'bytes=0-' . $range; $http_client->max_bodysize = $range; $http_client->max_bodysize_limit = true; $retval = $http_client->get($url, true); return array ( 'success' => $retval, 'headers' => $http_client->resp_headers, 'body' => $http_client->resp_body, 'error' => $http_client->error, 'status' => $http_client->status, ); } /** * Sends a notify mail on new linkback * * @param string $ID id of the wiki page for which the * linkback was received * @param array $linkback data array of the new linkback * * @author Andreas Gohr * @author Esther Brunner * @author Gina Haeussge */ function notify($ID, $linkback) { global $conf; if (!$conf['notify']) return; $to = $conf['notify']; $text = io_readFile($this->localFN('subscribermail')); $search = array ( '@PAGE@', '@TITLE@', '@DATE@', '@URL@', '@TEXT@', '@UNSUBSCRIBE@', '@DOKUWIKIURL@', '@PAGEURL@', ); $replace = array ( $ID, $conf['title'], strftime($conf['dformat'], $linkback['received']), $linkback['url'], $linkback['excerpt'], wl($ID, 'do=unsubscribe', true, '&'), DOKU_URL, wl($ID, '', true), ); $text = str_replace($search, $replace, $text); $subject = '[' . $conf['title'] . '] ' . $this->getLang('mail_newlinkback'); $mail = new Mailer(); $mail->to($to); $mail->subject($subject); $mail->setBody($text); $mail->send(); } /** * Adds an entry to the linkbacks changelog * * @author Esther Brunner * @author Ben Coburn * @author Gina Haeussge */ function addLogEntry($date, $id, $type = 'cl', $summary = '', $extra = '') { global $conf; $changelog = $conf['metadir'] . '/_linkbacks.changes'; if (!$date) { $date = time(); //use current time if none supplied } $remote = $_SERVER['REMOTE_ADDR']; $user = $_SERVER['REMOTE_USER']; $strip = array ( "\t", "\n" ); $logline = array ( 'date' => $date, 'ip' => $remote, 'type' => str_replace($strip, '', $type ), 'id' => $id, 'user' => $user, 'sum' => str_replace($strip, '', $summary), 'extra' => str_replace($strip, '', $extra)); // add changelog line $logline = implode("\t", $logline) . "\n"; io_saveFile($changelog, $logline, true); //global changelog cache $this->_trimRecentCommentsLog($changelog); } /** * Trims the recent comments cache to the last $conf['changes_days'] recent * changes or $conf['recent'] items, which ever is larger. * The trimming is only done once a day. * * @author Ben Coburn */ function _trimRecentCommentsLog($changelog) { global $conf; if (@ file_exists($changelog) && (filectime($changelog) + 86400) < time() && !@ file_exists($changelog . '_tmp')) { io_lock($changelog); $lines = file($changelog); if (count($lines) < $conf['recent']) { // nothing to trim io_unlock($changelog); return true; } io_saveFile($changelog . '_tmp', ''); // presave tmp as 2nd lock $trim_time = time() - $conf['recent_days'] * 86400; $out_lines = array (); $linecount = count($lines); for ($i = 0; $i < $linecount; $i++) { $log = parseChangelogLine($lines[$i]); if ($log === false) continue; // discard junk if ($log['date'] < $trim_time) { $old_lines[$log['date'] . ".$i"] = $lines[$i]; // keep old lines for now (append .$i to prevent key collisions) } else { $out_lines[$log['date'] . ".$i"] = $lines[$i]; // definitely keep these lines } } // sort the final result, it shouldn't be necessary, // however the extra robustness in making the changelog cache self-correcting is worth it ksort($out_lines); $extra = $conf['recent'] - count($out_lines); // do we need extra lines do bring us up to minimum if ($extra > 0) { ksort($old_lines); $out_lines = array_merge(array_slice($old_lines, - $extra), $out_lines); } // save trimmed changelog io_saveFile($changelog . '_tmp', implode('', $out_lines)); @ unlink($changelog); if (!rename($changelog . '_tmp', $changelog)) { // rename failed so try another way... io_unlock($changelog); io_saveFile($changelog, implode('', $out_lines)); @ unlink($changelog . '_tmp'); } else { io_unlock($changelog); } return true; } } function addProcessLogEntry($data) { global $conf; io_saveFile($conf['cachedir'].'/linkback.log',join("\n",$data)."\n\n",true); } }