X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=scripts%2Fmaildaemon.php;h=91c257adb451fd468af1a5da305beee297580c27;hb=ec83890bc242650b169a524c373f488bb652265c;hp=6d850751482d032845409c86fc9576b3a0b71afd;hpb=edbc0c665cc65875b4d14b79939233b1c9c06bb6;p=quix0rs-gnu-social.git diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index 6d85075148..91c257adb4 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -2,7 +2,7 @@ . */ -# Abort if called from a web server -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); -require_once(INSTALLDIR . '/lib/common.php'); +$helptext = <<parse_message($fname); + function handle_message($fname='php://stdin') + { + list($from, $to, $msg, $attachments) = $this->parse_message($fname); if (!$from || !$to || !$msg) { - $this->error(NULL, _('Could not parse message.')); + $this->error(null, _('Could not parse message.')); } - common_log(LOG_INFO, "Mail from $from to $to: " .substr($msg, 0, 20)); + common_log(LOG_INFO, "Mail from $from to $to with ".count($attachments) .' attachment(s): ' .substr($msg, 0, 20)); $user = $this->user_from($from); if (!$user) { $this->error($from, _('Not a registered user.')); @@ -63,18 +65,149 @@ class MailerDaemon { return true; } $msg = $this->cleanup_msg($msg); - $this->add_notice($user, $msg); + $msg = common_shorten_links($msg); + if (mb_strlen($msg) > 140) { + $this->error($from,_('That\'s too long. '. + 'Max notice size is 140 chars.')); + } + $fileRecords = array(); + foreach($attachments as $attachment){ + $mimetype = $this->getUploadedFileType($attachment); + $stream = stream_get_meta_data($attachment); + if (!$this->isRespectsQuota($user,filesize($stream['uri']))) { + die('error() should trigger an exception before reaching here.'); + } + $filename = $this->saveFile($user, $attachment,$mimetype); + + fclose($attachment); + + if (empty($filename)) { + $this->error($from,_('Couldn\'t save file.')); + } + + $fileRecord = $this->storeFile($filename, $mimetype); + $fileRecords[] = $fileRecord; + $fileurl = common_local_url('attachment', + array('attachment' => $fileRecord->id)); + + // not sure this is necessary -- Zach + $this->maybeAddRedir($fileRecord->id, $fileurl); + + $short_fileurl = common_shorten_url($fileurl); + $msg .= ' ' . $short_fileurl; + + if (mb_strlen($msg) > 140) { + $this->deleteFile($filename); + $this->error($from,_('Max notice size is 140 chars, including attachment URL.')); + } + + // Also, not sure this is necessary -- Zach + $this->maybeAddRedir($fileRecord->id, $short_fileurl); + } + + $err = $this->add_notice($user, $msg, $fileRecords); + if (is_string($err)) { + $this->error($from, $err); + return false; + } else { + return true; + } } - function error($from, $msg) { + function saveFile($user, $attachment, $mimetype) { + + $filename = File::filename($user->getProfile(), "email", $mimetype); + + $filepath = File::path($filename); + + $stream = stream_get_meta_data($attachment); + if (copy($stream['uri'], $filepath) && chmod($filepath,0664)) { + return $filename; + } else { + $this->error(null,_('File could not be moved to destination directory.' . $stream['uri'] . ' ' . $filepath)); + } + } + + function storeFile($filename, $mimetype) { + + $file = new File; + $file->filename = $filename; + + $file->url = File::url($filename); + + $filepath = File::path($filename); + + $file->size = filesize($filepath); + $file->date = time(); + $file->mimetype = $mimetype; + + $file_id = $file->insert(); + + if (!$file_id) { + common_log_db_error($file, "INSERT", __FILE__); + $this->error(null,_('There was a database error while saving your file. Please try again.')); + } + + return $file; + } + + function maybeAddRedir($file_id, $url) + { + $file_redir = File_redirection::staticGet('url', $url); + + if (empty($file_redir)) { + $file_redir = new File_redirection; + $file_redir->url = $url; + $file_redir->file_id = $file_id; + + $result = $file_redir->insert(); + + if (!$result) { + common_log_db_error($file_redir, "INSERT", __FILE__); + $this->error(null,_('There was a database error while saving your file. Please try again.')); + } + } + } + + function getUploadedFileType($fileHandle) { + require_once 'MIME/Type.php'; + + $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); + $cmd = common_config('attachments', 'filecommand'); + + $stream = stream_get_meta_data($fileHandle); + $filetype = MIME_Type::autoDetect($stream['uri']); + if (in_array($filetype, common_config('attachments', 'supported'))) { + return $filetype; + } + $media = MIME_Type::getMedia($filetype); + if ('application' !== $media) { + $hint = sprintf(_(' Try using another %s format.'), $media); + } else { + $hint = ''; + } + $this->error(null,sprintf( + _('%s is not a supported filetype on this server.'), $filetype) . $hint); + } + + function isRespectsQuota($user,$fileSize) { + $file = new File; + $ret = $file->isRespectsQuota($user,$fileSize); + if (true === $ret) return true; + $this->error(null,$ret); + } + + function error($from, $msg) + { file_put_contents("php://stderr", $msg . "\n"); exit(1); } - function user_from($from_hdr) { + function user_from($from_hdr) + { $froms = mailparse_rfc822_parse_addresses($from_hdr); if (!$froms) { - return NULL; + return null; } $from = $froms[0]; $addr = common_canonical_email($from['address']); @@ -85,7 +218,8 @@ class MailerDaemon { return $user; } - function user_match_to($user, $to_hdr) { + function user_match_to($user, $to_hdr) + { $incoming = $user->incomingemail; $tos = mailparse_rfc822_parse_addresses($to_hdr); foreach ($tos as $to) { @@ -96,7 +230,8 @@ class MailerDaemon { return false; } - function handle_command($user, $from, $msg) { + function handle_command($user, $from, $msg) + { $inter = new CommandInterpreter(); $cmd = $inter->handle_command($user, $msg); if ($cmd) { @@ -106,7 +241,8 @@ class MailerDaemon { return false; } - function respond($from, $to, $response) { + function respond($from, $to, $response) + { $headers['From'] = $to; $headers['To'] = $from; @@ -115,32 +251,44 @@ class MailerDaemon { return mail_send(array($from), $headers, $response); } - function log($level, $msg) { + function log($level, $msg) + { common_log($level, 'MailDaemon: '.$msg); } - function add_notice($user, $msg) { - // should test - // $msg_shortened = common_shorten_links($msg); - // if (mb_strlen($msg_shortened) > 140) ERROR and STOP + function add_notice($user, $msg, $fileRecords) + { $notice = Notice::saveNew($user->id, $msg, 'mail'); if (is_string($notice)) { $this->log(LOG_ERR, $notice); - return; + return $notice; + } + foreach($fileRecords as $fileRecord){ + $this->attachFile($notice, $fileRecord); } common_broadcast_notice($notice); $this->log(LOG_INFO, 'Added notice ' . $notice->id . ' from user ' . $user->nickname); + return true; + } + + function attachFile($notice, $filerec) + { + File_to_post::processNew($filerec->id, $notice->id); + + $this->maybeAddRedir($filerec->id, + common_local_url('file', array('notice' => $notice->id))); } - function parse_message($fname) { + function parse_message($fname) + { $contents = file_get_contents($fname); $parsed = Mail_mimeDecode::decode(array('input' => $contents, 'include_bodies' => true, 'decode_headers' => true, 'decode_bodies' => true)); if (!$parsed) { - return NULL; + return null; } $from = $parsed->headers['from']; @@ -149,28 +297,54 @@ class MailerDaemon { $type = $parsed->ctype_primary . '/' . $parsed->ctype_secondary; + $attachments = array(); + + $this->extract_part($parsed,$msg,$attachments); + + return array($from, $to, $msg, $attachments); + } + + function extract_part($parsed,&$msg,&$attachments){ if ($parsed->ctype_primary == 'multipart') { - foreach ($parsed->parts as $part) { - if ($part->ctype_primary == 'text' && - $part->ctype_secondary == 'plain') { - $msg = $part->body; - break; + if($parsed->ctype_secondary == 'alternative'){ + $altmsg = $this->extract_msg_from_multipart_alternative_part($parsed); + if(!empty($altmsg)) $msg = $altmsg; + }else{ + foreach($parsed->parts as $part){ + $this->extract_part($part,$msg,$attachments); } } - } else if ($type == 'text/plain') { + } else if ($parsed->ctype_primary == 'text' + && $parsed->ctype_secondary=='plain') { $msg = $parsed->body; - } else { - $this->unsupported_type($type); + if(strtolower($parsed->ctype_parameters['charset']) != "utf-8"){ + $msg = utf8_encode($msg); + } + }else if(!empty($parsed->body)){ + if(common_config('attachments', 'uploads')){ + //only save attachments if uploads are enabled + $attachment = tmpfile(); + fwrite($attachment, $parsed->body); + $attachments[] = $attachment; + } } + } - return array($from, $to, $msg); + function extract_msg_from_multipart_alternative_part($parsed){ + foreach ($parsed->parts as $part) { + $this->extract_part($part,$msg,$attachments); + } + //we don't want any attachments that are a result of this parsing + return $msg; } - function unsupported_type($type) { - $this->error(NULL, "Unsupported message type: " . $type); + function unsupported_type($type) + { + $this->error(null, "Unsupported message type: " . $type); } - function cleanup_msg($msg) { + function cleanup_msg($msg) + { $lines = explode("\n", $msg); $output = ''; @@ -211,5 +385,7 @@ class MailerDaemon { } } -$md = new MailerDaemon(); -$md->handle_message('php://stdin'); +if (common_config('emailpost', 'enabled')) { + $md = new MailerDaemon(); + $md->handle_message('php://stdin'); +}