Skip to content

Commit

Permalink
[mms] Add ability to download individual files from within a .tgz att…
Browse files Browse the repository at this point in the history
…achment.
  • Loading branch information
slusarz committed Nov 8, 2014
1 parent 5fab542 commit 3479d57
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 1 deletion.
19 changes: 19 additions & 0 deletions imp/config/mime_drivers.php
Expand Up @@ -176,6 +176,25 @@
'show_contents' => false
),

/* Tar file display.
* To access gzipped files, the zlib library must have been built into PHP
* (with the --with-zlib option). */
'tgz' => array(
'inline' => true,
'handles' => array(
'application/gzip',
'application/x-compressed-tar',
'application/x-gtar',
'application/x-gzip',
'application/x-gzip-compressed',
'application/x-tar',
'application/x-tgz'
),
'icons' => array(
'default' => 'compressed.png'
)
),

/* Delivery status messages display. */
'status' => array(
'inline' => true,
Expand Down
1 change: 1 addition & 0 deletions imp/docs/CHANGES
Expand Up @@ -2,6 +2,7 @@
v7.0.0-git
----------

[mms] Add ability to download individual files from within a .tgz attachment.
[mms] Improved display of contents of ZIP attachments.
[mms] Contacts popup now does address search dynamically, without the need to
reload the page.
Expand Down
2 changes: 2 additions & 0 deletions imp/docs/UPGRADING
Expand Up @@ -76,6 +76,8 @@ MIME Viewer Options (mime_drivers.php)
The ZIP driver now does not show the contents of the ZIP file by default. Set
the 'show_contents' option to true to restore the old behavior.

Added the TGZ (tar/gzip) driver.


Preferences (prefs.php)
-----------------------
Expand Down
4 changes: 4 additions & 0 deletions imp/js/dimpcore.js
Expand Up @@ -322,6 +322,10 @@ var DimpCore = {
elt.replace(this.text.loading);
this.reloadMessage({ zip_contents: 1 });
e.memo.stop();
} else if (elt.hasClassName('tgzViewContents')) {
elt.replace(this.text.loading);
this.reloadMessage({ tgz_contents: 1 });
e.memo.stop();
}
},

Expand Down
171 changes: 171 additions & 0 deletions imp/lib/Mime/Viewer/Tgz.php
@@ -0,0 +1,171 @@
<?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
*/

/**
* Handler to render the contents of gzip/tar files, allowing downloading of
* extractable files.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
class IMP_Mime_Viewer_Tgz extends Horde_Mime_Viewer_Tgz
{
/**
* Return the full rendered version of the Horde_Mime_Part object.
*
* URL parameters used by this function:
* - tgz_attachment: (integer) The ZIP attachment to download.
*
* @return array See parent::render().
* @throws Horde_Exception
*/
protected function _render()
{
global $injector;

$vars = $injector->getInstance('Horde_Variables');
$tgzInfo = $this->_getTgzInfo();

/* Verify that the requested file exists. */
if ((($key = $vars->tgz_attachment) === null) ||
!isset($tgzInfo[$key])) {
return array();
}

return array(
$this->_mimepart->getMimeId() => array(
'data' => $tgzInfo[$key]['data'],
'name' => basename($tgzInfo[$key]['name']),
'type' => 'application/octet-stream'
)
);
}

/**
* Return the rendered information about the Horde_Mime_Part object.
*
* URL parameters used by this function:
* - tgz_contents: (integer) If set, show contents of ZIP file.
*
* @return array See Horde_Mime_Viewer_Driver::render().
*/
protected function _renderInfo()
{
global $injector;

$vars = $injector->getInstance('Horde_Variables');

if (!$this->getConfigParam('show_contents') &&
!isset($vars->tgz_contents)) {
$status = new IMP_Mime_Status(_("This is a gzip/tar compressed file."));
$status->icon('mime/compressed.png');
$status->addText(
Horde::link('#', '', 'tgzViewContents') .
_("Click HERE to display the contents.") .
'</a>'
);

return array(
$this->_mimepart->getMimeId() => array(
'data' => '',
'status' => $status,
'type' => 'text/html; charset=UTF-8'
)
);
}

$view = new Horde_View(array(
'templatePath' => IMP_TEMPLATES . '/mime'
));
$view->addHelper('Text');

$view->files = array();

$tgzInfo = $this->_getTgzInfo();
$zlib = Horde_Util::extensionExists('zlib');

foreach ($tgzInfo as $key => $val) {
if (!strlen($val['data'])) {
continue;
}

$file = new stdClass;
$file->download = '';
$file->name = $val['name'];
$file->size = IMP::sizeFormat($val['size']);

if (!empty($val['size'])) {
$file->download = $this->getConfigParam('imp_contents')->linkView(
$this->_mimepart,
'download_render',
'',
array(
'class' => 'iconImg downloadAtc',
'jstext' => _("Download"),
'params' => array(
'tgz_attachment' => $key
)
)
);
}

$view->files[] = $file;
}

return array(
$this->_mimepart->getMimeId() => array(
'data' => $view->render('tgz'),
'type' => 'text/html; charset=UTF-8'
)
);
}

/**
* Return TGZ information.
*
* @return array See Horde_Compress_Tgz#decompress().
*/
protected function _getTgzInfo()
{
$contents = $this->_mimepart->getContents();
$gzip = $this->getConfigParam('gzip');
$tar = $this->getConfigParam('tar');

try {
$contents = $gzip->decompress($contents);
$this->_metadata['compressed'] = true;
} catch (Horde_Compress_Exception $e) {
$this->_metadata['compressed'] = false;
}

try {
return $tar->decompress($contents);
} catch (Horde_Compress_Exception $e) {
if ($this->_metadata['compressed']) {
/* Doubly gzip'd tgz files are somewhat common. Try a second
* decompression before giving up. */
try {
return $tar->decompress(
$gzip->decompress($contents)
);
} catch (Horde_Compress_Exception $e) {}
}
}

return null;
}

}
1 change: 1 addition & 0 deletions imp/package.xml
Expand Up @@ -33,6 +33,7 @@
</stability>
<license uri="http://www.horde.org/licenses/gpl">GPL-2.0</license>
<notes>
* [mms] Add ability to download individual files from within a .tgz attachment.
* [mms] Improved display of contents of ZIP attachments.
* [mms] Contacts popup now does address search dynamically, without the need to reload the page.
* [mms] Remove &apos;mailboxarray&apos; hook.
Expand Down
22 changes: 22 additions & 0 deletions imp/templates/mime/tgz.html.php
@@ -0,0 +1,22 @@
<p>
<h3><?php echo _("Contents of Tar/Gzip file:") ?></h3>
</p>

<table class="horde-table tgzcontents">
<thead>
<tr>
<th><?php echo _("Filename") ?></th>
<th><?php echo _("Size") ?></th>
<th><?php echo _("Download") ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($this->files as $v): ?>
<tr>
<td><?php echo $this->h($v->name) ?></td>
<td><?php echo $this->h($v->size) ?></td>
<td class="tgzdownload"><?php echo $v->download ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
4 changes: 3 additions & 1 deletion imp/themes/default/mime.css
Expand Up @@ -10,12 +10,14 @@ table.imp-itip {
background-color: #ffdf4d;
}

/* ZIP styles. */
/* TGZ/ZIP styles. */
table.tgzcontents,
table.zipcontents {
border-left: 1px solid #d0d0d0;
border-right: 1px solid #d0d0d0;
margin-bottom: 10px;
}
td.tgzdownload a,
td.zipdownload a {
display: block;
margin-left: auto;
Expand Down

0 comments on commit 3479d57

Please sign in to comment.