/** * @param string $requestString * @return wfWAFRequest */ public static function parseString($requestString) { if (!is_string($requestString)) { throw new InvalidArgumentException(__METHOD__ . ' expects a string for first parameter, recieved ' . gettype($requestString)); } if (version_compare(phpversion(), '5.3.0') > 0) { $class = get_called_class(); $request = new $class(); } else { $request = new self(); } $request->setAuth(array()); $request->setBody(array()); $request->setMd5Body(array()); $request->setCookies(array()); $request->setFileNames(array()); $request->setFiles(array()); $request->setHeaders(array()); $request->setHost(''); $request->setIP(''); $request->setMethod(''); $request->setPath(''); $request->setProtocol(''); $request->setQueryString(array()); $request->setMd5QueryString(array()); $request->setTimestamp(''); $request->setURI(''); list($headersString, $bodyString) = explode("\n\n", $requestString, 2); $headersString = trim($headersString); $bodyString = trim($bodyString); $headers = explode("\n", $headersString); // Assume first is method if (preg_match('/^([a-z]+) (.*?) HTTP\\/1.[0-9]/i', $headers[0], $matches)) { $request->setMethod($matches[1]); $uri = $matches[2]; $request->setUri($uri); if (($pos = wfWAFUtils::strpos($uri, '?')) !== false) { $queryString = wfWAFUtils::substr($uri, $pos + 1); parse_str($queryString, $queryStringArray); $request->setQueryString($queryStringArray); $path = wfWAFUtils::substr($uri, 0, $pos); $request->setPath($path); } else { $request->setPath($uri); } } $kvHeaders = array(); for ($i = 1; $i < count($headers); $i++) { $headerString = $headers[$i]; list($header, $headerValue) = explode(':', $headerString, 2); $header = trim($header); $headerValue = trim($headerValue); $kvHeaders[$header] = $headerValue; switch (wfWAFUtils::strtolower($header)) { case 'authorization': if (preg_match('/basic ([A-Za-z0-9\\+\\/=]+)/i', $headerValue, $matches)) { list($authUser, $authPass) = explode(':', base64_decode($matches[1]), 2); $auth['user'] = $authUser; $auth['password'] = $authPass; $request->setAuth($auth); } break; case 'host': $request->setHost($headerValue); break; case 'cookie': $cookieArray = array(); $cookies = str_replace('&', '%26', $headerValue); $cookies = preg_replace('/\\s*;\\s*/', '&', $cookies); parse_str($cookies, $cookieArray); $request->setCookies($cookieArray); break; } } $request->setHeaders($kvHeaders); if (wfWAFUtils::strlen($bodyString) > 0) { if (preg_match('/^multipart\\/form\\-data; boundary=(.*?)$/i', $request->getHeaders('Content-Type'), $boundaryMatches)) { $body = ''; $files = array(); $fileNames = array(); $boundary = $boundaryMatches[1]; $bodyChunks = explode("--{$boundary}", $bodyString); foreach ($bodyChunks as $chunk) { if (!$chunk || $chunk == '--') { continue; } list($chunkHeaders, $chunkData) = explode("\n\n", $chunk, 2); $chunkHeaders = explode("\n", $chunkHeaders); $param = array('value' => wfWAFUtils::substr($chunkData, 0, -1)); foreach ($chunkHeaders as $chunkHeader) { if (wfWAFUtils::strpos($chunkHeader, ':') !== false) { list($chunkHeaderKey, $chunkHeaderValue) = explode(':', $chunkHeader, 2); $chunkHeaderKey = trim($chunkHeaderKey); $chunkHeaderValue = trim($chunkHeaderValue); switch ($chunkHeaderKey) { case 'Content-Disposition': $dataAttributes = explode(';', $chunkHeaderValue); foreach ($dataAttributes as $attr) { $attr = trim($attr); if (preg_match('/^name="(.*?)"$/i', $attr, $attrMatch)) { $param['name'] = $attrMatch[1]; continue; } if (preg_match('/^filename="(.*?)"$/i', $attr, $attrMatch)) { $param['filename'] = $attrMatch[1]; continue; } } break; case 'Content-Type': $param['type'] = $chunkHeaderValue; break; } } } if (array_key_exists('name', $param)) { if (array_key_exists('filename', $param)) { $files[$param['name']] = array('name' => $param['filename'], 'type' => $param['type'], 'size' => wfWAFUtils::strlen($param['value']), 'content' => $param['value']); $fileNames[$param['name']] = $param['filename']; } else { $body .= urlencode($param['name']) . '=' . urlencode($param['value']) . '&'; } } } if ($body) { parse_str($body, $postBody); if (is_array($postBody)) { $request->setBody($postBody); } else { $request->setBody($body); } } if ($files) { $request->setFiles($files); } if ($fileNames) { $request->setFileNames($fileNames); } } else { parse_str($bodyString, $postBody); if (is_array($postBody)) { $request->setBody($postBody); } else { $request->setBody($bodyString); } } } return $request; }