Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Maildir.php
Go to the documentation of this file.
1 <?php
27 #require_once 'Zend/Mail/Storage/Folder/Maildir.php';
28 
32 #require_once 'Zend/Mail/Storage/Writable/Interface.php';
33 
34 
44 {
45  // TODO: init maildir (+ constructor option create if not found)
46 
51  protected $_quota;
52 
62  public static function initMaildir($dir)
63  {
64  if (file_exists($dir)) {
65  if (!is_dir($dir)) {
69  #require_once 'Zend/Mail/Storage/Exception.php';
70  throw new Zend_Mail_Storage_Exception('maildir must be a directory if already exists');
71  }
72  } else {
73  if (!mkdir($dir)) {
77  #require_once 'Zend/Mail/Storage/Exception.php';
78  $dir = dirname($dir);
79  if (!file_exists($dir)) {
80  throw new Zend_Mail_Storage_Exception("parent $dir not found");
81  } else if (!is_dir($dir)) {
82  throw new Zend_Mail_Storage_Exception("parent $dir not a directory");
83  } else {
84  throw new Zend_Mail_Storage_Exception('cannot create maildir');
85  }
86  }
87  }
88 
89  foreach (array('cur', 'tmp', 'new') as $subdir) {
90  if (!@mkdir($dir . DIRECTORY_SEPARATOR . $subdir)) {
91  // ignore if dir exists (i.e. was already valid maildir or two processes try to create one)
92  if (!file_exists($dir . DIRECTORY_SEPARATOR . $subdir)) {
96  #require_once 'Zend/Mail/Storage/Exception.php';
97  throw new Zend_Mail_Storage_Exception('could not create subdir ' . $subdir);
98  }
99  }
100  }
101  }
102 
111  public function __construct($params) {
112  if (is_array($params)) {
113  $params = (object)$params;
114  }
115 
116  if (!empty($params->create) && isset($params->dirname) && !file_exists($params->dirname . DIRECTORY_SEPARATOR . 'cur')) {
117  self::initMaildir($params->dirname);
118  }
119 
120  parent::__construct($params);
121  }
122 
134  public function createFolder($name, $parentFolder = null)
135  {
136  if ($parentFolder instanceof Zend_Mail_Storage_Folder) {
137  $folder = $parentFolder->getGlobalName() . $this->_delim . $name;
138  } else if ($parentFolder != null) {
139  $folder = rtrim($parentFolder, $this->_delim) . $this->_delim . $name;
140  } else {
141  $folder = $name;
142  }
143 
144  $folder = trim($folder, $this->_delim);
145 
146  // first we check if we try to create a folder that does exist
147  $exists = null;
148  try {
149  $exists = $this->getFolders($folder);
150  } catch (Zend_Mail_Exception $e) {
151  // ok
152  }
153  if ($exists) {
157  #require_once 'Zend/Mail/Storage/Exception.php';
158  throw new Zend_Mail_Storage_Exception('folder already exists');
159  }
160 
161  if (strpos($folder, $this->_delim . $this->_delim) !== false) {
165  #require_once 'Zend/Mail/Storage/Exception.php';
166  throw new Zend_Mail_Storage_Exception('invalid name - folder parts may not be empty');
167  }
168 
169  if (strpos($folder, 'INBOX' . $this->_delim) === 0) {
170  $folder = substr($folder, 6);
171  }
172 
173  $fulldir = $this->_rootdir . '.' . $folder;
174 
175  // check if we got tricked and would create a dir outside of the rootdir or not as direct child
176  if (strpos($folder, DIRECTORY_SEPARATOR) !== false || strpos($folder, '/') !== false
177  || dirname($fulldir) . DIRECTORY_SEPARATOR != $this->_rootdir) {
181  #require_once 'Zend/Mail/Storage/Exception.php';
182  throw new Zend_Mail_Storage_Exception('invalid name - no directory seprator allowed in folder name');
183  }
184 
185  // has a parent folder?
186  $parent = null;
187  if (strpos($folder, $this->_delim)) {
188  // let's see if the parent folder exists
189  $parent = substr($folder, 0, strrpos($folder, $this->_delim));
190  try {
191  $this->getFolders($parent);
192  } catch (Zend_Mail_Exception $e) {
193  // does not - create parent folder
194  $this->createFolder($parent);
195  }
196  }
197 
198  if (!@mkdir($fulldir) || !@mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) {
202  #require_once 'Zend/Mail/Storage/Exception.php';
203  throw new Zend_Mail_Storage_Exception('error while creating new folder, may be created incompletly');
204  }
205 
206  mkdir($fulldir . DIRECTORY_SEPARATOR . 'new');
207  mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp');
208 
209  $localName = $parent ? substr($folder, strlen($parent) + 1) : $folder;
210  $this->getFolders($parent)->$localName = new Zend_Mail_Storage_Folder($localName, $folder, true);
211 
212  return $fulldir;
213  }
214 
222  public function removeFolder($name)
223  {
224  // TODO: This could fail in the middle of the task, which is not optimal.
225  // But there is no defined standard way to mark a folder as removed and there is no atomar fs-op
226  // to remove a directory. Also moving the folder to a/the trash folder is not possible, as
227  // all parent folders must be created. What we could do is add a dash to the front of the
228  // directory name and it should be ignored as long as other processes obey the standard.
229 
230  if ($name instanceof Zend_Mail_Storage_Folder) {
231  $name = $name->getGlobalName();
232  }
233 
234  $name = trim($name, $this->_delim);
235  if (strpos($name, 'INBOX' . $this->_delim) === 0) {
236  $name = substr($name, 6);
237  }
238 
239  // check if folder exists and has no children
240  if (!$this->getFolders($name)->isLeaf()) {
244  #require_once 'Zend/Mail/Storage/Exception.php';
245  throw new Zend_Mail_Storage_Exception('delete children first');
246  }
247 
248  if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') {
252  #require_once 'Zend/Mail/Storage/Exception.php';
253  throw new Zend_Mail_Storage_Exception('wont delete INBOX');
254  }
255 
256  if ($name == $this->getCurrentFolder()) {
260  #require_once 'Zend/Mail/Storage/Exception.php';
261  throw new Zend_Mail_Storage_Exception('wont delete selected folder');
262  }
263 
264  foreach (array('tmp', 'new', 'cur', '.') as $subdir) {
265  $dir = $this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir;
266  if (!file_exists($dir)) {
267  continue;
268  }
269  $dh = opendir($dir);
270  if (!$dh) {
274  #require_once 'Zend/Mail/Storage/Exception.php';
275  throw new Zend_Mail_Storage_Exception("error opening $subdir");
276  }
277  while (($entry = readdir($dh)) !== false) {
278  if ($entry == '.' || $entry == '..') {
279  continue;
280  }
281  if (!unlink($dir . DIRECTORY_SEPARATOR . $entry)) {
285  #require_once 'Zend/Mail/Storage/Exception.php';
286  throw new Zend_Mail_Storage_Exception("error cleaning $subdir");
287  }
288  }
289  closedir($dh);
290  if ($subdir !== '.') {
291  if (!rmdir($dir)) {
295  #require_once 'Zend/Mail/Storage/Exception.php';
296  throw new Zend_Mail_Storage_Exception("error removing $subdir");
297  }
298  }
299  }
300 
301  if (!rmdir($this->_rootdir . '.' . $name)) {
302  // at least we should try to make it a valid maildir again
303  mkdir($this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur');
307  #require_once 'Zend/Mail/Storage/Exception.php';
308  throw new Zend_Mail_Storage_Exception("error removing maindir");
309  }
310 
311  $parent = strpos($name, $this->_delim) ? substr($name, 0, strrpos($name, $this->_delim)) : null;
312  $localName = $parent ? substr($name, strlen($parent) + 1) : $name;
313  unset($this->getFolders($parent)->$localName);
314  }
315 
326  public function renameFolder($oldName, $newName)
327  {
328  // TODO: This is also not atomar and has similar problems as removeFolder()
329 
330  if ($oldName instanceof Zend_Mail_Storage_Folder) {
331  $oldName = $oldName->getGlobalName();
332  }
333 
334  $oldName = trim($oldName, $this->_delim);
335  if (strpos($oldName, 'INBOX' . $this->_delim) === 0) {
336  $oldName = substr($oldName, 6);
337  }
338 
339  $newName = trim($newName, $this->_delim);
340  if (strpos($newName, 'INBOX' . $this->_delim) === 0) {
341  $newName = substr($newName, 6);
342  }
343 
344  if (strpos($newName, $oldName . $this->_delim) === 0) {
348  #require_once 'Zend/Mail/Storage/Exception.php';
349  throw new Zend_Mail_Storage_Exception('new folder cannot be a child of old folder');
350  }
351 
352  // check if folder exists and has no children
353  $folder = $this->getFolders($oldName);
354 
355  if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') {
359  #require_once 'Zend/Mail/Storage/Exception.php';
360  throw new Zend_Mail_Storage_Exception('wont rename INBOX');
361  }
362 
363  if ($oldName == $this->getCurrentFolder()) {
367  #require_once 'Zend/Mail/Storage/Exception.php';
368  throw new Zend_Mail_Storage_Exception('wont rename selected folder');
369  }
370 
371  $newdir = $this->createFolder($newName);
372 
373  if (!$folder->isLeaf()) {
374  foreach ($folder as $k => $v) {
375  $this->renameFolder($v->getGlobalName(), $newName . $this->_delim . $k);
376  }
377  }
378 
379  $olddir = $this->_rootdir . '.' . $folder;
380  foreach (array('tmp', 'new', 'cur') as $subdir) {
381  $subdir = DIRECTORY_SEPARATOR . $subdir;
382  if (!file_exists($olddir . $subdir)) {
383  continue;
384  }
385  // using copy or moving files would be even better - but also much slower
386  if (!rename($olddir . $subdir, $newdir . $subdir)) {
390  #require_once 'Zend/Mail/Storage/Exception.php';
391  throw new Zend_Mail_Storage_Exception('error while moving ' . $subdir);
392  }
393  }
394  // create a dummy if removing fails - otherwise we can't read it next time
395  mkdir($olddir . DIRECTORY_SEPARATOR . 'cur');
396  $this->removeFolder($oldName);
397  }
398 
412  protected function _createUniqueId()
413  {
414  $id = '';
415  $id .= function_exists('microtime') ? microtime(true) : (time() . ' ' . rand(0, 100000));
416  $id .= '.' . (function_exists('posix_getpid') ? posix_getpid() : rand(50, 65535));
417  $id .= '.' . php_uname('n');
418 
419  return $id;
420  }
421 
433  protected function _createTmpFile($folder = 'INBOX')
434  {
435  if ($folder == 'INBOX') {
436  $tmpdir = $this->_rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
437  } else {
438  $tmpdir = $this->_rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
439  }
440  if (!file_exists($tmpdir)) {
441  if (!mkdir($tmpdir)) {
445  #require_once 'Zend/Mail/Storage/Exception.php';
446  throw new Zend_Mail_Storage_Exception('problems creating tmp dir');
447  }
448  }
449 
450  // we should retry to create a unique id if a file with the same name exists
451  // to avoid a script timeout we only wait 1 second (instead of 2) and stop
452  // after a defined retry count
453  // if you change this variable take into account that it can take up to $max_tries seconds
454  // normally we should have a valid unique name after the first try, we're just following the "standard" here
455  $max_tries = 5;
456  for ($i = 0; $i < $max_tries; ++$i) {
457  $uniq = $this->_createUniqueId();
458  if (!file_exists($tmpdir . $uniq)) {
459  // here is the race condition! - as defined in the standard
460  // to avoid having a long time between stat()ing the file and creating it we're opening it here
461  // to mark the filename as taken
462  $fh = fopen($tmpdir . $uniq, 'w');
463  if (!$fh) {
467  #require_once 'Zend/Mail/Storage/Exception.php';
468  throw new Zend_Mail_Storage_Exception('could not open temp file');
469  }
470  break;
471  }
472  sleep(1);
473  }
474 
475  if (!$fh) {
479  #require_once 'Zend/Mail/Storage/Exception.php';
480  throw new Zend_Mail_Storage_Exception("tried $max_tries unique ids for a temp file, but all were taken"
481  . ' - giving up');
482  }
483 
484  return array('dirname' => $this->_rootdir . '.' . $folder, 'uniq' => $uniq, 'filename' => $tmpdir . $uniq,
485  'handle' => $fh);
486  }
487 
495  protected function _getInfoString(&$flags)
496  {
497  // accessing keys is easier, faster and it removes duplicated flags
498  $wanted_flags = array_flip($flags);
499  if (isset($wanted_flags[Zend_Mail_Storage::FLAG_RECENT])) {
503  #require_once 'Zend/Mail/Storage/Exception.php';
504  throw new Zend_Mail_Storage_Exception('recent flag may not be set');
505  }
506 
507  $info = ':2,';
508  $flags = array();
509  foreach (Zend_Mail_Storage_Maildir::$_knownFlags as $char => $flag) {
510  if (!isset($wanted_flags[$flag])) {
511  continue;
512  }
513  $info .= $char;
514  $flags[$char] = $flag;
515  unset($wanted_flags[$flag]);
516  }
517 
518  if (!empty($wanted_flags)) {
519  $wanted_flags = implode(', ', array_keys($wanted_flags));
523  #require_once 'Zend/Mail/Storage/Exception.php';
524  throw new Zend_Mail_Storage_Exception('unknown flag(s): ' . $wanted_flags);
525  }
526 
527  return $info;
528  }
529 
540  // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class
541 
542  public function appendMessage($message, $folder = null, $flags = null, $recent = false)
543  {
544  if ($this->_quota && $this->checkQuota()) {
548  #require_once 'Zend/Mail/Storage/Exception.php';
549  throw new Zend_Mail_Storage_Exception('storage is over quota!');
550  }
551 
552  if ($folder === null) {
553  $folder = $this->_currentFolder;
554  }
555 
556  if (!($folder instanceof Zend_Mail_Storage_Folder)) {
557  $folder = $this->getFolders($folder);
558  }
559 
560  if ($flags === null) {
561  $flags = array(Zend_Mail_Storage::FLAG_SEEN);
562  }
563  $info = $this->_getInfoString($flags);
564  $temp_file = $this->_createTmpFile($folder->getGlobalName());
565 
566  // TODO: handle class instances for $message
567  if (is_resource($message) && get_resource_type($message) == 'stream') {
568  stream_copy_to_stream($message, $temp_file['handle']);
569  } else {
570  fputs($temp_file['handle'], $message);
571  }
572  fclose($temp_file['handle']);
573 
574  // we're adding the size to the filename for maildir++
575  $size = filesize($temp_file['filename']);
576  if ($size !== false) {
577  $info = ',S=' . $size . $info;
578  }
579  $new_filename = $temp_file['dirname'] . DIRECTORY_SEPARATOR;
580  $new_filename .= $recent ? 'new' : 'cur';
581  $new_filename .= DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info;
582 
583  // we're throwing any exception after removing our temp file and saving it to this variable instead
584  $exception = null;
585 
586  if (!link($temp_file['filename'], $new_filename)) {
590  #require_once 'Zend/Mail/Storage/Exception.php';
591  $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
592  }
593  @unlink($temp_file['filename']);
594 
595  if ($exception) {
596  throw $exception;
597  }
598 
599  $this->_files[] = array('uniq' => $temp_file['uniq'],
600  'flags' => $flags,
601  'filename' => $new_filename);
602  if ($this->_quota) {
603  $this->_addQuotaEntry((int)$size, 1);
604  }
605  }
606 
615  public function copyMessage($id, $folder)
616  {
617  if ($this->_quota && $this->checkQuota()) {
621  #require_once 'Zend/Mail/Storage/Exception.php';
622  throw new Zend_Mail_Storage_Exception('storage is over quota!');
623  }
624 
625  if (!($folder instanceof Zend_Mail_Storage_Folder)) {
626  $folder = $this->getFolders($folder);
627  }
628 
629  $filedata = $this->_getFileData($id);
630  $old_file = $filedata['filename'];
631  $flags = $filedata['flags'];
632 
633  // copied message can't be recent
634  while (($key = array_search(Zend_Mail_Storage::FLAG_RECENT, $flags)) !== false) {
635  unset($flags[$key]);
636  }
637  $info = $this->_getInfoString($flags);
638 
639  // we're creating the copy as temp file before moving to cur/
640  $temp_file = $this->_createTmpFile($folder->getGlobalName());
641  // we don't write directly to the file
642  fclose($temp_file['handle']);
643 
644  // we're adding the size to the filename for maildir++
645  $size = filesize($old_file);
646  if ($size !== false) {
647  $info = ',S=' . $size . $info;
648  }
649 
650  $new_file = $temp_file['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info;
651 
652  // we're throwing any exception after removing our temp file and saving it to this variable instead
653  $exception = null;
654 
655  if (!copy($old_file, $temp_file['filename'])) {
659  #require_once 'Zend/Mail/Storage/Exception.php';
660  $exception = new Zend_Mail_Storage_Exception('cannot copy message file');
661  } else if (!link($temp_file['filename'], $new_file)) {
665  #require_once 'Zend/Mail/Storage/Exception.php';
666  $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
667  }
668  @unlink($temp_file['filename']);
669 
670  if ($exception) {
671  throw $exception;
672  }
673 
674  if ($folder->getGlobalName() == $this->_currentFolder
675  || ($this->_currentFolder == 'INBOX' && $folder->getGlobalName() == '/')) {
676  $this->_files[] = array('uniq' => $temp_file['uniq'],
677  'flags' => $flags,
678  'filename' => $new_file);
679  }
680 
681  if ($this->_quota) {
682  $this->_addQuotaEntry((int)$size, 1);
683  }
684  }
685 
694  public function moveMessage($id, $folder) {
695  if (!($folder instanceof Zend_Mail_Storage_Folder)) {
696  $folder = $this->getFolders($folder);
697  }
698 
699  if ($folder->getGlobalName() == $this->_currentFolder
700  || ($this->_currentFolder == 'INBOX' && $folder->getGlobalName() == '/')) {
704  #require_once 'Zend/Mail/Storage/Exception.php';
705  throw new Zend_Mail_Storage_Exception('target is current folder');
706  }
707 
708  $filedata = $this->_getFileData($id);
709  $old_file = $filedata['filename'];
710  $flags = $filedata['flags'];
711 
712  // moved message can't be recent
713  while (($key = array_search(Zend_Mail_Storage::FLAG_RECENT, $flags)) !== false) {
714  unset($flags[$key]);
715  }
716  $info = $this->_getInfoString($flags);
717 
718  // reserving a new name
719  $temp_file = $this->_createTmpFile($folder->getGlobalName());
720  fclose($temp_file['handle']);
721 
722  // we're adding the size to the filename for maildir++
723  $size = filesize($old_file);
724  if ($size !== false) {
725  $info = ',S=' . $size . $info;
726  }
727 
728  $new_file = $temp_file['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info;
729 
730  // we're throwing any exception after removing our temp file and saving it to this variable instead
731  $exception = null;
732 
733  if (!rename($old_file, $new_file)) {
737  #require_once 'Zend/Mail/Storage/Exception.php';
738  $exception = new Zend_Mail_Storage_Exception('cannot move message file');
739  }
740  @unlink($temp_file['filename']);
741 
742  if ($exception) {
743  throw $exception;
744  }
745 
746  unset($this->_files[$id - 1]);
747  // remove the gap
748  $this->_files = array_values($this->_files);
749  }
750 
751 
761  public function setFlags($id, $flags)
762  {
763  $info = $this->_getInfoString($flags);
764  $filedata = $this->_getFileData($id);
765 
766  // NOTE: double dirname to make sure we always move to cur. if recent flag has been set (message is in new) it will be moved to cur.
767  $new_filename = dirname(dirname($filedata['filename'])) . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . "$filedata[uniq]$info";
768 
769  if (!@rename($filedata['filename'], $new_filename)) {
773  #require_once 'Zend/Mail/Storage/Exception.php';
774  throw new Zend_Mail_Storage_Exception('cannot rename file');
775  }
776 
777  $filedata['flags'] = $flags;
778  $filedata['filename'] = $new_filename;
779 
780  $this->_files[$id - 1] = $filedata;
781  }
782 
783 
790  public function removeMessage($id)
791  {
792  $filename = $this->_getFileData($id, 'filename');
793 
794  if ($this->_quota) {
795  $size = filesize($filename);
796  }
797 
798  if (!@unlink($filename)) {
802  #require_once 'Zend/Mail/Storage/Exception.php';
803  throw new Zend_Mail_Storage_Exception('cannot remove message');
804  }
805  unset($this->_files[$id - 1]);
806  // remove the gap
807  $this->_files = array_values($this->_files);
808  if ($this->_quota) {
809  $this->_addQuotaEntry(0 - (int)$size, -1);
810  }
811  }
812 
824  public function setQuota($value) {
825  $this->_quota = $value;
826  }
827 
835  public function getQuota($fromStorage = false) {
836  if ($fromStorage) {
837  $fh = @fopen($this->_rootdir . 'maildirsize', 'r');
838  if (!$fh) {
842  #require_once 'Zend/Mail/Storage/Exception.php';
843  throw new Zend_Mail_Storage_Exception('cannot open maildirsize');
844  }
845  $definition = fgets($fh);
846  fclose($fh);
847  $definition = explode(',', trim($definition));
848  $quota = array();
849  foreach ($definition as $member) {
850  $key = $member[strlen($member) - 1];
851  if ($key == 'S' || $key == 'C') {
852  $key = $key == 'C' ? 'count' : 'size';
853  }
854  $quota[$key] = substr($member, 0, -1);
855  }
856  return $quota;
857  }
858 
859  return $this->_quota;
860  }
861 
865  protected function _calculateMaildirsize() {
866  $timestamps = array();
867  $messages = 0;
868  $total_size = 0;
869 
870  if (is_array($this->_quota)) {
871  $quota = $this->_quota;
872  } else {
873  try {
874  $quota = $this->getQuota(true);
875  } catch (Zend_Mail_Storage_Exception $e) {
876  throw new Zend_Mail_Storage_Exception('no quota definition found', 0, $e);
877  }
878  }
879 
880  $folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
881  foreach ($folders as $folder) {
882  $subdir = $folder->getGlobalName();
883  if ($subdir == 'INBOX') {
884  $subdir = '';
885  } else {
886  $subdir = '.' . $subdir;
887  }
888  if ($subdir == 'Trash') {
889  continue;
890  }
891 
892  foreach (array('cur', 'new') as $subsubdir) {
893  $dirname = $this->_rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR;
894  if (!file_exists($dirname)) {
895  continue;
896  }
897  // NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime
898  // and as we are accessing the directory it would make the whole calculation useless.
899  $timestamps[$dirname] = filemtime($dirname);
900 
901  $dh = opendir($dirname);
902  // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will
903  // therefore not be fully enforeced, but next request will fail anyway, if problem persists.
904  if (!$dh) {
905  continue;
906  }
907 
908 
909  while (($entry = readdir()) !== false) {
910  if ($entry[0] == '.' || !is_file($dirname . $entry)) {
911  continue;
912  }
913 
914  if (strpos($entry, ',S=')) {
915  strtok($entry, '=');
916  $filesize = strtok(':');
917  if (is_numeric($filesize)) {
918  $total_size += $filesize;
919  ++$messages;
920  continue;
921  }
922  }
923  $size = filesize($dirname . $entry);
924  if ($size === false) {
925  // ignore, as we assume file got removed
926  continue;
927  }
928  $total_size += $size;
929  ++$messages;
930  }
931  }
932  }
933 
934  $tmp = $this->_createTmpFile();
935  $fh = $tmp['handle'];
936  $definition = array();
937  foreach ($quota as $type => $value) {
938  if ($type == 'size' || $type == 'count') {
939  $type = $type == 'count' ? 'C' : 'S';
940  }
941  $definition[] = $value . $type;
942  }
943  $definition = implode(',', $definition);
944  fputs($fh, "$definition\n");
945  fputs($fh, "$total_size $messages\n");
946  fclose($fh);
947  rename($tmp['filename'], $this->_rootdir . 'maildirsize');
948  foreach ($timestamps as $dir => $timestamp) {
949  if ($timestamp < filemtime($dir)) {
950  unlink($this->_rootdir . 'maildirsize');
951  break;
952  }
953  }
954 
955  return array('size' => $total_size, 'count' => $messages, 'quota' => $quota);
956  }
957 
961  protected function _calculateQuota($forceRecalc = false) {
962  $fh = null;
963  $total_size = 0;
964  $messages = 0;
965  $maildirsize = '';
966  if (!$forceRecalc && file_exists($this->_rootdir . 'maildirsize') && filesize($this->_rootdir . 'maildirsize') < 5120) {
967  $fh = fopen($this->_rootdir . 'maildirsize', 'r');
968  }
969  if ($fh) {
970  $maildirsize = fread($fh, 5120);
971  if (strlen($maildirsize) >= 5120) {
972  fclose($fh);
973  $fh = null;
974  $maildirsize = '';
975  }
976  }
977  if (!$fh) {
978  $result = $this->_calculateMaildirsize();
979  $total_size = $result['size'];
980  $messages = $result['count'];
981  $quota = $result['quota'];
982  } else {
983  $maildirsize = explode("\n", $maildirsize);
984  if (is_array($this->_quota)) {
985  $quota = $this->_quota;
986  } else {
987  $definition = explode(',', $maildirsize[0]);
988  $quota = array();
989  foreach ($definition as $member) {
990  $key = $member[strlen($member) - 1];
991  if ($key == 'S' || $key == 'C') {
992  $key = $key == 'C' ? 'count' : 'size';
993  }
994  $quota[$key] = substr($member, 0, -1);
995  }
996  }
997  unset($maildirsize[0]);
998  foreach ($maildirsize as $line) {
999  list($size, $count) = explode(' ', trim($line));
1000  $total_size += $size;
1001  $messages += $count;
1002  }
1003  }
1004 
1005  $over_quota = false;
1006  $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
1007  $over_quota = $over_quota || (isset($quota['count']) && $messages > $quota['count']);
1008  // NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only
1009  // one line, because $maildirsize[0] gets unsetted.
1010  // Also we're using local time to calculate the 15 minute offset. Touching a file just for known the
1011  // local time of the file storage isn't worth the hassle.
1012  if ($over_quota && ($maildirsize || filemtime($this->_rootdir . 'maildirsize') > time() - 900)) {
1013  $result = $this->_calculateMaildirsize();
1014  $total_size = $result['size'];
1015  $messages = $result['count'];
1016  $quota = $result['quota'];
1017  $over_quota = false;
1018  $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
1019  $over_quota = $over_quota || (isset($quota['count']) && $messages > $quota['count']);
1020  }
1021 
1022  if ($fh) {
1023  // TODO is there a safe way to keep the handle open for writing?
1024  fclose($fh);
1025  }
1026 
1027  return array('size' => $total_size, 'count' => $messages, 'quota' => $quota, 'over_quota' => $over_quota);
1028  }
1029 
1030  protected function _addQuotaEntry($size, $count = 1) {
1031  if (!file_exists($this->_rootdir . 'maildirsize')) {
1032  // TODO: should get file handler from _calculateQuota
1033  }
1034  $size = (int)$size;
1035  $count = (int)$count;
1036  file_put_contents($this->_rootdir . 'maildirsize', "$size $count\n", FILE_APPEND);
1037  }
1038 
1045  public function checkQuota($detailedResponse = false, $forceRecalc = false) {
1046  $result = $this->_calculateQuota($forceRecalc);
1047  return $detailedResponse ? $result : $result['over_quota'];
1048  }
1049 }
checkQuota($detailedResponse=false, $forceRecalc=false)
Definition: Maildir.php:1045
const FLAG_RECENT
Definition: Storage.php:39
_createTmpFile($folder='INBOX')
Definition: Maildir.php:433
$id
Definition: fieldset.phtml:14
$count
Definition: recent.phtml:13
createFolder($name, $parentFolder=null)
Definition: Maildir.php:134
$message
$type
Definition: item.phtml:13
getQuota($fromStorage=false)
Definition: Maildir.php:835
_getFileData($id, $field=null)
Definition: Maildir.php:119
$value
Definition: gender.phtml:16
getFolders($rootFolder=null)
Definition: Maildir.php:187
renameFolder($oldName, $newName)
Definition: Maildir.php:326
appendMessage($message, $folder=null, $flags=null, $recent=false)
Definition: Maildir.php:542
mkdir($pathname, $mode=0777, $recursive=false, $context=null)
Definition: ioMock.php:25
foreach( $_productCollection as $_product)() ?>" class $info
Definition: listing.phtml:52
_calculateQuota($forceRecalc=false)
Definition: Maildir.php:961
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]
Definition: website.php:18
$i
Definition: gallery.phtml:31
if(!isset($_GET['name'])) $name
Definition: log.php:14