19 declare(strict_types=1);
    43         if (!defined(
'MAILPATH')) {
    44             define(
'MAILPATH', 
'mail');
    48         $this->
ilias = $DIC[
'ilias'];
    51         $this->db = $DIC->database();
    52         $this->tmpDirectory = $DIC->filesystem()->temp();
    53         $this->storageDirectory = $DIC->filesystem()->storage();
    60         if (is_writable($this->
getPath())
    76         $max_size = $this->
ilias->getSetting(
'mail_maxsize_attach', 
'');
    77         if ($max_size === 
'') {
    81         return (
float) $this->
ilias->getSetting(
'mail_maxsize_attach', 
'0') * 1024;
    91         return $this->mail_path . 
'/' . $this->user_id . 
'_';
   100         $res = $this->db->queryF(
   101             "SELECT path FROM mail_attachment WHERE mail_id = %s",
   106         if (1 !== $this->db->numRows(
$res)) {
   110         $row = $this->db->fetchAssoc(
$res);
   112         $relativePath = $row[
'path'];
   116         foreach ($files as $file) {
   117             if ($file[
'type'] === 
'file' && md5($file[
'entry']) === $md5FileHash) {
   119                     'path' => $this->
getMailPath() . 
'/' . $relativePath . 
'/' . $file[
'entry'],
   120                     'filename' => $file[
'entry'],
   131         $query = $this->db->query(
   132             "SELECT path FROM mail_attachment WHERE mail_id = " . $this->db->quote($mailId, 
'integer')
   135         while ($row = $this->db->fetchObject($query)) {
   146         if (is_readable(
$path)) {
   160         foreach ($a_attachments as $file) {
   162             if (!copy(
$path, $this->
getMailPath() . 
'/' . $this->user_id . 
'_' . $file)) {
   163                 return 'ERROR: ' . $this->
getMailPath() . 
'/' . $this->user_id . 
'_' . $file . 
' cannot be created';
   172         if (is_writable($this->mail_path) && is_readable($this->mail_path)) {
   176         $this->
ilias->raiseError(
   177             "Mail directory is not readable/writable by webserver: " .
   179             $this->
ilias->error_obj->FATAL
   190         return $this->getUnsentFiles();
   196     private function getUnsentFiles(): array
   200         $iter = 
new RegexIterator(
new DirectoryIterator($this->mail_path), 
"/^{$this->user_id}_(.+)$/");
   201         foreach ($iter as $file) {
   203             if (!$file->isFile()) {
   207             [$uid, $rest] = explode(
'_', $file->getFilename(), 2);
   208             if ($uid === (
string) $this->user_id) {
   211                     'size' => $file->getSize(),
   212                     'ctime' => $file->getCTime(),
   225                     'Mail upload limit reached for user with id %s',
   234         $abs_path = $this->
getMailPath() . 
'/' . $this->user_id . 
'_' . $name;
   236         $fp = fopen($abs_path, 
'wb+');
   237         if (!is_resource($fp)) {
   240                     'Could not read file: %s',
   246         if (fwrite($fp, $a_content) === 
false) {
   250                     'Could not write file: %s',
   273             $this->
getMailPath() . 
'/' . $this->user_id . 
'_' . $sanitized_filename
   276         return $sanitized_filename;
   284         @copy($a_abs_path, $this->
getMailPath() . 
"/" . $this->user_id . 
"_" . $a_new_name);
   291         if (is_file($a_path)) {
   305         foreach ($a_filenames as $file) {
   316         if (is_file($this->mail_path . 
'/' . basename($this->user_id . 
'_' . $a_filename))) {
   317             return unlink($this->mail_path . 
'/' . basename($this->user_id . 
'_' . $a_filename));
   337     public function saveFiles(
int $a_mail_id, array $a_attachments): void
   339         if (!is_numeric($a_mail_id) || $a_mail_id < 1) {
   343         foreach ($a_attachments as $attachment) {
   344             $this->
saveFile($a_mail_id, $attachment);
   350         static $fsstorage_cache = [];
   352         $fsstorage_cache[$a_mail_id][$a_usr_id] = 
new ilFSStorageMail($a_mail_id, $a_usr_id);
   354         return $fsstorage_cache[$a_mail_id][$a_usr_id];
   360     public function saveFile(
int $a_mail_id, 
string $a_attachment): bool
   362         $oStorage = self::getStorage($a_mail_id, $this->user_id);
   364         $storage_directory = $oStorage->getAbsolutePath();
   366         if (!is_dir($storage_directory)) {
   371             $this->mail_path . 
'/' . $this->user_id . 
'_' . $a_attachment,
   372             $storage_directory . 
'/' . $a_attachment
   381         if ($a_files !== []) {
   382             foreach ($a_files as $file) {
   383                 if (!is_file($this->mail_path . 
'/' . $this->user_id . 
'_' . $file)) {
   396         $oStorage = self::getStorage($a_sent_mail_id, $this->user_id);
   399                         INSERT INTO mail_attachment    400                         ( mail_id, path) VALUES (%s, %s)',
   402             [$a_mail_id, $oStorage->getRelativePathExMailDirectory()]
   411             'SELECT path FROM mail_attachment WHERE mail_id = ' .
   412             $ilDB->quote($a_mail_id, 
'integer')
   417             $path = (string) $row->path;
   422                 'SELECT COUNT(mail_id) count_mail_id FROM mail_attachment WHERE path = ' .
   423                 $ilDB->quote(
$path, 
'text')
   428                 $cnt_mail_id = (
int) $row->count_mail_id;
   431             if ($cnt_mail_id === 1) {
   437             'DELETE FROM mail_attachment WHERE mail_id = %s',
   456         $umf = ini_get(
"upload_max_filesize");
   458         $pms = ini_get(
"post_max_size");
   461         $multiplier_a = [
"K" => 1024, 
"M" => 1024 * 1024, 
"G" => 1024 * 1024 * 1024];
   463         $umf_parts = preg_split(
   467             PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
   469         $pms_parts = preg_split(
   473             PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
   476         if ((is_countable($umf_parts) ? count($umf_parts) : 0) === 2) {
   477             $umf = (float) $umf_parts[0] * $multiplier_a[$umf_parts[1]];
   479         if ((is_countable($pms_parts) ? count($pms_parts) : 0) === 2) {
   480             $pms = (float) $pms_parts[0] * $multiplier_a[$pms_parts[1]];
   484         $max_filesize = min($umf, $pms);
   486         if (!$max_filesize) {
   487             $max_filesize = max($umf, $pms);
   490         $this->mail_max_upload_file_size = (
int) $max_filesize;
   493     public function onUserDelete(): 
void   502             $iter = 
new RegexIterator(
   504                 '/^' . $this->user_id . 
'_/'   506             foreach ($iter as $file) {
   511                 if ($file->isFile()) {
   512                     @unlink($file->getPathname());
   520                         SELECT DISTINCT(ma1.path)   521                         FROM mail_attachment ma1   523                                 ON mail.mail_id = ma1.mail_id   524                         WHERE mail.user_id = %s   525                         AND (SELECT COUNT(tmp.path) FROM mail_attachment tmp WHERE tmp.path = ma1.path) = 1   527         $res = $ilDB->queryF(
   532         while ($row = $ilDB->fetchAssoc(
$res)) {
   537                     RecursiveIteratorIterator::CHILD_FIRST
   539                 foreach ($iter as $file) {
   544                     if ($file->isDir()) {
   545                         @rmdir($file->getPathname());
   547                         @unlink($file->getPathname());
   563                                         WHERE mail.user_id = %s AND mail.mail_id = mail_attachment.mail_id   581         bool $isDraft = 
false   592         if ($downloadFilename === 
'') {
   593             $downloadFilename = 
'attachments';
   597         $relativeProcessingDirectory = basename($processingDirectory);
   599         $absoluteZipDirectory = $processingDirectory . 
'/' . $downloadFilename;
   600         $relativeZipDirectory = $relativeProcessingDirectory . 
'/' . $downloadFilename;
   602         $this->tmpDirectory->createDir($relativeZipDirectory);
   604         foreach ($files as $fileName) {
   606                 $source = str_replace(
   615             $source = str_replace(
'//', 
'/', $source);
   616             if (!$this->storageDirectory->has($source)) {
   620             $target = $relativeZipDirectory . 
'/' . $fileName;
   622             $stream = $this->storageDirectory->readStream($source);
   623             $this->tmpDirectory->writeStream($target, $stream);
   626         $pathToZipFile = $processingDirectory . 
'/' . $downloadFilename . 
'.zip';
   629         $this->tmpDirectory->deleteDir($relativeZipDirectory);
   632             $processingDirectory . 
'/' . $downloadFilename . 
'.zip',
 getAttachmentsTotalSizeLimit()
 
getAttachmentPathAndFilenameByMd5Hash(string $md5FileHash, int $mailId)
 
Filesystem $storageDirectory
 
storeAsAttachment(string $a_filename, string $a_content)
 
This class handles all operations on files (attachments) in directory ilias_data/mail. 
 
Class ChatMainBarProvider . 
 
adoptAttachments(array $a_attachments, int $a_mail_id)
Adopt attachments (in case of forwarding a mail) 
 
static getValidFilename(string $a_filename)
 
copyAttachmentFile(string $a_abs_path, string $a_new_name)
Copy files in mail directory. 
 
static getASCIIFilename(string $a_filename)
 
getAttachmentPathByMailId(int $mailId)
 
static getStorage(int $a_mail_id, int $a_usr_id)
 
unlinkFile(string $a_filename)
 
static deliverFileAttached(string $path_to_file, ?string $download_file_name=null, ?string $mime_type=null, bool $delete_file=false)
 
assignAttachmentsToDirectory(int $a_mail_id, int $a_sent_mail_id)
 
rotateFiles(string $a_path)
 
getAbsoluteAttachmentPoolPathByFilename(string $fileName)
Resolves a path for a passed filename in regards of a user's mail attachment pool, meaning attachments not being sent. 
 
deassignAttachmentFromDirectory(int $a_mail_id)
 
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively 
 
deliverAttachmentsAsZip(string $basename, int $mailId, array $files=[], bool $isDraft=false)
 
unlinkFiles(array $a_filenames)
 
header include for all ilias files. 
 
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory 
 
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file 
 
getAbsoluteAttachmentPoolPathPrefix()
 
static _sanitizeFilemame(string $a_filename)
 
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory. 
 
int $mail_max_upload_file_size
 
static zip(string $a_dir, string $a_file, bool $compress_content=false)
 
storeUploadedFile(array $file)
 
__construct(public int $user_id=0)
 
static rename(string $a_source, string $a_target)
 
saveFiles(int $a_mail_id, array $a_attachments)
Saves all attachment files in a specific mail directory .../mail/<calculated_path>/mail_<mail_id>_<us...
 
getAttachmentPath(string $a_filename, int $a_mail_id)
 
initAttachmentMaxUploadSize()
 
checkFilesExist(array $a_files)
 
saveFile(int $a_mail_id, string $a_attachment)
Save attachment file in a specific mail directory .../mail/<calculated_path>/mail_<mail_id>_<user_id>...
 
deleteAttachmentDirectory(string $a_rel_path)