LDAPAccountManager/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Mail/Horde/Mail/Mbox/Parse.php

253 lines
6.0 KiB
PHP

<?php
/**
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (BSD). If you
* did not receive this file, see http://www.horde.org/licenses/bsd.
*
* @category Horde
* @copyright 2011-2017 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
/**
* This object allows easy access to parsing mbox data (RFC 4155).
*
* See:
* http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2011-2017 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
* @since 2.5.0
*/
class Horde_Mail_Mbox_Parse
implements ArrayAccess, Countable, Iterator
{
/**
* Data stream.
*
* @var resource
*/
protected $_data;
/**
* Parsed data. Each entry is an array containing 3 keys:
* - date: (mixed) Date information, in DateTime object. Null if date
* cannot be parsed. False if message is not MBOX data.
* - start: (integer) Start boundary.
*
* @var array
*/
protected $_parsed = array();
/**
* Constructor.
*
* @param mixed $data The mbox data. Either a resource or a filename
* as interpreted by fopen() (string).
* @param integer $limit Limit to this many messages; additional messages
* will throw an exception.
*
* @throws Horde_Mail_Parse_Exception
*/
public function __construct($data, $limit = null)
{
$this->_data = is_resource($data)
? $data
: @fopen($data, 'r');
if ($this->_data === false) {
throw new Horde_Mail_Exception(
Horde_Mail_Translation::t("Could not parse mailbox data.")
);
}
rewind($this->_data);
$i = 0;
$last_line = null;
/* Is this a MBOX format file? */
$mbox = false;
while (!feof($this->_data)) {
if (is_null($last_line)) {
$start = ftell($this->_data);
}
$line = fgets($this->_data);
if (is_null($last_line)) {
ltrim($line);
}
if (substr($line, 0, 5) == 'From ') {
if (is_null($last_line)) {
/* This file is in MBOX format. */
$mbox = true;
} elseif (!$mbox || (trim($last_line) !== '')) {
continue;
}
if ($limit && ($i++ > $limit)) {
throw new Horde_Mail_Exception(
sprintf(
Horde_Mail_Translation::t("Imported mailbox contains more than enforced limit of %u messages."),
$limit
)
);
}
$from_line = explode(' ', $line, 3);
try {
$date = new DateTime($from_line[2]);
} catch (Exception $e) {
$date = null;
}
$this->_parsed[] = array(
'date' => $date,
'start' => ftell($this->_data)
);
}
/* Strip all empty lines before first data. */
if (!is_null($last_line) || (trim($line) !== '')) {
$last_line = $line;
}
}
/* This was a single message, not a MBOX file. */
if (empty($this->_parsed)) {
$this->_parsed[] = array(
'date' => false,
'start' => $start
);
}
}
/* ArrayAccess methods. */
/**
*/
public function offsetExists($offset)
{
return isset($this->_parsed[$offset]);
}
/**
*/
public function offsetGet($offset)
{
if (!isset($this->_parsed[$offset])) {
return null;
}
$p = $this->_parsed[$offset];
$end = isset($this->_parsed[$offset + 1])
? $this->_parsed[$offset + 1]['start']
: null;
$fd = fopen('php://temp', 'w+');
fseek($this->_data, $p['start']);
while (!feof($this->_data)) {
$line = fgets($this->_data);
if ($end && (ftell($this->_data) >= $end)) {
break;
}
fwrite(
$fd,
(($p['date'] !== false) && substr($line, 0, 6) == '>From ')
? substr($line, 1)
: $line
);
}
$out = array(
'data' => $fd,
'date' => ($p['date'] === false) ? null : $p['date'],
'size' => intval(ftell($fd))
);
rewind($fd);
return $out;
}
/**
*/
public function offsetSet($offset, $value)
{
// NOOP
}
/**
*/
public function offsetUnset($offset)
{
// NOOP
}
/* Countable methods. */
/**
* Index count.
*
* @return integer The number of messages.
*/
public function count()
{
return count($this->_parsed);
}
/* Magic methods. */
/**
* String representation of the object.
*
* @return string String representation.
*/
public function __toString()
{
rewind($this->_data);
return stream_get_contents($this->_data);
}
/* Iterator methods. */
public function current()
{
$key = $this->key();
return is_null($key)
? null
: $this[$key];
}
public function key()
{
return key($this->_parsed);
}
public function next()
{
if ($this->valid()) {
next($this->_parsed);
}
}
public function rewind()
{
reset($this->_parsed);
}
public function valid()
{
return !is_null($this->key());
}
}