Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File name too long when parsing attachments #45

Closed
speller opened this issue Apr 15, 2016 · 7 comments
Closed

File name too long when parsing attachments #45

speller opened this issue Apr 15, 2016 · 7 comments

Comments

@speller
Copy link

speller commented Apr 15, 2016

I have the following repeated error when parsing email:

    [exception] => [object] (RuntimeException: fopen(/tmp/29810-1/=_utf-8_Q_=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8_= =_utf-8_Q_=D1=80=D0=BE=D0=B2=D0=BA=D0=B0_=D0=B7=D0=B0_= =_utf-8_Q_=D0=BA=D0=B0=D0=B7=D0=B0_=D0=BF=D0=BE=D0=BA_= =_utf-8_Q_=D1=83=D0=BF=D0=B0=D1=82=D0=B5=D0=BB=D1=8F__= =_utf-8_Q_=E2=84=96_=D0=A6=D0=9100000491_=D0=BE=D1=82_23=2E01=2E2012=2Ex_= =_utf-8_Q_ls_=): failed to open stream: File name too long on vendor/zetacomponents/mail/src/parser/parts/file_parser.php:170 at src/Amayama/Bootstrap.php:163:
#  13 : [internal function] Amayama\Bootstrap->errorHandler(2, 'fopen(/tmp/29810-1/=_utf-8_Q_=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8_= =_utf-8_Q_=D1=80=D0=BE=D0=B2=D0=BA=D0=B0_=D0=B7=D0=B0_= =_utf-8_Q_=D0=BA=D0=B0=D0=B7=D0=B0_=D0=BF=D0=BE=D0=BA_= =_utf-8_Q_=D1=83=D0=BF=D0=B0=D1=82=D0=B5=D0=BB=D1=8F__= =_utf-8_Q_=E2=84=96_=D0=A6=D0=9100000491_=D0=BE=D1=82_23=2E01=2E2012=2Ex_= =_utf-8_Q_ls_=): failed to open stream: File name too long', 'vendor/zetacomponents/mail/src/parser/parts/file_parser.php', 170, array[size:2])
#  12 : file_parser.php:170 fopen('/tmp/29810-1/=_utf-8_Q_=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8_= =_utf-8_Q_=D1=80=D0=BE=D0=B2=D0=BA=D0=B0_=D0=B7=D0=B0_= =_utf-8_Q_=D0=BA=D0=B0=D0=B7=D0=B0_=D0=BF=D0=BE=D0=BA_= =_utf-8_Q_=D1=83=D0=BF=D0=B0=D1=82=D0=B5=D0=BB=D1=8F__= =_utf-8_Q_=E2=84=96_=D0=A6=D0=9100000491_=D0=BE=D1=82_23=2E01=2E2012=2Ex_= =_utf-8_Q_ls_=', 'w')
#  11 : file_parser.php:142 ezcMailFileParser->openFile('=_utf-8_Q_=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8_= =_utf-8_Q_=D1=80=D0=BE=D0=B2=D0=BA=D0=B0_=D0=B7=D0=B0_= =_utf-8_Q_=D0=BA=D0=B0=D0=B7=D0=B0_=D0=BF=D0=BE=D0=BA_= =_utf-8_Q_=D1=83=D0=BF=D0=B0=D1=82=D0=B5=D0=BB=D1=8F__= =_utf-8_Q_=E2=84=96_=D0=A6=D0=9100000491_=D0=BE=D1=82_23=2E01=2E2012=2Ex_= =_utf-8_Q_ls_=')
#  10 : part_parser.php:150 ezcMailFileParser->__construct('application', 'octet-stream', [object] (ezcMailHeadersHolder))
#   9 : multipart_parser.php:184 ezcMailPartParser::createPartParserForHeaders([object] (ezcMailHeadersHolder))
#   8 : rfc822_parser.php:118 ezcMailMultipartParser->parseBody('
')
#   7 : rfc822_digest_parser.php:81 ezcMailRfc822Parser->parseBody('
')
#   6 : multipart_parser.php:196 ezcMailRfc822DigestParser->parseBody('
')
#   5 : rfc822_parser.php:118 ezcMailMultipartParser->parseBody('
')
#   4 : parser.php:252 ezcMailRfc822Parser->parseBody('
')
#   3 : ImportEmail.php:167 ezcMailParser->parseMail([object] (ezcMailVariableSet))

Please fix attachment file handling.

@speller
Copy link
Author

speller commented Feb 20, 2018

Any new on this issue?

@derickr
Copy link
Member

derickr commented Feb 20, 2018

Sorry, must have missed this. Can you provide the source of the email, or, even better, add a PR with a test case?

@speller
Copy link
Author

speller commented Mar 20, 2018

Hi @derickr , I've solved this in my fork using this patch:

diff --git a/src/parser/parts/file_parser.php b/src/parser/parts/file_parser.php
index 553172b..4143b35 100644
--- a/src/parser/parts/file_parser.php
+++ b/src/parser/parts/file_parser.php
@@ -165,10 +165,16 @@ class ezcMailFileParser extends ezcMailPartParser
 
         // remove the directory and the file when PHP shuts down
         ezcMailParserShutdownHandler::registerForRemoval( $dirName );
+
+        // If we have very long filename close to fs limit - truncate it to 250 symbols
+        if ( mb_strlen( $fileName ) > 250 ) {
+            $fileName = mb_substr($fileName, 0, 250);
+        }
+
         $this->fileName = $dirName . $fileName;
 
         $fp = fopen( $this->fileName, 'w' );
-        if ( $this->fp === false )
+        if ( $fp === false )
         {
             throw new ezcBaseFileNotFoundException( $this->fileName );
         }

I don't have test email, sorry.

@derickr
Copy link
Member

derickr commented Jan 8, 2020

Is this still a live issue for you?

@PHPGangsta
Copy link
Contributor

PHPGangsta commented Jan 31, 2020

I'm using an old version of this library, but I have the same problem. If you use the filename of a user-provided email attachment, it might be too long.

One solution is to cut it to 250 characters, like @speller does.

Why are we trying to use the original filename (which is user-provided data)? We have to extract it (from "Content-Disposition" or "Content-Type"), it has to be cleaned by "unsafe characters", and then we still might have the problem that filenames are too long.
Or the filename is empty: For example, if you extract a filename "[]" from a header, and then you remove unsafe characters, the string is empty at the end. Creating that file with fopen() will fail. Unsafe chars are not removed, but replaced by underscores, "[]" is not a problem. But other unsafe chars are problematic, for example a horizontal tab. The blacklist of unsafe chars in https://github.com/zetacomponents/Mail/blob/master/src/parser/parts/file_parser.php#L145 is too short. Either a whitelist would be a lot better, or not using user-provided-data at all . See my unit tests below.

Why not just use a random filename? As far as I can see, the filename is not important. Maybe this code solves all problems?

$fileName = uniqid('zetacomponents_tmp_mail_file_', true);

You can remove 20 lines of code, the filename is unique, no user-data involved, it's not too long, it's not too short, and everybody is happy :-)

@derickr
Copy link
Member

derickr commented Jun 13, 2020

I've fixed this as part of #83.

@derickr derickr closed this as completed Jun 13, 2020
@PHPGangsta
Copy link
Contributor

PHPGangsta commented Jun 13, 2020

Hi @derickr ,

Thanks for the commit, but I think the problem is not fixed yet.

I just ran the tests on my Windows machine, and I got:

ezcBaseFileNotFoundException : The file 'C:\Users\Michael\AppData\Local\Temp\3224-27/ ' could not be found.
 D:\zetacomponents\Mail\src\parser\parts\file_parser.php:183
 D:\zetacomponents\Mail\src\parser\parts\file_parser.php:152
 D:\zetacomponents\Mail\src\parser\interfaces\part_parser.php:150
 D:\zetacomponents\Mail\src\parser\parts\multipart_parser.php:184
 D:\zetacomponents\Mail\src\parser\parts\rfc822_parser.php:118
 D:\zetacomponents\Mail\src\parser\parser.php:252
 D:\zetacomponents\Mail\tests\parser\parser_test.php:916

The space in the test "testVarious13" still is not working.
I did not test it, but I also guess that a filename of "." or ".." would not work.

You are now using a whitelist:
$fileName = preg_replace( '/[^A-Za-z0-9-. ]/', '_', $fileName );
But dots and spaces can be problematic, for example "." or ".." on Linux and Windows might result in problems.

White searching for "allowed filenames on Windows" I found this:
"For example, spaces and dots are valid filename characters, but names composed only of those characters are forbidden"

My suggestion is still: Don't use the user-provided string, and just generate a random filename like this for example:
$fileName = uniqid('zetacomponents_tmp_mail_file_', true);

Or you also have to remove the dot and the space from the character whitelist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants