0

I am trying to set restriction on uploading files to php server but thats not working except only txt file.

here is code.

$allowedExts = array("text", "doc","rtf");
$temp = explode(".", $_FILES["datafile"]["name"]);
$extension = end($temp);
if (isset($_FILES['datafile']['tmp_name'])) {
    if (($_FILES['datafile']['type'] == "text/plain") || ($_FILES['datafile']['type'] == "application/msword") || ($_FILES['datafile']['type'] == "application/rtf") && in_array($extension, $allowedExts)) {
            $lines = file($_FILES['datafile']['tmp_name'],FILE_IGNORE_NEW_LINES);
            $data = json_encode($lines);
            if (!empty($_FILES['datafile']['tmp_name'])) {
                $File = "<b>Selected File:</b> ".$_FILES['datafile']['name'];
            }else{
                $File = "No file selected";
            };

    } else {
        if (empty($_FILES['datafile']['tmp_name'])){
            $File = "<b>Selected File:</b> No file selected";
        }else {
            $File = "<b>Invalid File</b>";
        }
    }
}

So where is problem? when I choose other files .doc or .rtf the error occured $File = "<b>Invalid File</b>";.

any help would be appreciatd. thankx

5
Contributors
21
Replies
144
Views
3 Years
Discussion Span
Last Post by ultmt.punisher
0

Check logic in your line 5 again... Shouldn't it be ((w || x || y) && z) instead of ((w || x || y && z))?

And by the way, the "extension" for a text file is .txt, not .text.

Edited by Taywin

0

Don't find the extension with explode - use pathinfo()

Anyway, you need to check the mime type - extensions mean absolutely nothing.

You can read a file line by line (I believe we discussed this in a previous post), but you can validate the line data using all manner of functions, preg_match probably being the most useful.

$data = array();
$pattern = '/M\d{4}/';
foreach($lines as $line)
{
    if(preg_match($pattern, $line, $matches)) $data[] = $line;
}

Maybe something like that..

0

Instead of this...

$data = json_encode($lines);

Put the code I suggested and then

$jsondata = json_encode($data);

Obviously you'll have to change instances of $data to $jsondata from that point on OR call $data something else in the code I suggested.

Anyway, that was just an example of some simple screening or filtering.
There are a number of functions that you could use like array_map or array_filter along with built in filters (validate/sanitize function) - see the php manual for these.

NEVER trust input data, even if you're the one uploading it. The integrity of your whole system relies upon the fact that you can control what goes in to it.

0

I have tried this ,

$allowedExts = array("txt", "doc","rtf");
$temp = pathinfo($_FILES["datafile"]["name"]);
$extension = end($temp);
if (isset($_FILES['datafile']['tmp_name'])) {
    if ((($_FILES['datafile']['type'] == "text/plain") 
    || ($_FILES['datafile']['type'] == "application/msword") 
    || ($_FILES['datafile']['type'] == "application/rtf"))
    && in_array($extension, $allowedExts)) {
            $lines = file($_FILES['datafile']['tmp_name'],FILE_IGNORE_NEW_LINES);
            $data = array();
            $pattern = '/M\d{4}/';
            foreach($lines as $line)
            {
                if(preg_match($pattern, $line, $matches)) $data[] = $line;
            }
            $jsondata = json_encode($data);
            if (!empty($_FILES['datafile']['tmp_name'])) {
                $File = "<b>Selected File:</b> ".$_FILES['datafile']['name'];
            }else{
                $File = "No file selected";
            };

    } else {
        if (empty($_FILES['datafile']['tmp_name'])){
            $File = "<b>Selected File:</b> No file selected";
        }else {
            $File = "<b>Invalid File</b>";
        }
    }
}

and its not working at all, non of file is selceted.

0

As I said earlier, something is not right in your if-statement logic. Your extention type is wrong as well. No text file should ever have its extension as text but only txt. And also, you forgot the file extension could be case sensitive (Windows automatically handle this for you and that's why many people from the OS don't realize this)... Look below as an example to modify your script.

$allowedExts = array("txt", "doc", "rtf");
$temp = explode(".", $_FILES["datafile"]["name"]);
$extension = strtolower(end($temp));
if (isset($_FILES['datafile']['tmp_name'])) {
  if (($_FILES['datafile']['type']=="text/plain") ||
      ($_FILES['datafile']['type']=="application/msword") ||
      ($_FILES['datafile']['type']=="application/rtf")) &&
      in_array($extension, $allowedExts)) {
    ...
  }
  else {
    ...
  }
}

Your script will break if the selected file has no DOT in its file name. In other words, it does not work in Linux/Unix environment where a file may not have extention (uncommon but possible).

Edited by Taywin

0

nah , its still not working, and your code has the syntax error, not in mine.

here you forgot to put prenthisis if ((($_FILES['datafile']['type']=="text/plain") ||...

Edited by ultmt.punisher

0

I didn't test the script but wrote it off from the top of my head. Also I didn't mention anything about syntax but logic. Syntax is easily fixed, but logic is not because it can be hidden (and you do the scripting without any knowledge of it, pfff).

When you said "not working," you are simply not helping nor do your work right. A developer/programmer needs to be able to report bug/error correctly. Reporting bug/error requires 1)what is the input and its format, 2)what is the expected output and its format, 3)what is the test input, and 4)what is the test output (with error message detail).

In your case, you just reported the behavior. You should have an access to error message or log file. Look into that first. What is the error you get when you said "not working".

0

well I already mentioned the error that is occured on the load form,which comes from this statement Invalid File

... } else {
        if (empty($_FILES['datafile']['tmp_name'])){
            $File = "<b>Selected File:</b> No file selected";
        }else {
            $File = "<b>Invalid File</b>";
        }
    }

or what you mean by the error? should check to error from $_FILES["datafile"]["error"] ??

Edited by ultmt.punisher

1

if you var_dump or print_r this

$_FILES['datafile']['type']

what do you get?

Careful with the mime type as Diafol already brough up. A PHP file uploaded will give you "text/plain". By not knowing the exact extension of this file, it means a widely open back door.

Votes + Comments
your suggestion helped.
0

the print_r($_FILES['datafile']['type']); retuns file type of .doc and .rtf and .php is application/octet-stream what does this mean ? :(

0

Ok, I have used application/octet-stream for file types .rtf and .doc and its working now, but when I choose .rtf file and show results, its output looks like

{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
M-3106\par
{\*\generator Riched20 6.3.9600}\viewkind4\uc1 

M-3198\par
M-1267\par
}
M-9087\par

what does this mean and why its showing like this?

Edited by ultmt.punisher

0

Those are control words, used as the HTML tags to give formatting to the document. If you want to convert the above to plain-text then try this library:

Regarding application/octet-stream this is a generic mime used for binary data, you can get an .exe as a .doc with that mime, it depends on how the client browser will detect the uploaded file, it is not set by the server.

So, to perform an extended check don't rely only on the result of the $_FILES array, but use the Finfo library, which is embedded on PHP since version 5.3, here's an example:

$finfo = new finfo();
$mime = $finfo->file($_FILES['datafile']['tmp_name'], FILEINFO_MIME_TYPE);

switch($mime)
{
    case 'text/rtf':
    case 'application/rtf':

        # code for .rtf files

        break;

    case 'application/msword':

        # code for .doc files

        break;

    case 'text/plain':

        # code for .txt, .csv files

        break;

    default:

        echo 'Not allowed file';
}

Keep in mind that text/plain can also be a javascript or PHP file, so as suggested above, never trust client input. If you still have doubts, post your updated code.

Docs: http://php.net/manual/en/function.finfo-file.php

Edited by cereal

0

Where should I put your this code between

$allowedExts = array("txt", "doc","rtf");
$temp = explode(".", $_FILES["datafile"]["name"]);
$extension = end($temp);
if (isset($_FILES['datafile']['tmp_name'])) {
    if ((($_FILES['datafile']['type'] == "text/plain") 
    || ($_FILES['datafile']['type'] == "application/octet-stream") 
    || ($_FILES['datafile']['type'] == "application/octet-stream"))
    && in_array($extension, $allowedExts)) {
            $lines = file($_FILES['datafile']['tmp_name'],FILE_IGNORE_NEW_LINES);
            $data = json_encode($lines);
            if (!empty($_FILES['datafile']['tmp_name'])) {
                $File = "<b>Selected File:</b> ".$_FILES['datafile']['name'];
            }else{
                $File = "No file selected";
            };

    } else {
        if (empty($_FILES['datafile']['tmp_name'])){
            $File = "<b>Selected File:</b> No file selected";
        }else {
            $File = "<b>Invalid File</b>";
        }
    }
}

any help would b appreciated.

Edited by ultmt.punisher

0

After the first IF statement. Try this, is a rewrite of your above code:

<?php

    $allowedExts = array("txt", "doc", "rtf");
    $extension = pathinfo($_FILES['datafile']['name'], PATHINFO_EXTENSION);
    $File = '';
    $data = '';

    if (isset($_FILES['datafile']['tmp_name']) && in_array($extension, $allowedExts))
    {
        $finfo  = new finfo();
        $mime   = $finfo->file($_FILES['datafile']['tmp_name'], FILEINFO_MIME_TYPE);
        $lines  = array();

        switch($mime)
        {
            case 'application/rtf':
            case 'text/rtf':
            case 'application/msword':
            case 'text/plain':

                $lines = file($_FILES['datafile']['tmp_name'], FILE_IGNORE_NEW_LINES);

                # here you could filter / sanitize / convert the input

                break;

            default:

                $File = "<b>Invalid File</b>";
        }

        $data = json_encode($lines);
    }

    else
    {
        if (empty($_FILES['datafile']['tmp_name']))
        {
            $File = "<b>Selected File:</b> No file selected";
        }

        else
        {
            $File = "<b>Invalid File</b>";
        }
    }


    echo $data;
    echo $File;

I modified the switch cases to execute the same action, but if you want to apply different code for each file type just use the break statement as in my previous example, or simply use IF / ELSEIF statements.

Edited by cereal

0

what kind of code should I filter/sanitize or convert there?

because \pard\sl240\slmult1\f0\fs22\lang9 M-3100\par
M-0123\par
{\*\generator Riched20 6.3.9600}\viewkind4\uc1 this is just output of file.

so I should sanitize or filter these code after getting output?

I need output as sanitized.

Edited by ultmt.punisher

0

To convert try the previously suggested library, but I did few tests and I think it needs some fixes to get it to work. If you can access a terminal, then you could use an alternative approach: install a converter tool, get the output as text and then sanitize and save it.

For example, in linux you can use unrtf or unoconv, the former works fine but it applies a banner at the top of the file, there is a patch to remove it (the --quiet option) and few workarounds at terminal level:

the latter instead requires some components of libreoffice, and can work as server, which can be located in the same box of your web server or in a remote location.

So, my question is: will you use a linux server and if yes, can you install programs from a shell? If yes then you could use these suggested tools, otherwise wait for other suggestions.

And are you trying to convert the contents of these files to display them into HTML pages? If you explain us the reason, maybe we can suggest a better solution.

Once you have converted the files to plain text, you can sanitize it by applying the filter_var() function:

Bye!

0

I am not using unix or linux , and I am not trying to convert file content into html, I am just load the file into the browser and justshow the results as plain/text as it is in file.

thanks

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.