Skip to content

Commit

Permalink
Abstract HTML signature image processing code
Browse files Browse the repository at this point in the history
Needed because drag/drop images is allowed in compose preview window
  • Loading branch information
slusarz committed Apr 14, 2014
1 parent d842898 commit f709e3d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 51 deletions.
26 changes: 11 additions & 15 deletions imp/lib/Compose.php
Expand Up @@ -44,9 +44,6 @@ class IMP_Compose implements ArrayAccess, Countable, IteratorAggregate
/* Related part attribute name. */
const RELATED_ATTR = 'imp_related_attr';

/* Signature data attribute name. */
const HTMLSIG_ATTR = 'imp_htmlsig';

/* The blockquote tag to use to indicate quoted text in HTML data. */
const HTML_BLOCKQUOTE = '<blockquote type="cite" style="border-left:2px solid blue;margin-left:2px;padding-left:12px;">';

Expand Down Expand Up @@ -1496,11 +1493,16 @@ protected function _createMimeMessage(
}

if (!empty($options['html'])) {
$sig_dom = new Horde_Domhtml($html_sig, 'UTF-8');
foreach ($sig_dom->getBody()->childNodes as $child) {
$node = $body_html->dom->importNode($child, true);
$node->setAttribute(self::HTMLSIG_ATTR, '1');
$body_html_body->appendChild($node);
try {
$sig_ob = new IMP_Compose_HtmlSignature($html_sig);
} catch (IMP_Exception $e) {
throw new IMP_Compose_Exception($e);
}

foreach ($sig_ob->dom->getBody()->childNodes as $child) {
$body_html_body->appendChild(
$body_html->dom->importNode($child, true)
);
}
}
}
Expand Down Expand Up @@ -2630,8 +2632,7 @@ protected function _cleanHtmlOutput(Horde_Domhtml $html)
/* Check for attempts to sneak data URL information into the
* output. */
if (Horde_Url_Data::isData($src)) {
if ((strcasecmp($node->tagName, 'IMG') === 0) &&
($xpath->query('ancestor-or-self::node()[@' . self::HTMLSIG_ATTR . ']', $node)->length)) {
if (IMP_Compose_HtmlSignature::isSigImage($node, true)) {
/* This is HTML signature image data. Convert to an
* attachment. */
$sig_img = new Horde_Url_Data($src);
Expand Down Expand Up @@ -2685,11 +2686,6 @@ protected function _cleanHtmlOutput(Horde_Domhtml $html)
}
}
}

/* Remove HTML sig identifiers. */
foreach ($xpath->query('//*[@' . self::HTMLSIG_ATTR . ']') as $node) {
$node->removeAttribute(self::HTMLSIG_ATTR);
}
}

/**
Expand Down
101 changes: 101 additions & 0 deletions imp/lib/Compose/HtmlSignature.php
@@ -0,0 +1,101 @@
<?php
/**
* Copyright 2014 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.horde.org/licenses/gpl.
*
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/

/**
* Parse HTML signature data.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
class IMP_Compose_HtmlSignature
{
/** Signature data attribute name. */
const HTMLSIG_ATTR = 'imp_htmlsig';

/**
* DOM object containing HTML signature data.
*
* @var Horde_Domhtml
*/
public $dom;

/**
* Constructor.
*
* @param string $sig HTML signature data.
*
* @throws IMP_Exception
*/
public function __construct($sig)
{
global $conf, $injector;

/* Scrub HTML. */
$this->dom = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter(
$sig,
'Xss',
array(
'charset' => 'UTF-8',
'return_dom' => true,
'strip_style_attributes' => false
)
);

$img_limit = intval($conf['compose']['htmlsig_img_size']);

$xpath = new DOMXPath($this->dom->dom);
foreach ($xpath->query('//*[@src]') as $node) {
$src = $node->getAttribute('src');

if (Horde_Url_Data::isData($src)) {
if (strcasecmp($node->tagName, 'IMG') === 0) {
$data_url = new Horde_Url_Data($src);
if ($img_limit &&
($img_limit -= strlen($data_url->data)) < 0) {
throw new IMP_Exception(_("The total size of your HTML signature image data has exceeded the maximum allowed."));
}

$node->setAttribute(self::HTMLSIG_ATTR, 1);
} else {
/* Don't allow any other non-image data URLs. */
$node->removeAttribute('src');
}
}
}
}

/**
* Determine if node contains HTML signature image data.
*
* @param DOMNode $node The node to check.
* @param boolean $strip Strip attribute from the node?
*
* @return boolean True if node contains image data.
*/
static public function isSigImage(DOMNode $node, $strip = false)
{
if ((strcasecmp($node->tagName, 'IMG') === 0) &&
$node->hasAttribute(self::HTMLSIG_ATTR)) {
if ($strip) {
$node->removeAttribute(self::HTMLSIG_ATTR);
}
return true;
}

return false;
}

}
42 changes: 7 additions & 35 deletions imp/lib/Prefs/Special/HtmlSignature.php
Expand Up @@ -63,46 +63,18 @@ public function display(Horde_Core_Prefs_Ui $ui)
*/
public function update(Horde_Core_Prefs_Ui $ui)
{
global $conf, $injector, $notification;
global $notification;

$filter = $injector->getInstance('Horde_Core_Factory_TextFilter');

/* Scrub HTML. */
$html = $filter->filter(
$ui->vars->signature_html,
'Xss',
array(
'charset' => 'UTF-8',
'return_dom' => true,
'strip_style_attributes' => false
)
);

if ($img_limit = intval($conf['compose']['htmlsig_img_size'])) {
$xpath = new DOMXPath($html->dom);
foreach ($xpath->query('//*[@src]') as $node) {
$src = $node->getAttribute('src');
if (Horde_Url_Data::isData($src)) {
if (strcasecmp($node->tagName, 'IMG') === 0) {
$data_url = new Horde_Url_Data($src);
if (($img_limit -= strlen($data_url->data)) < 0) {
$notification->push(
_("The total size of your HTML signature image data has exceeded the maximum allowed."),
'horde.error'
);
return false;
}
} else {
/* Don't allow any other non-image data URLs. */
$node->removeAttribute('src');
}
}
}
try {
new IMP_Compose_HtmlSignature($ui->vars->signature_html);
} catch (IMP_Exception $e) {
$notification->push($e, 'horde.error');
return false;
}

return $injector->getInstance('IMP_Identity')->setValue(
'signature_html',
$html->returnHtml(array('charset' => 'UTF-8'))
$ui->vars->signature_html
);
}

Expand Down
4 changes: 3 additions & 1 deletion imp/package.xml
Expand Up @@ -22,7 +22,7 @@
<email>chuck@horde.org</email>
<active>yes</active>
</lead>
<date>2014-03-23</date>
<date>2014-04-14</date>
<version>
<release>6.2.0</release>
<api>6.2.0</api>
Expand Down Expand Up @@ -227,6 +227,7 @@
</dir> <!-- /lib/Compose/Exception -->
<file name="Attachment.php" role="horde" />
<file name="Exception.php" role="horde" />
<file name="HtmlSignature.php" role="horde" />
<file name="Link.php" role="horde" />
<file name="LinkedAttachment.php" role="horde" />
<file name="References.php" role="horde" />
Expand Down Expand Up @@ -1664,6 +1665,7 @@
<install as="imp/lib/Block/Summary.php" name="lib/Block/Summary.php" />
<install as="imp/lib/Compose/Attachment.php" name="lib/Compose/Attachment.php" />
<install as="imp/lib/Compose/Exception.php" name="lib/Compose/Exception.php" />
<install as="imp/lib/Compose/HtmlSignature.php" name="lib/Compose/HtmlSignature.php" />
<install as="imp/lib/Compose/Link.php" name="lib/Compose/Link.php" />
<install as="imp/lib/Compose/LinkedAttachment.php" name="lib/Compose/LinkedAttachment.php" />
<install as="imp/lib/Compose/References.php" name="lib/Compose/References.php" />
Expand Down

0 comments on commit f709e3d

Please sign in to comment.