0

I'm using PHP to process uploads of .jpg, .gif, .jpeg, .png, .zip and .rar files to a upload/ directory. Only authorized users (with given password) are allowed to upload files. I have given the folder upload/ ownership www-data:www-data with appropriate access rights, so that is not the problem.

Uploading works great, as long as I am uploading through website directly on the server, which is hosting the whole site and is whose IP is associated with a certain domain. If I go to another computer and try to upload a zip file through website to server, I get an Invalid file message and nothing gets uploaded or stored in database. Here's my code:

$allowedExts = array("jpg", "jpeg", "gif", "png");
$extension = end(explode(".", $_FILES["fajl"]["name"]));
$allowedExts1 = array("zip", "rar");
$extension1 = end(explode(".", $_FILES["fajl"]["name"]));
if ((($_FILES["fajl"]["type"] == "image/gif")
    || ($_FILES["fajl"]["type"] == "image/jpeg")
|| ($_FILES["fajl"]["type"] == "image/png")
|| ($_FILES["fajl"]["type"] == "image/pjpeg"))
    && ($_FILES["fajl"]["size"] < 4000000)
    && in_array($extension, $allowedExts))
{
    if ($_FILES["fajl"]["error"] > 0)
    {
        echo "Return Code: " . $_FILES["fajl"]["error"] . "<br />";
    }
    else
    {
        echo "Upload: " . $_FILES["fajl"]["name"] . "<br />";
        echo "Type: " . $_FILES["fajl"]["type"] . "<br />";
        echo "Size: " . ($_FILES["fajl"]["size"] / 1024) . " KB<br />";
        echo "Temp file: " . $_FILES["fajl"]["tmp_name"] . "<br />";

        if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/upload/slike/' . $nav . '/' . $_FILES["fajl"]["name"]))
        {
            echo $_FILES["fajl"]["name"] . " already exists. ";
        }
        else
        {
            move_uploaded_file($_FILES["fajl"]["tmp_name"], $_SERVER['DOCUMENT_ROOT'] . '/upload/slike/' . $nav . '/' . $_FILES["fajl"]["name"]);
            echo "Stored in: " . $_SERVER['DOCUMENT_ROOT'] . '/upload/slike/' . $nav . '/' . $_FILES["fajl"]["name"];
            $pomlokacijasl='/upload/slike/' . $nav . '/' . $_FILES["fajl"]["name"];
            $query22 = "INSERT INTO `slike` (navig, slik) VALUES ('$nav', '$pomlokacijasl')";
            $query22 = mysql_query($query22) or trigger_error ("Error in query: $query22. ".mysql_error());
            mysql_free_result($query22);
        }
    }
}
else if ((($_FILES["fajl"]["type"] == "application/x-rar-compressed")
    || ($_FILES["fajl"]["type"] == "application/zip"))
    && ($_FILES["fajl"]["size"] < 25000000)
    && in_array($extension1, $allowedExts1)) 
{
    if ($_FILES["fajl"]["error"] > 0)
    {
        echo "Return Code: " . $_FILES["fajl"]["error"] . "<br />";
    }
    else
    {
        echo "Upload: " . $_FILES["fajl"]["name"] . "<br />";
        echo "Type: " . $_FILES["fajl"]["type"] . "<br />";
        echo "Size: " . ($_FILES["fajl"]["size"] / 1024) . " KB<br />";
        echo "Temp file: " . $_FILES["fajl"]["tmp_name"] . "<br />";

        if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/upload/datoteke/' . $nav . '/' . $_FILES["fajl"]["name"]))
        {
            echo $_FILES["fajl"]["name"] . " already exists. ";
        }
        else
        {
            move_uploaded_file($_FILES["fajl"]["tmp_name"], $_SERVER['DOCUMENT_ROOT'] . '/upload/datoteke/' . $nav . '/' . $_FILES["fajl"]["name"]);
            echo "Stored in: " . $_SERVER['DOCUMENT_ROOT'] . '/upload/datoteke/' . $nav . '/' . $_FILES["fajl"]["name"];
            $pomlokacijadat='/upload/datoteke/' . $nav . '/' . $_FILES["fajl"]["name"];
            $query22 = "INSERT INTO `datoteke` (navig, dat) VALUES ('$nav', '$pomlokacijadat')";
            $query22 = mysql_query($query22) or trigger_error ("Error in query: $query22. ".mysql_error());
            mysql_free_result($query22);
        }
    }
}
else
{
    echo "Invalid file";
}

How can I solve this? Will appending $_SERVER('DOCUMENT_ROOT') to $_SERVER('SERVER_NAME') work?

Kenny Linsky
  • 1,726
  • 3
  • 17
  • 41
Matjaž Lojen
  • 75
  • 2
  • 5
  • you want the html form on one server and the scipt posted to on another? –  Oct 12 '12 at 02:54
  • You should be getting your extensions like: `$ext = pathinfo($_FILES["fajl"]["name"], PATHINFO_EXTENSION);` and you should run it through [`strtolower()`](http://php.net/manual/en/function.strtolower.php) since image.JPG will be considered an `Invalid file` with your current code. – Kenny Linsky Oct 12 '12 at 03:18
  • Nope, I dont want anything like that. Both html form and php script are in the same .php file. UPDATE: Uploading pictures (.jpg, .gif, .jpeg, .png) files from another machine works, but uploading .zip files does not work and I don't know why. Uploading .zip files only works from the same machine. I thought the problem was somehow related to $_SERVER('DOCUMENT_ROOT') variable, but that is not the case. – Matjaž Lojen Oct 12 '12 at 03:20
  • The idea is that if uploaded file is a picture, it gets uploaded into /upload/slike/(some number), and if uploaded file is .zip it should get uploaded to /upload/datoteke/(some number). And the problem is, that .zip files get recognized as such and properly uploaded only from the machine that is the server, If I go to another computer and try to upload a .zip file it does not work and I dont know why. – Matjaž Lojen Oct 12 '12 at 03:20
  • Don't just `echo "Invalid file"`. Have it display useful information e.g. `echo $_FILES["fajl"]["name"] . " is an invalid file of type " . $_FILES["fajl"]["type"]`. – Kenny Linsky Oct 12 '12 at 03:21
  • @Kenny: So, $ext = pathinfo($_FILES["fajl"]["name"], PATHINFO_EXTENSION); WILL DO THE TRICK? – Matjaž Lojen Oct 12 '12 at 03:22
  • Because, I tried to upload, for example, Winzip.zip (NOT .ZIP or anything...). – Matjaž Lojen Oct 12 '12 at 03:24
  • `$ext = strtolower(end(explode(".", $_FILES["fajl"]["name"])));` will solve the problem of people not being able to upload image.JPG or files.ZiP, because the extension is case-sensitive. Using `pathinfo()` is just cleaner. – Kenny Linsky Oct 12 '12 at 03:24
  • just put a `var_dump($̲FILES)` in there and see what’s going on. – Chronial Oct 12 '12 at 03:25
  • array(1) { ["fajl"]=> array(5) { ["name"]=> string(11) "rapidpi.zip" ["type"]=> string(28) "application/x-zip-compressed" ["tmp_name"]=> string(14) "/tmp/phpp6vACk" ["error"]=> int(0) ["size"]=> int(3140023) } } – Matjaž Lojen Oct 12 '12 at 03:41
  • SO, I guess i should put "application/x-zip-compressed" instead into || ($_FILES["fajl"]["type"] == "application/zip"))?? – Matjaž Lojen Oct 12 '12 at 03:43

1 Answers1

2

Your MIME type check is excluding some valid types for zip files. It varies by browser, but the most common types are:

application/zip   
application/x-zip
application/octet-stream
application/x-zip-compressed

You should allow all of those in your check. To match the rest of your code, make it something like:

$allowedCompressedTypes = array("application/x-rar-compressed", "application/zip", "application/x-zip", "application/octet-stream", "application/x-zip-compressed");

else if (in_array($_FILES["fajl"]["type"], $allowedCompressedTypes)
    && ($_FILES["fajl"]["size"] < 25000000)
    && in_array($extension1, $allowedExts1)) {
Kenny Linsky
  • 1,726
  • 3
  • 17
  • 41
  • Which are all valid types for a .rar file? Are they the same? – Matjaž Lojen Oct 12 '12 at 04:08
  • @MatjažLojen According to: [.rar, .zip files MIME Type](http://stackoverflow.com/a/7027582/1090474) the RAR MIME type can either be `application/x-rar-compressed` or `application/octet-stream` so the array in my answer will work, since it includes both. `application/x-rar-compressed` for the RAR and `application/octet-stream` works for both RAR and ZIP. – Kenny Linsky Oct 12 '12 at 04:13