PHPDaemon\HTTPRequest\Input::parseMultipart PHP Method

parseMultipart() public method

Parses multipart
public parseMultipart ( ) : void
return void
    public function parseMultipart()
    {
        start:
        if ($this->frozen) {
            return;
        }
        if ($this->state === self::STATE_SEEKBOUNDARY) {
            // seek to the nearest boundary
            if (($p = $this->search('--' . $this->boundary . "\r\n")) === false) {
                return;
            }
            // we have found the nearest boundary at position $p
            if ($p > 0) {
                $extra = $this->read($p);
                if ($extra !== "\r\n") {
                    $this->log('parseBody(): SEEKBOUNDARY: got unexpected data before boundary (length = ' . $p . '): ' . Debug::exportBytes($extra));
                }
            }
            $this->drain(mb_orig_strlen($this->boundary) + 4);
            // drain
            $this->state = self::STATE_HEADERS;
        }
        if ($this->state === self::STATE_HEADERS) {
            // parse the part's headers
            $this->curPartDisp = false;
            $i = 0;
            do {
                $l = $this->readline(\EventBuffer::EOL_CRLF);
                if ($l === null) {
                    return;
                }
                if ($l === '') {
                    break;
                }
                $e = explode(':', $l, 2);
                $e[0] = strtr(strtoupper($e[0]), Generic::$htr);
                if (isset($e[1])) {
                    $e[1] = ltrim($e[1]);
                }
                if ($e[0] === 'CONTENT_DISPOSITION' && isset($e[1])) {
                    Generic::parseStr($e[1], $this->curPartDisp, true);
                    if (!isset($this->curPartDisp['form-data'])) {
                        break;
                    }
                    if (!isset($this->curPartDisp['name'])) {
                        break;
                    }
                    $this->curPartDisp['name'] = trim($this->curPartDisp['name'], '"');
                    $name = $this->curPartDisp['name'];
                    if (isset($this->curPartDisp['filename'])) {
                        $this->curPartDisp['filename'] = trim($this->curPartDisp['filename'], '"');
                        if (!ini_get('file_uploads')) {
                            break;
                        }
                        $this->req->attrs->files[$name] = ['name' => $this->curPartDisp['filename'], 'type' => '', 'tmp_name' => null, 'fp' => null, 'error' => UPLOAD_ERR_OK, 'size' => 0];
                        $this->curPart =& $this->req->attrs->files[$name];
                        $this->req->onUploadFileStart($this);
                        $this->state = self::STATE_UPLOAD;
                    } else {
                        $this->curPart =& $this->req->attrs->post[$name];
                        $this->curPart = '';
                    }
                } elseif ($e[0] === 'CONTENT_TYPE' && isset($e[1])) {
                    if (isset($this->curPartDisp['name']) && isset($this->curPartDisp['filename'])) {
                        $this->curPart['type'] = $e[1];
                    }
                }
            } while ($i++ < 10);
            if ($this->state === self::STATE_HEADERS) {
                $this->state = self::STATE_BODY;
            }
            goto start;
        }
        if ($this->state === self::STATE_BODY || $this->state === self::STATE_UPLOAD) {
            // process the body
            $chunkEnd1 = $this->search("\r\n--" . $this->boundary . "\r\n");
            $chunkEnd2 = $this->search("\r\n--" . $this->boundary . "--\r\n");
            if ($chunkEnd1 === false && $chunkEnd2 === false) {
                /*  we have only piece of Part in buffer */
                $l = $this->length - mb_orig_strlen($this->boundary) - 8;
                if ($l <= 0) {
                    return;
                }
                if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) {
                    $this->curPart .= $this->read($l);
                } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) {
                    $this->curPart['size'] += $l;
                    if ($this->req->getUploadMaxSize() < $this->curPart['size']) {
                        $this->curPart['error'] = UPLOAD_ERR_INI_SIZE;
                        $this->req->header('413 Request Entity Too Large');
                        $this->req->out('');
                        $this->req->finish();
                    } elseif ($this->maxFileSize && $this->maxFileSize < $this->curPart['size']) {
                        $this->curPart['error'] = UPLOAD_ERR_FORM_SIZE;
                        $this->req->header('413 Request Entity Too Large');
                        $this->req->out('');
                        $this->req->finish();
                    } else {
                        $this->curChunkSize = $l;
                        $this->req->onUploadFileChunk($this);
                    }
                }
            } else {
                /* we have entire Part in buffer */
                if ($chunkEnd1 === false) {
                    $l = $chunkEnd2;
                    $endOfMsg = true;
                } else {
                    $l = $chunkEnd1;
                    $endOfMsg = false;
                }
                if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) {
                    $this->curPart .= $this->read($l);
                    if ($this->curPartDisp['name'] === 'MAX_FILE_SIZE') {
                        $this->maxFileSize = (int) $this->curPart;
                    }
                } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) {
                    $this->curPart['size'] += $l;
                    $this->curChunkSize = $l;
                    $this->req->onUploadFileChunk($this, true);
                }
                $this->state = self::STATE_SEEKBOUNDARY;
                if ($endOfMsg) {
                    // end of whole message
                    $this->sendEOF();
                } else {
                    goto start;
                    // let's read the next part
                }
            }
        }
    }