ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilFileDataMail.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 
12 require_once("./Services/FileSystem/classes/class.ilFileData.php");
13 
18 {
24  var $user_id;
25 
32 
37 
45  public function __construct($a_user_id = 0)
46  {
47  define('MAILPATH','mail');
49  $this->mail_path = parent::getPath()."/".MAILPATH;
50  $this->checkReadWrite();
51  $this->user_id = $a_user_id;
52 
54  }
55 
62  function initDirectory()
63  {
64  if(is_writable($this->getPath()))
65  {
66  if(mkdir($this->getPath().'/'.MAILPATH))
67  {
68  if(chmod($this->getPath().'/'.MAILPATH,0755))
69  {
70  $this->mail_path = $this->getPath().'/'.MAILPATH;
71  return true;
72  }
73  }
74  }
75  return false;
76  }
77 
81  public function getUploadLimit()
82  {
84  }
85 
89  public function getAttachmentsTotalSizeLimit()
90  {
91  $max_size = $this->ilias->getSetting('mail_maxsize_attach', '');
92  if(!strlen($max_size))
93  {
94  return null;
95  }
96 
97  return (float)$this->ilias->getSetting('mail_maxsize_attach', 0) * 1024;
98  }
99 
105  function getMailPath()
106  {
107  return $this->mail_path;
108  }
109 
117  public function getAttachmentPathByMD5Filename($a_filename,$a_mail_id)
118  {
119  global $ilDB;
120 
121 /* $query = "SELECT path FROM mail_attachment ".
122  "WHERE mail_id = ".$ilDB->quote($a_mail_id)."";
123 
124  $row = $this->ilias->db->getRow($query,DB_FETCHMODE_OBJECT);
125  $path = $this->getMailPath().'/'.$row->path;
126 */
127  $query = $ilDB->query("SELECT path FROM mail_attachment
128  WHERE mail_id = ".$ilDB->quote($a_mail_id,'integer')."");
129 
130  $rel_path = "";
131  while($row = $ilDB->fetchObject($query))
132  {
133  $rel_path = $row->path;
134  $path = $this->getMailPath().'/'.$row->path;
135 
136  }
137 
138  $files = ilUtil::getDir($path);
139  foreach((array)$files as $file)
140  {
141  if($file['type'] == 'file' && md5($file['entry']) == $a_filename)
142  {
143  return array(
144  'path' => $this->getMailPath().'/'.$rel_path.'/'.$file['entry'],
145  'filename' => $file['entry']
146  );
147  }
148  }
149  return '';
150  }
151 
152 
160  function getAttachmentPath($a_filename,$a_mail_id)
161  {
162  global $ilDB;
163 
164 /* $query = "SELECT path FROM mail_attachment ".
165  "WHERE mail_id = ".$ilDB->quote($a_mail_id)."";
166 
167  $row = $this->ilias->db->getRow($query,DB_FETCHMODE_OBJECT);
168  $path = $this->getMailPath().'/'.$row->path.'/'.$a_filename;
169 */
170  $query = $ilDB->query("SELECT path FROM mail_attachment ".
171  "WHERE mail_id = ".$ilDB->quote($a_mail_id, 'integer')."");
172 
173  while($row = $ilDB->fetchObject($query))
174  {
175  $path = $this->getMailPath().'/'.$row->path.'/'.$a_filename;
176  }
177 
178  if(file_exists($path))
179  {
180  if(is_readable($path))
181  {
182  return $path;
183  }
184  return '';
185  }
186  return '';
187  }
195  function adoptAttachments($a_attachments,$a_mail_id)
196  {
197  if(is_array($a_attachments))
198  {
199  foreach($a_attachments as $file)
200  {
201  $path = $this->getAttachmentPath($file,$a_mail_id);
202  if(!copy($path,$this->getMailPath().'/'.$this->user_id.'_'.$file))
203  {
204  return "ERROR: $this->getMailPath().'/'.$this->user_id.'_'.$file cannot be created";
205  }
206  }
207  }
208  else
209  {
210  return "ARRAY REQUIRED";
211  }
212  return '';
213  }
214 
221  function checkReadWrite()
222  {
223  if(is_writable($this->mail_path) && is_readable($this->mail_path))
224  {
225  return true;
226  }
227  else
228  {
229  $this->ilias->raiseError("Mail directory is not readable/writable by webserver: ".$this->mail_path,$this->ilias->error_obj->FATAL);
230  }
231  }
237  function getUserFilesData()
238  {
239  return $files = $this->getUnsentFiles();
240  }
241 
248  function getUnsentFiles()
249  {
250  $files = array();
251  $dp = opendir($this->mail_path);
252 
253  while($file = readdir($dp))
254  {
255  if(is_dir($file))
256  {
257  continue;
258  }
259  list($uid,$rest) = explode('_',$file,2);
260  if($uid == $this->user_id)
261  {
262  if(!is_dir($this->mail_path.'/'.$file))
263  {
264  $files[] = array(
265  'name' => $rest,
266  'size' => filesize($this->mail_path.'/'.$file),
267  'ctime' => filectime($this->mail_path.'/'.$file)
268  );
269  }
270  }
271  }
272  closedir($dp);
273  return $files;
274  }
275 
282  public function storeAsAttachment($a_filename,$a_content)
283  {
284  if(strlen($a_content) >= $this->getUploadLimit())
285  {
286  return 1;
287  }
288 
289  $name = ilUtil::_sanitizeFilemame($a_filename);
290  $this->rotateFiles($this->getMailPath().'/'.$this->user_id.'_'.$name);
291 
292  $abs_path = $this->getMailPath().'/'.$this->user_id.'_'.$name;
293 
294  if(!$fp = @fopen($abs_path,'w+'))
295  {
296  return false;
297  }
298  if(@fwrite($fp,$a_content) === false)
299  {
300  @fclose($fp);
301  return false;
302  }
303  @fclose($fp);
304  return true;
305  }
306 
310  public function storeUploadedFile($file)
311  {
312  $file['name'] = ilUtil::_sanitizeFilemame($file['name']);
313 
314  $this->rotateFiles($this->getMailPath() . '/' . $this->user_id . '_' . $file['name']);
315 
317  $file['tmp_name'],
318  $file['name'],
319  $this->getMailPath() . '/' . $this->user_id . '_' . $file['name']
320  );
321  }
322 
329  function copyAttachmentFile($a_abs_path,$a_new_name)
330  {
331  @copy($a_abs_path,$this->getMailPath()."/".$this->user_id."_".$a_new_name);
332 
333  return true;
334  }
335 
336 
337 
345  function rotateFiles($a_path)
346  {
347  if(file_exists($a_path))
348  {
349  $this->rotateFiles($a_path.".old");
350  return rename($a_path,$a_path.'.old');
351  }
352  return true;
353  }
360  function unlinkFiles($a_filenames)
361  {
362  if(is_array($a_filenames))
363  {
364  foreach($a_filenames as $file)
365  {
366  if(!$this->unlinkFile($file))
367  {
368  return $file;
369  }
370  }
371  }
372  return '';
373  }
380  function unlinkFile($a_filename)
381  {
382  if(file_exists($this->mail_path.'/'.basename($this->user_id.'_'.$a_filename)))
383  {
384  return unlink($this->mail_path.'/'.basename($this->user_id.'_'.$a_filename));
385  }
386  }
393  function getAbsolutePath($a_path)
394  {
395  return $this->mail_path.'/'.$this->user_id.'_'.$a_path;
396  }
397 
405  function saveFiles($a_mail_id,$a_attachments)
406  {
407  if(!$a_mail_id)
408  {
409  return "INTERNAL HERE ERROR: No valid mail_id given";
410  }
411  if(is_array($a_attachments))
412  {
413  foreach($a_attachments as $attachment)
414  {
415  if(!$this->saveFile($a_mail_id,$attachment))
416  {
417  return $attachment;
418  }
419  }
420  }
421  else
422  {
423  return "ARRAY REQUIRED";
424  }
425  return '';
426  }
427 
428  public static function getStorage($a_mail_id, $a_usr_id)
429  {
430  static $fsstorage_cache = array();
431 
432  if(!is_object($fsstorage_cache[$a_mail_id][$a_usr_id]))
433  {
434  include_once 'Services/Mail/classes/class.ilFSStorageMail.php';
435  $fsstorage_cache[$a_mail_id][$a_usr_id] = new ilFSStorageMail($a_mail_id, $a_usr_id);
436  }
437 
438  return $fsstorage_cache[$a_mail_id][$a_usr_id];
439  }
440 
448  function saveFile($a_mail_id,$a_attachment)
449  {
450  $oStorage = self::getStorage($a_mail_id, $this->user_id);
451  $oStorage->create();
452  $storage_directory = $oStorage->getAbsolutePath();
453 
454  if(@!is_dir($storage_directory))
455  {
456  return false;
457  }
458 
459  return copy($this->mail_path.'/'.$this->user_id.'_'.$a_attachment,
460  $storage_directory.'/'.$a_attachment);
461  }
468  function checkFilesExist($a_files)
469  {
470  if($a_files)
471  {
472  foreach($a_files as $file)
473  {
474  if(!file_exists($this->mail_path.'/'.$this->user_id.'_'.$file))
475  {
476  return false;
477  }
478  }
479  return true;
480  }
481  return true;
482  }
490  function assignAttachmentsToDirectory($a_mail_id,$a_sent_mail_id)
491  {
492  global $ilDB;
493 
494 /* $query = "INSERT INTO mail_attachment ".
495  "SET mail_id = ".$ilDB->quote($a_mail_id).", ".
496  "path = ".$ilDB->quote($this->user_id."_".$a_sent_mail_id)." ";
497  $res = $this->ilias->db->query($query);
498 */
499 
500  $oStorage = self::getStorage($a_sent_mail_id, $this->user_id);
501  $res = $ilDB->manipulateF('
502  INSERT INTO mail_attachment
503  ( mail_id, path) VALUES (%s, %s)',
504  array('integer', 'text'),
505  array($a_mail_id, $oStorage->getRelativePathExMailDirectory())
506  );
507 
508  }
515  function deassignAttachmentFromDirectory($a_mail_id)
516  {
517  global $ilDB;
518  // IF IT'S THE LAST MAIL CONTAINING THESE ATTACHMENTS => DELETE ATTACHMENTS
519  $res = $ilDB->query("SELECT path FROM mail_attachment
520  WHERE mail_id = ".$ilDB->quote($a_mail_id,'integer'));
521 
522  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
523  {
524  $path = $row->path;
525  }
526  if($path)
527  {
528  $res = $ilDB->query("SELECT COUNT(mail_id) count_mail_id FROM mail_attachment
529  WHERE path = ".$ilDB->quote($path,'text')) ;
530 
531  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
532  {
533  $cnt_mail_id = $row->count_mail_id;
534  }
535  if($cnt_mail_id == 1)
536  {
538  }
539  }
540 
541  $res = $ilDB->manipulateF("DELETE FROM mail_attachment
542  WHERE mail_id = %s",
543  array('integer'),
544  array($a_mail_id));
545  return true;
546  }
547 
548  function __deleteAttachmentDirectory($a_rel_path)
549  {
550  ilUtil::delDir($this->mail_path."/".$a_rel_path);
551 
552  return true;
553  }
554 
558  protected function initAttachmentMaxUploadSize()
559  {
562  // Copy of ilFileInputGUI: begin
563  // get the value for the maximal uploadable filesize from the php.ini (if available)
564  $umf = ini_get("upload_max_filesize");
565  // get the value for the maximal post data from the php.ini (if available)
566  $pms = ini_get("post_max_size");
567 
568  //convert from short-string representation to "real" bytes
569  $multiplier_a = array("K" => 1024, "M" => 1024 * 1024, "G" => 1024 * 1024 * 1024);
570 
571  $umf_parts = preg_split("/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
572  $pms_parts = preg_split("/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
573 
574  if(count($umf_parts) == 2)
575  {
576  $umf = $umf_parts[0] * $multiplier_a[$umf_parts[1]];
577  }
578  if(count($pms_parts) == 2)
579  {
580  $pms = $pms_parts[0] * $multiplier_a[$pms_parts[1]];
581  }
582 
583  // use the smaller one as limit
584  $max_filesize = min($umf, $pms);
585 
586  if(!$max_filesize) $max_filesize = max($umf, $pms);
587  // Copy of ilFileInputGUI: end
588 
589  $this->mail_max_upload_file_size = $max_filesize;
590  }
591 
601  {
602  // XXX - This method is extremely slow. We should
603  // use a cache to speed it up, for example, we should
604  // store the disk space used in table mail_attachment.
605  global $ilDB, $lng;
606 
607  $mail_data_dir = ilUtil::getDataDir('filesystem').DIRECTORY_SEPARATOR."mail";
608 
609  $q = "SELECT path ".
610  "FROM mail_attachment ma ".
611  "JOIN mail m ON ma.mail_id=m.mail_id ".
612  "WHERE m.user_id = ".$ilDB->quote($user_id);
613  $result_set = $ilDB->query($q);
614  $size = 0;
615  $count = 0;
616  while($row = $result_set->fetchRow(DB_FETCHMODE_ASSOC))
617  {
618  $attachment_path = $mail_data_dir.DIRECTORY_SEPARATOR.$row['path'];
619  $attachment_size = ilUtil::dirsize($attachment_path);
620  if ($attachment_size != -1)
621  {
622  $size += $attachment_size;
623  }
624  $count++;
625  }
626  return array('count'=>$count, 'size'=>$size);
627  }
628 
632  public function onUserDelete()
633  {
637  global $ilDB;
638 
639  // Delete uploaded mail files which are not attached to any message
640  try
641  {
642  $iter = new RegexIterator(
643  new DirectoryIterator($this->getMailPath()), '/^'.$this->user_id.'_/'
644  );
645  foreach($iter as $file)
646  {
651  if($file->isFile())
652  {
653  @unlink($file->getPathname());
654  }
655  }
656  }
657  catch(Exception $e) { }
658 
659  // Select all files attached to messages which are not shared (... = 1) with other messages anymore
660  $query = '
661  SELECT DISTINCT(ma1.path)
662  FROM mail_attachment ma1
663  INNER JOIN mail
664  ON mail.mail_id = ma1.mail_id
665  WHERE mail.user_id = %s
666  AND (SELECT COUNT(tmp.path) FROM mail_attachment tmp WHERE tmp.path = ma1.path) = 1
667  ';
668  $res = $ilDB->queryF(
669  $query,
670  array('integer'),
671  array($this->user_id)
672  );
673  while($row = $ilDB->fetchAssoc($res))
674  {
675  try
676  {
677  $path = $this->getMailPath().DIRECTORY_SEPARATOR.$row['path'];
678  $iter = new RecursiveIteratorIterator(
679  new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::CHILD_FIRST
680  );
681  foreach($iter as $file)
682  {
687  if($file->isDir())
688  {
689  @rmdir($file->getPathname());
690  }
691  else
692  {
693  @unlink($file->getPathname());
694  }
695  }
696  @rmdir($path);
697  }
698  catch(Exception $e) { }
699  }
700 
701  // Delete each mail attachment row assigned to a message of the deleted user.
702  if($ilDB->getDBType() == 'mysql' || $ilDB->getDBType() == 'innodb')
703  {
704  $ilDB->manipulateF('
705  DELETE m1
706  FROM mail_attachment m1
707  INNER JOIN (
708  SELECT mail_attachment.mail_id
709  FROM mail
710  INNER JOIN mail_attachment
711  ON mail_attachment.mail_id = mail.mail_id
712  WHERE user_id = %s
713  ) m2
714  ON m2.mail_id = m1.mail_id
715  ',
716  array('integer'),
717  array($this->user_id)
718  );
719  }
720  else
721  {
722  // Oracle and Postgres
723  $ilDB->manipulateF('
724  DELETE FROM mail_attachment
725  WHERE mail_attachment.mail_id IN (
726  SELECT mail_attachment.mail_id
727  FROM mail
728  INNER JOIN mail_attachment
729  ON mail_attachment.mail_id = mail.mail_id
730  WHERE user_id = %s
731  )
732  ',
733  array('integer'),
734  array($this->user_id)
735  );
736  }
737  }
738 }
739 ?>