additional_plugins/serendipity_event_autotitle/serendipity_event_autotitle.php
2021-07-12 15:44:23 +02:00

287 lines
9.9 KiB
PHP
Executable file

<?php #
if (IN_serendipity !== true) {
die ("Don't hack!");
}
@serendipity_plugin_api::load_language(dirname(__FILE__));
class serendipity_event_autotitle extends serendipity_event
{
var $title = PLUGIN_EVENT_AUTOTITLE_NAME;
var $cache = null;
var $cache_group = 'serendipity_autotitle';
var $cache_key = '';
var $page_charset;
function introspect(&$propbag)
{
global $serendipity;
$propbag->add('name', PLUGIN_EVENT_AUTOTITLE_NAME);
$propbag->add('description', PLUGIN_EVENT_AUTOTITLE_DESC);
$propbag->add('stackable', false);
$propbag->add('author', 'Malte Paskuda');
$propbag->add('version', '0.1.13');
$propbag->add('requirements', array(
'php' => '4.1.0'
));
$propbag->add('cachable_events', array('frontend_display' => true));
$propbag->add('event_hooks', array('frontend_display' => true));
$propbag->add('groups', array('MARKUP'));
$this->markup_elements = array(
array(
'name' => 'ENTRY_BODY',
'element' => 'body',
),
array(
'name' => 'EXTENDED_BODY',
'element' => 'extended',
),
array(
'name' => 'COMMENT',
'element' => 'comment',
),
array(
'name' => 'HTML_NUGGET',
'element' => 'html_nugget',
)
);
$conf_array = array('fetchlimit');
foreach($this->markup_elements as $element) {
$conf_array[] = $element['name'];
}
$propbag->add('configuration', $conf_array);
}
function install() {
serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
}
function uninstall(&$propbag) {
serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
}
function generate_content(&$title) {
$title = $this->title;
}
function introspect_config_item($name, &$propbag)
{
switch($name) {
case 'fetchlimit':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_AUTOTITLE_FETCHLIMIT);
$propbag->add('description', PLUGIN_EVENT_AUTOTITLE_FETCHLIMIT_DESC);
$propbag->add('default', '4');
break;
default:
$propbag->add('type', 'boolean');
$propbag->add('name', constant($name));
$propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
$propbag->add('default', 'true');
}
return true;
}
function event_hook($event, &$bag, &$eventData, $addData = null) {
global $serendipity;
$hooks = &$bag->get('event_hooks');
if (isset($hooks[$event])) {
switch($event) {
case 'frontend_display':
foreach ($this->markup_elements as $temp) {
if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']]) &&
!$eventData['properties']['ep_disable_markup_' . $this->instance] &&
!in_array($this->instance, (array)$serendipity['POST']['properties']['disable_markups'])) {
@include_once 'Cache/Lite.php';
if (!class_exists('Cache_Lite')) {
$this->debugMsg('Cache_Lite not available.');
return false;
}
$options = array(
'cacheDir' => $serendipity['serendipityPath'] . 'templates_c/',
'lifeTime' => 604800, //one week
'hashedDirectoryLevel' => 2,
'automaticCleaningFactor' => 200
);
$this->cache = new Cache_Lite($options);
$element = $temp['element'];
$eventData[$element] = $this->autotitle($eventData[$element]);
}
}
return true;
break;
default:
return false;
}
} else {
return false;
}
}
/**
* Get the title-tag of every linked site
* */
function autotitle($text) {
global $serendipity;
//get all links
preg_match_all('|<a (.*?)\">|is', $text, $links);
//links could exist twice in links-array
$links = array_unique($links[1]);
$offset = 0;
while (true) {
preg_match('|<a (.*?)\">|is', $text, $links,
PREG_OFFSET_CAPTURE, $offset);
if (empty($links[0])) {
break;
} else {
$link = $links[1][0];
$offset = $links[1][1] + 1;
}
//ignore this link if title already set
if (strpos($link, 'title=') !== false) {
continue;
}
//if href is alone, last " is missing
if (substr($link, strlen($link), 1) != '"') {
$link = $link .'"';
}
//grab the real url
preg_match('|href="([^\"]*?)"|is', $link, $url);
$url = $url[1];
if (empty($url)) {
continue;
}
//prepare cache:
$this->cache->_setFileName($url, $this->cache_group);
//check cache:
$title = $this->get_cached_title($url);
if ($title === false) {
//$page = a maximum of the first 4kb of the linked site
$page = $this->getPage($url);
//fetch everything between <title>, only one is allowed
preg_match('|<title>([^<]*?)</title>|is', $page, $title);
$page_charset = $this->getCharset($page);
//we need smarty to get our own charset :/
if (!is_object($serendipity['smarty'])) {
serendipity_smarty_init();
}
if( !defined('Smarty::SMARTY_VERSION') ) {
//handle with Smarty version 2
$own_charset = $serendipity['smarty']->get_template_vars('head_charset');
} else {
//handle with Smarty version 3 ...
$own_charset = $serendipity['smarty']->tpl_vars['head_charset']->value;
}
//remove newlines to prevent issues with inserted brs by nl2br or textile
//1. Standardize line endings:
// DOS to Unix and Mac to Unix
$title = str_replace(array("\r\n", "\r"), "\n", $title[1]);
//2. remove nl, also \t because it looks like crap
$title = str_replace(array("\n", "\t"), '', $title);
//escape and convert to prevent encoding-errors
$title = htmlspecialchars(
iconv("$page_charset", "$own_charset//TRANSLIT", $title)
, ENT_COMPAT, $own_charset, false);
$this->cache_title($url, $title);
}
//insert title in links
$titled_link = "$link title=\"$title\"";
//strip text in two parts at the linkposition so str_replace
//wont insert the link which have a title, but have this link
//as a part (e.g. <a href=".*">, <a href=".*" class="x">
$firstPart = substr($text, 0, $offset-5);
$secondPart = substr($text, $offset-5);
$secondPart = str_replace("<a $link", "<a $titled_link", $secondPart);
$text = $firstPart . $secondPart;
}
return $text;
}
function getPage($url) {
$fetchlimit = $this->get_config('fetchlimit', 4);
if(is_int($fetchlimit)) {
$fetchlimit = $fetchlimit * 1024;
} else {
$fetchlimit = 4096;
}
$page = @file_get_contents($url, 0, null, -1, $fetchlimit);
if (empty($page)) {
//try it again with curl if fopen was forbidden
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_RANGE, "0-$fetchlimits");
//the range isn't properly working. So the timeout shall hinder the worst
//that's why curl is not the default
curl_setopt($ch, CURLOPT_TIMEOUT, "20");
$page = curl_exec($ch);
curl_close($ch);
}
}
return $page;
}
function getCharset($page) {
preg_match( '@<meta\s+http-equiv="Content-Type"\s+content="([\w/]+)(;\s+charset=([^\s"]+))?@i', $page, $matches );
if (isset($matches[3])) {
return $matches[3];
} else {
return 'UTF-8';
}
}
function get_cached_title($url) {
return $this->cache->get($url, $this->cache_group);
}
function cache_title($url, $title) {
return $this->cache->save($title, $url, $this->cache_group);
}
function debugMsg($msg) {
global $serendipity;
$this->debug_fp = @fopen ( $serendipity ['serendipityPath'] . 'templates_c/autotitle.log', 'a' );
if (! $this->debug_fp) {
return false;
}
if (empty ( $msg )) {
fwrite ( $this->debug_fp, "failure \n" );
} else {
fwrite ( $this->debug_fp, print_r ( $msg, true ) );
}
fclose ( $this->debug_fp );
}
}
/* vim: set sts=4 ts=4 expandtab : */