value
* Known key are:
* - group = group name
* - artid/first = article id the the group
* - subscribe = to show the subscription page
* - action = action to do (new, cancel, view)
* - part = to show the given MIME part of the article
* - pj = to get the given attachment
* - xface = to make a link to an xface
*
* Can be overloaded by defining a hook_makeLink function
*/
function makeLink($params)
{
if (function_exists('hook_makeLink')
&& $res = hook_makeLink($params)) {
return $res;
}
$proto = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
$host = $_SERVER['HTTP_HOST'];
$file = $_SERVER['PHP_SELF'];
if (isset($params['xface'])) {
$file = dirname($file) . '/xface.php';
$get = 'face=' . $params['xface'];
} else if (count($params) != 0) {
$get = '?';
foreach ($params as $key=>$value) {
if (strlen($get) != 1) {
$get .= '&';
}
$get .= $key . '=' . $value;
}
} else {
$get = '';
}
return $proto . $host . $file . $get;
}
/** Format a link to be use in a link
* @ref makeLink
*/
function makeHREF($params, $text = null)
{
$link = makeLink($params);
if (is_null($text)) {
$text = $link;
}
$target = null;
if (isset($params['action']) && $params['action'] == 'view') {
$target = ' target="_blank"';
}
return '' . $text . '';
}
/** Format tree images links
* @param img STRING Image name (without extension)
* @param alt STRING alternative string
* @param width INT to force width of the image (null if not defined)
*
* This function can be overloaded by defining hook_makeImg()
*/
function makeImg($img, $alt, $height = null, $width = null)
{
if (function_exists('hook_makeImg')
&& $res = hook_makeImg($img, $alt, $height, $width)) {
return $res;
}
if (!is_null($width)) {
$width = ' width="' . $width . '"';
}
if (!is_null($height)) {
$height = ' height="' . $height . '"';
}
$proto = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
$host = $_SERVER['HTTP_HOST'];
$file = dirname($_SERVER['PHP_SELF']) . '/img/' . $img . '.gif';
$url = $proto . $host . $file;
return '';
}
/********************************************************************************
* HTML STUFF
* Taken from php.net
*/
/**
* @return string
* @param string
* @desc Strip forbidden tags and delegate tag-source check to removeEvilAttributes()
*/
function removeEvilTags($source)
{
$allowedTags = '
)\n?-- ?\n?(
'; $source = preg_replace('||i', '
', $source); $source = strip_tags($source, $allowedTags); return preg_replace('/<(.*?)>/ie', "'<'.removeEvilAttributes('\\1').'>'", $source); } /** * @return string * @param string * @desc Strip forbidden attributes from a tag */ function removeEvilAttributes($tagSource) { $stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|'. 'onmousemove|onmouseout|onkeypress|onkeydown|onkeyup'; return stripslashes(preg_replace("/$stripAttrib/i", '', $tagSource)); } /** Convert html to plain text */ function htmlToPlainText($res) { $res = trim(html_entity_decode(strip_tags($res, ''; } /******************************************************************************** * FORMATTING STUFF : BODY */ function autoformat($text) { global $banana; $length = $banana->wrap; $cmd = "echo ".escapeshellarg($text)." | perl -MText::Autoformat -e 'autoformat {left=>1, right=>$length, all=>1 };'"; exec($cmd, $result, $ret); if ($ret != 0) { $result = split("\n", $text); } return $result; } function wrap($text, $_prefix="", $_force=false) { $parts = preg_split("/\n-- ?\n/", $text); if (count($parts) >1) { $sign = "\n-- \n" . array_pop($parts); $text = join("\n-- \n", $parts); } else { $sign = ''; } global $banana; $url = $banana->url_regexp; $length = $banana->wrap; $max = $length + ($length/10); $splits = split("\n", $text); $result = array(); $next = array(); $format = false; foreach ($splits as $line) { if ($_force || strlen($line) > $max) { if (preg_match("!^(.*)($url)(.*)!i", $line, $matches) && strlen($matches[2]) > $length && strlen($matches) < 900) { if (strlen($matches[1]) != 0) { array_push($next, rtrim($matches[1])); if (strlen($matches[1]) > $max) { $format = true; } } if ($format) { $result = array_merge($result, autoformat(join("\n", $next))); } else { $result = array_merge($result, $next); } $format = false; $next = array(); array_push($result, $matches[2]); if (strlen($matches[6]) != 0) { array_push($next, ltrim($matches[6])); if (strlen($matches[6]) > $max) { $format = true; } } } else { $format = true; array_push($next, $line); } } else { array_push($next, $line); } } if ($format) { $result = array_merge($result, autoformat(join("\n", $next))); } else { $result = array_merge($result, $next); } return $_prefix.join("\n$_prefix", $result).($_prefix ? '' : $sign); } function cutlink($link) { global $banana; if (strlen($link) > $banana->wrap) { $link = substr($link, 0, $banana->wrap - 3)."..."; } return $link; } function cleanurl($url) { $url = str_replace('@', '%40', $url); return ''.cutlink($url).''; } function formatbody($_text, $format='plain', $flowed=false) { if ($format == 'html') { $res = ''))); $res = preg_replace("@?(br|p|div)[^>]*>@i", "\n", $res); if (!is_utf8($res)) { $res = utf8_encode($res); } return $res; } /******************************************************************************** * RICHTEXT STUFF */ /** Convert richtext to html */ function richtextToHtml($source) { $tags = Array('bold' => 'b', 'italic' => 'i', 'smaller' => 'small', 'bigger' => 'big', 'underline' => 'u', 'subscript' => 'sub', 'superscript' => 'sup', 'excerpt' => 'blockquote', 'paragraph' => 'p', 'nl' => 'br' ); // clean unsupported tags $protectedTags = '
<'.join('><', array_keys($tags)).'>'; $source = strip_tags($source, $protectedTags); // convert richtext tags to html foreach (array_keys($tags) as $tag) { $source = preg_replace('@(?)'.$tag.'([^>]*>)@i', '\1'.$tags[$tag].'\2', $source); } // some special cases $source = preg_replace('@ @i', ' @i', '', $source); $source = preg_replace('@
--
', $source); $source = preg_replace('@@i', '<', $source); $source = preg_replace('@ ]*>((?:[^<]|<(?!/comment>))*) @i', '', $source); return removeEvilAttributes($source); } /******************************************************************************** * HEADER STUFF */ function _headerdecode($charset, $c, $str) { $s = ($c == 'Q' || $c == 'q') ? quoted_printable_decode($str) : base64_decode($str); $s = iconv($charset, 'iso-8859-15', $s); return str_replace('_', ' ', $s); } function headerDecode($value) { $val = preg_replace('/(=\?[^?]*\?[BQbq]\?[^?]*\?=) (=\?[^?]*\?[BQbq]\?[^?]*\?=)/', '\1\2', $value); return preg_replace('/=\?([^?]*)\?([BQbq])\?([^?]*)\?=/e', '_headerdecode("\1", "\2", "\3")', $val); } function headerEncode($value, $trim = 0) { if ($trim) { if (strlen($value) > $trim) { $value = substr($value, 0, $trim) . "[...]"; } } return "=?UTF-8?B?".base64_encode($value)."?="; } function header_translate($hdr) { switch ($hdr) { case 'from': return _b_('De'); case 'subject': return _b_('Sujet'); case 'newsgroups': return _b_('Forums'); case 'followup-to': return _b_('Suivi-à'); case 'date': return _b_('Date'); case 'organization': return _b_('Organisation'); case 'references': return _b_('Références'); case 'x-face': return _b_('Image'); default: if (function_exists('hook_headerTranslate') && $res = hook_headerTranslate($hdr)) { return $res; } return $hdr; } } function formatDisplayHeader($_header,$_text) { global $banana; switch ($_header) { case "date": return formatDate($_text); case "followup-to": case "newsgroups": $res = ""; $groups = preg_split("/[\t ]*,[\t ]*/",$_text); foreach ($groups as $g) { $res .= makeHREF(Array('group' => $g), $g) . ', '; } return substr($res,0, -2); case "from": return formatFrom($_text); case "references": $rsl = ""; $ndx = 1; $text = str_replace("><","> <",$_text); $text = preg_split("/[ \t]/",strtr($text,$banana->spool->ids)); $parents = preg_grep("/^\d+$/",$text); $p = array_pop($parents); $par_ok = Array(); while ($p) { $par_ok[]=$p; $p = $banana->spool->overview[$p]->parent; } foreach (array_reverse($par_ok) as $p) { $rsl .= makeHREF(Array('group' => $banana->spool->group), $ndx) . ' '; $ndx++; } return $rsl; case "x-face": return ''; default: if (function_exists('hook_formatDisplayHeader') && $res = hook_formatDisplayHeader($_header, $_text)) { return $res; } return htmlentities($_text); } } /******************************************************************************** * FORMATTING STUFF */ function formatDate($_text) { return strftime("%A %d %B %Y, %H:%M (fuseau serveur)", strtotime($_text)); } function fancyDate($stamp) { $today = intval(time() / (24*3600)); $dday = intval($stamp / (24*3600)); if ($today == $dday) { $format = "%H:%M"; } elseif ($today == 1 + $dday) { $format = _b_('hier')." %H:%M"; } elseif ($today < 7 + $dday) { $format = '%a %H:%M'; } else { $format = '%a %e %b'; } return strftime($format, $stamp); } function formatFrom($text) { # From: mark@cbosgd.ATT.COM # From: mark@cbosgd.ATT.COM (Mark Horton) # From: Mark Horton $mailto = '".htmlentities($regs[1]."@".$regs[2]).""; } if (preg_match("/^([^ ]+)@([^ ]+) \((.*)\)$/",$text,$regs)) { $result="$mailto{$regs[1]}@{$regs[2]}\">".htmlentities($regs[3]).""; } if (preg_match("/^\"?([^<>\"]+)\"? +<(.+)@(.+)>$/",$text,$regs)) { $result="$mailto{$regs[2]}@{$regs[3]}\">".htmlentities($regs[1]).""; } return preg_replace("/\\\(\(|\))/","\\1",$result); } function displayshortcuts($first = -1) { global $banana; extract($banana->state); $res = '
'; $res .= '[' . makeHREF(Array(), _b_('Liste des forums')) . '] '; if (is_null($group)) { return $res.'[' . makeHREF(Array('subscribe' => 1), _b_('Abonnements')) . ']'; } $res .= '[' . makeHREF(Array('group' => $group), $group) . '] '; if (is_null($artid)) { $res .= '[' . makeHREF(Array('group' => $group, 'action' => 'new'), _b_('Nouveau message')) . '] '; if (sizeof($banana->spool->overview)>$banana->tmax) { $res .= '
'; $n = intval(log(count($banana->spool->overview), 10))+1; for ($ndx=1; $ndx <= sizeof($banana->spool->overview); $ndx += $banana->tmax) { if ($first==$ndx) { $fmt = "[%0{$n}u-%0{$n}u] "; } else { $fmt = '[' . makeHREF(Array('group' => $group, 'first' => $ndx), '%0' . $n . 'u-%0' . $n . 'u') . '] '; } $res .= sprintf($fmt, $ndx, min($ndx+$banana->tmax-1,sizeof($banana->spool->overview))); } } } else { $res .= '[' . makeHREF(Array('group' => $group, 'artid' => $artid, 'action' => 'new'), _b_('Répondre')) . '] '; if ($banana->post && $banana->post->checkcancel()) { $res .= '[' . makeHREF(Array('group' => $group, 'artid' => $artid, 'action' => 'cancel'), _b_('Annuler ce message')) . '] '; } } return $res.'
'.html_entity_decode(to_entities(removeEvilTags($_text))).'
'; } else if ($format == 'richtext') { $res = '
'.html_entity_decode(to_entities(richtextToHtml($_text))).'
'; } else { $res = "\n\n" . to_entities(wrap($_text, "", $flowed))."\n\n"; $formatting = Array('\*' => 'strong', '_' => 'u', '/' => 'em'); $word = '-a-z0-9\'âäàãéêëêïîìöôòõüûùÿ'; foreach ($formatting as $limit=>$mark) { $res = preg_replace('@([^' . $word . '])' . $limit . '([' . $word . ']+)' . $limit . '([^' . $word . '])@i' ,'\1<' . $mark . '>\2' . $mark . '>\3' , $res); } } if ($format != 'html') { global $banana; $url = $banana->url_regexp; $res = preg_replace("/(<|>|")/", " \\1 ", $res); $res = preg_replace("!$url!ie", "'\\1'.cleanurl('\\2').'\\3'", $res); $res = preg_replace('/(["\[])?(?:mailto:)?([a-z0-9.\-+_]+@[a-z0-9.\-+_]+)(["\]])?/i', '\1\2\3', $res); $res = preg_replace("/ (<|>|") /", "\\1", $res); if ($format == 'richtext') { $format = 'html'; } } if ($format == 'html') { $res = preg_replace("@(]*>|
]*>)@", "\\1
-- \\2", $res); $res = preg_replace("@
]*>\n?-- ?\n?(]*>)@", "
--
\\2", $res); $res = preg_replace("@(]*>)\n?-- ?\n@", "
--
\\1", $res); $parts = preg_split("@(:?]*>\n?-- ?\n?
|
]*>\n?-- ?\n?
]*>)@", $res); } else { while (preg_match("@(^||\n)>@i", $res)) { $res = preg_replace("@(^||\n)((>[^\n]*\n)+)@ie", "'\\1'" .".stripslashes(preg_replace('@(^||\n)>[ \\t\\r]*@i', '\\1', '\\2'))" .".''", $res); } $res = preg_replace("@-- ?\n@", "\n-- \n", $res); $parts = preg_split("/\n-- ?\n/", $res); } if (count($parts) > 1) { $sign = array_pop($parts); if ($format == 'html') { $res = join('
--
', $parts); $sign = '
'.$sign.'
'; } else { $res = join('\n-- \n', $parts); $sign = ''.$sign; } return $res.$sign; } else { return $res; } } // vim:set et sw=4 sts=4 ts=4 ?>