1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 03:20:59 +01:00

Use PEAR Text_Figlet to render figlet fonts

Summary:
Ref T7785. Makes Figlet available without installing the `figlet` package.

The PEAR Text_Figlet code is really sketchy and includes this API, which is quite marvelous:

```
    function loadFont($filename, $loadgerman = true)
```

At some point, this should probably be rewritten into a modern style, but it's not trivial since the figlet file format and rendering engine are somewhat complicated. I made some adjustments:

  - Broke the dependency on the PEAR core.
  - Prevented it from doing any wrong HTML escaping.
  - Looked through it for any glaring security or correctness problems.

This code isn't very pretty or modern, but as far as I can tell it's safe and does render Figlet fonts in a reasonable way.

Test Plan: {F803268}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9408, T7785

Differential Revision: https://secure.phabricator.com/D14102
This commit is contained in:
epriestley 2015-09-13 12:31:07 -07:00
parent 935ced1edd
commit 6bd8ee861c
2 changed files with 56 additions and 48 deletions

View file

@ -15,7 +15,6 @@
* @version CVS: $Id$
* @link http://pear.php.net/package/Text_Figlet
*/
require_once 'PEAR.php';
/**
* ASCII art text creation
@ -113,22 +112,9 @@ class Text_Figlet
{
$this->font = array();
if (!file_exists($filename)) {
//if it does not exist, try the Text_Figlet data directory
include_once 'PEAR/Config.php';
$config = PEAR_Config::singleton();
$fontdir = $config->get('data_dir') . '/Text_Figlet/fonts/';
//only for filenames without path separators
if (strpos($filename, '/') === false
&& file_exists($fontdir . $filename)
) {
$filename = $fontdir . $filename;
} else {
return PEAR::raiseError('Figlet font file "'
. $filename
. '" cannot be found', 1);
}
return self::raiseError('Figlet font file "'
. $filename
. '" cannot be found', 1);
}
$this->font_comment = '';
@ -139,7 +125,7 @@ class Text_Figlet
$compressed = true;
if (!function_exists('gzcompress')) {
return PEAR::raiseError('Cannot load gzip compressed fonts since'
return self::raiseError('Cannot load gzip compressed fonts since'
. ' gzcompress() is not available.',
3);
}
@ -148,14 +134,14 @@ class Text_Figlet
}
if (!($fp = fopen($filename, 'rb'))) {
return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
return self::raiseError('Cannot open figlet font file ' . $filename, 2);
}
if (!$compressed) {
/* ZIPed font */
if (fread($fp, 2) == 'PK') {
if (!function_exists('zip_open')) {
return PEAR::raiseError('Cannot load ZIP compressed fonts since'
return self::raiseError('Cannot load ZIP compressed fonts since'
. ' ZIP PHP extension is not available.',
5);
}
@ -163,14 +149,14 @@ class Text_Figlet
fclose($fp);
if (!($fp = zip_open($filename))) {
return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
return self::raiseError('Cannot open figlet font file ' . $filename, 2);
}
$name = zip_entry_name(zip_read($fp));
zip_close($fp);
if (!($fp = fopen('zip://' . realpath($filename) . '#' . $name, 'rb'))) {
return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
return self::raiseError('Cannot open figlet font file ' . $filename, 2);
}
$compressed = true;
@ -193,7 +179,7 @@ class Text_Figlet
$header = explode(' ', fgets($fp, 2048));
if (substr($header[0], 0, 5) <> 'flf2a') {
return PEAR::raiseError('Unknown FIGlet font format.', 4);
return self::raiseError('Unknown FIGlet font format.', 4);
}
@list ($this->hardblank, $this->height,,,
@ -381,9 +367,9 @@ class Text_Figlet
$str = strtr(implode("\n", $out), $trans);
if ($inhtml) {
return '<nobr>'.
nl2br(str_replace(' ', '&nbsp;', htmlspecialchars($str))).
'</nobr>';
self::raiseError(
'Do not use the HTML escaping provided by this class in '.
'a Phabricator context.');
}
return $str;
@ -506,5 +492,9 @@ class Text_Figlet
return true;
}
private static function raiseError($message, $code = 1) {
throw new Exception($message);
}
}
?>

View file

@ -7,33 +7,28 @@ final class PhabricatorRemarkupFigletBlockInterpreter
return 'figlet';
}
/**
* @phutil-external-symbol class Text_Figlet
*/
public function markupContent($content, array $argv) {
if (!Filesystem::binaryExists('figlet')) {
return $this->markupError(
pht(
'Unable to locate the `%s` binary. Install figlet.',
'figlet'));
$map = self::getFigletMap();
$font = idx($argv, 'font');
$font = phutil_utf8_strtolower($font);
if (empty($map[$font])) {
$font = 'standard';
}
$font = idx($argv, 'font', 'standard');
$safe_font = preg_replace('/[^0-9a-zA-Z-_.]/', '', $font);
$future = id(new ExecFuture('figlet -f %s', $safe_font))
->setTimeout(15)
->write(trim($content, "\n"));
$root = dirname(phutil_get_library_root('phabricator'));
require_once $root.'/externals/pear-figlet/Text/Figlet.php';
list($err, $stdout, $stderr) = $future->resolve();
if ($err) {
return $this->markupError(
pht(
'Execution of `%s` failed: %s',
'figlet',
$stderr));
}
$figlet = new Text_Figlet();
$figlet->loadFont($map[$font]);
$result = $figlet->lineEcho($content);
if ($this->getEngine()->isTextMode()) {
return $stdout;
return $result;
}
return phutil_tag(
@ -41,7 +36,30 @@ final class PhabricatorRemarkupFigletBlockInterpreter
array(
'class' => 'PhabricatorMonospaced remarkup-figlet',
),
$stdout);
$result);
}
private static function getFigletMap() {
$root = dirname(phutil_get_library_root('phabricator'));
$dirs = array(
$root.'/externals/figlet/fonts/',
$root.'/externals/pear-figlet/fonts/',
$root.'/resources/figlet/custom/',
);
$map = array();
foreach ($dirs as $dir) {
foreach (Filesystem::listDirectory($dir, false) as $file) {
if (preg_match('/\.flf\z/', $file)) {
$name = phutil_utf8_strtolower($file);
$name = preg_replace('/\.flf\z/', '', $name);
$map[$name] = $dir.$file;
}
}
}
return $map;
}
}