Asked  8 Months ago    Answers:  5   Viewed   52 times

Hopefully someone here might have an answer to my question.

I have a basic form that contains simple fields, like name, number, email address etc and 1 file upload field.

I am trying to add some validation into my script that detects if the file is too large and then rejects the user back to the form to select/upload a smaller file.

My problem is, if a user selects a file that is bigger than my validation file size rule and larger than php.ini POST_MAX_SIZE/UPLOAD_MAX_FILESIZE and pushes submit, then PHP seems to try process the form only to fail on the POST_MAX_SIZE settings and then clears the entire $_POST array and returns nothing back to the form.

Is there a way around this? Surely if someone uploads something > than the max size configured in the php.ini then you can still get the rest of the $_POST data???

Here is my code.

<?php

   function validEmail($email)
    {
       $isValid = true;
       $atIndex = strrpos($email, "@");
       if (is_bool($atIndex) && !$atIndex)
       {
          $isValid = false;
       } else {
          $domain = substr($email, $atIndex+1);
          $local = substr($email, 0, $atIndex);
          $localLen = strlen($local);
          $domainLen = strlen($domain);

          if ($localLen < 1 || $localLen > 64)
          {
             // local part length exceeded
             $isValid = false;
          }
          else if ($domainLen < 1 || $domainLen > 255)
          {
             // domain part length exceeded
             $isValid = false;
          }
          else if ($local[0] == '.' || $local[$localLen-1] == '.')
          {
             // local part starts or ends with '.'
             $isValid = false;
          }
          else if (preg_match('/\.\./', $local))
          {
             // local part has two consecutive dots
             $isValid = false;
          }
          else if (!preg_match('/^[A-Za-z0-9\-\.]+$/', $domain))
          {
             // character not valid in domain part
             $isValid = false;
          }
          else if (preg_match('/\.\./', $domain))
          {
             // domain part has two consecutive dots
             $isValid = false;
          }
          else if
          (!preg_match('/^(\\.|[A-Za-z0-9!#%&`_=\/$'*+?^{}|~.-])+$/', str_replace("\\","",$local)))
          {
             // character not valid in local part unless 
             // local part is quoted
             if (!preg_match('/^"(\\"|[^"])+"$/', str_replace("\\","",$local)))
             {
                $isValid = false;
             }
          }

       }
       return $isValid;
    }

        //setup post variables
        @$name = htmlspecialchars(trim($_REQUEST['name'])); 
        @$emailCheck = htmlspecialchars(trim($_REQUEST['email']));
        @$organisation = htmlspecialchars(trim($_REQUEST['organisation']));
        @$title = htmlspecialchars(trim($_REQUEST['title']));
        @$phone = htmlspecialchars(trim($_REQUEST['phone']));
        @$location = htmlspecialchars(trim($_REQUEST['location']));
        @$description = htmlspecialchars(trim($_REQUEST['description']));
        @$fileError = 0;
        @$phoneError = "";

        //setup file upload handler
        $target_path = 'uploads/';
        $filename =  basename( @$_FILES['uploadedfile']['name']);
        $max_size = 8000000; // maximum file size (8mb in bytes) NB: php.ini max filesize upload is 10MB on test environment.
        $allowed_filetypes = Array(".pdf", ".doc", ".zip", ".txt", ".xls", ".docx", ".csv", ".rtf"); //put extensions in here that should be uploaded only.
        $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.

        if(!is_writable($target_path)) die('You cannot upload to the specified directory, please CHMOD it to 777.'); //Check if we can upload to the specified upload folder.


        //display form function
        function displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError)
        {
          //make $emailCheck global so function can get value from global scope.
          global $emailCheck;
          global $max_size;



          echo  '<form action="geodetic_form.php" method="post" name="contact" id="contact" enctype="multipart/form-data">'."n".
                '<fieldset>'."n".'<div>'."n";

          //name        
          echo '<label for="name"><span class="mandatory">*</span>Your name:</label>'."n".
                '<input type="text" name="name" id="name" class="inputText required" value="'. $name .'" />'."n";

                //check if name field is filled out
                if (isset($_REQUEST['submit']) && empty($name)) 
                {        
                  echo '<label for="name" class="error">Please enter your name.</label>'."n";
                }

           echo '</div>'."n". '<div>'."n";

           //Email     
           echo '<label for="email"><span class="mandatory">*</span>Your email:</label>'."n".
                '<input type="text" name="email" id="email" class="inputText required email" value="'. $emailCheck .'" />'."n";

               // check if email field is filled out and proper format   
                if (isset($_REQUEST['submit']) && validEmail($emailCheck) == false)
                {
                  echo '<label for="email" class="error">Invalid email address entered.</label>'."n";
                }

           echo '</div>'."n". '<div>'."n";

           //organisation     
           echo '<label for="phone">Organisation:</label>'."n".
                '<input type="text" name="organisation" id="organisation" class="inputText" value="'. $organisation .'" />'."n";
           echo '</div>'."n". '</fieldset>'."n".'<fieldset>'. "n" . '<div>'."n";

           //title     
           echo '<label for="phone">Title:</label>'."n".
                '<input type="text" name="title" id="title" class="inputText" value="'. $title .'" />'."n";        
           echo '</div>'."n". '</fieldset>'."n".'<fieldset>'. "n" . '<div>'."n";

          //phone     
           echo '<label for="phone"><span class="mandatory">*</span>Phone <br /><span class="small">(include area code)</span>:</label>'."n".
                '<input type="text" name="phone" id="phone" class="inputText required" value="'. $phone .'" />'."n";       

           // check if phone field is filled out that it has numbers and not characters
           if (isset($_REQUEST['submit']) && $phoneError == "true" && empty($phone)) echo '<label for="email" class="error">Please enter a valid phone number.</label>'."n";       

           echo '</div>'."n". '</fieldset>'."n".'<fieldset>'. "n" . '<div>'."n";

            //Location     
            echo '<label class="location" for="location"><span class="mandatory">*</span>Location:</label>'."n".
                 '<textarea name="location" id="location" class="required">'. $location .'</textarea>'."n";

            //check if message field is filled out
            if (isset($_REQUEST['submit']) && empty($_REQUEST['location'])) echo '<label for="location" class="error">This field is required.</label>'."n";

            echo '</div>'."n". '</fieldset>'."n".'<fieldset>'. "n" . '<div>'."n";

           //description     
           echo '<label class="description" for="description">Description:</label>'."n".
                '<textarea name="description" id="queryComments">'. $description .'</textarea>'."n";               
           echo '</div>'."n". '</fieldset>'."n".'<fieldset>'. "n" . '<div>'."n";

          //file upload
           echo '<label class="uploadedfile" for="uploadedfile">File:</label>'."n".
                '<input type="file" name="uploadedfile" id="uploadedfile" value="'. $filename .'" />'."n";

           // Check if the filetype is allowed, if not DIE and inform the user.   
           switch ($fileError)
           {
            case "1":
                echo '<label for="uploadedfile" class="error">The file you attempted to upload is not allowed.</label>';
            break;

            case "2":
                echo '<label for="uploadedfile" class="error">The file you attempted to upload is too large.</label>';
            break;
           }   
           echo '</div>'."n". '</fieldset>';

            //end of form
            echo '<div class="submit"><input type="submit" name="submit" value="Submit" id="submit"  /></div>'.
                 '<div class="clear"><p><br /></p></div>';
        } //end function

        //setup error validations
        if (isset($_REQUEST['submit']) && !empty($_REQUEST['phone']) && !is_numeric($_REQUEST['phone'])) $phoneError = "true";
        if (isset($_REQUEST['submit']) && $_FILES['uploadedfile']['error'] != 4 && !in_array($ext, $allowed_filetypes)) $fileError = 1;
        if (isset($_REQUEST['submit']) && $_FILES["uploadedfile"]["size"] > $max_size) $fileError = 2; echo "this condition " . $fileError; 

        $POST_MAX_SIZE = ini_get('post_max_size');
        $mul = substr($POST_MAX_SIZE, -1);

        $mul = ($mul == 'M' ? 1048576 : ($mul == 'K' ? 1024 : ($mul == 'G' ? 1073741824 : 1)));
        if ($_SERVER['CONTENT_LENGTH'] > $mul*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) echo "too big!!";
        echo $POST_MAX_SIZE;


        if(empty($name) || empty($phone) || empty($location) || validEmail($emailCheck) == false || $phoneError == "true" || $fileError != 0)
        {
            displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError);
          echo $fileError;
          echo "max size is: " .$max_size;
          echo "and file size is: " .  $_FILES["uploadedfile"]["size"];
          exit;
        } else {

            //copy file from temp to upload directory
            $path_of_uploaded_file = $target_path . $filename;
            $tmp_path = $_FILES["uploadedfile"]["tmp_name"];
            echo $tmp_path;
            echo "and file size is: " .  filesize($_FILES["uploadedfile"]["tmp_name"]);
            exit;
            if(is_uploaded_file($tmp_path))
            {
              if(!copy($tmp_path,$path_of_uploaded_file))
              {
                echo 'error while copying the uploaded file';
              }
            }

        //test debug stuff
            echo "sending email...";
            exit;


        }
        ?>

PHP is returning this error in the log: [29-Apr-2010 10:32:47] PHP Warning: POST Content-Length of 57885895 bytes exceeds the limit of 10485760 bytes in Unknown on line 0

Excuse all the debug stuff :)

FTR, I am running PHP 5.1.2 on IIS.

 Answers

63

PHP throws all the POST data away because there was no room to put it. There is nothing reliable to be had from only part of the data.

I would work around this problem by uploading the necessary files in a separate step, a different form. You can store the values already obtained in session, ensuring they are not lost because of excessive POST data.

Wednesday, March 31, 2021
 
Teno
answered 8 Months ago
86

You should point to your vendor/autoload.php at Settings | PHP | PHPUnit when using PHPUnit via Composer.

This blog post has all the details (with pictures) to successfully configure IDE for such scenario: http://confluence.jetbrains.com/display/PhpStorm/PHPUnit+Installation+via+Composer+in+PhpStorm

Related usability ticket: http://youtrack.jetbrains.com/issue/WI-18388

P.S. The WI-18388 ticket is already fixed in v8.0

Wednesday, March 31, 2021
 
ojrac
answered 8 Months ago
79

On Mac OS X environment variables available in Terminal and for the normal applications can be different, check the related question for the solution how to make them similar.

Note that this solution will not work on Mountain Lion (10.8).

Saturday, May 29, 2021
 
Nate
answered 5 Months ago
35

Your script seems fine. Please check your server configuration. Perhaps you exceed POST limits (set with post_max_size in php.ini)

Saturday, May 29, 2021
 
ericstumper
answered 5 Months ago
37

In certain cases a browser will automatically perform a preflight request to check the list of allowed methods or verbs before actually sending the reel one. You can see those within your browser's network tab. I guess in Postman you are directly sending the POST request while the pre-sent OPTIONS request should be the failing one.

Yii has a built-in action which is defined under the ActiveController class to respond to such requests. But in your case you are directly extending its parent controller instead so you'll need to manually define a similar action inside your controllers (or a parent one to them) responding to preflight requests:

public function actionOptions() 
{
    if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') {
        Yii::$app->getResponse()->setStatusCode(405);
    }

    $allowed_verbs = ['GET', 'POST', 'HEAD', 'OPTIONS'];
    Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed_verbs));
}

Also; as you are not using the built-in routing mechanism for REST; in your case you'll also need to manually define rules to that Options action: (edited version of the code from your comments)

'urlManager' => [ 
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [ 
        'POST <version:[w-]+>/users/verify' => '<version>/user/verify',
        'POST <version:[w-]+>/airtime' => '<version>/airtime/airtime',
        'POST <version:[w-]+>/bulk' => '<version>/routine/index',
        'POST <version:[w-]+>/contact' => '<version>/contact/index',

        // OPTTIONS URI ENDPOINTS
        'OPTIONS <version:[w-]+>/users/verify' => '<version>/user/options',
        'OPTIONS <version:[w-]+>/airtime' => '<version>/airtime/options',
        'OPTIONS <version:[w-]+>/bulk' => '<version>/routine/options',
        'OPTIONS <version:[w-]+>/contact' => '<version>/contact/options',
    ],
];
Sunday, August 29, 2021
 
NPE
answered 2 Months ago
NPE
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share