}
// Sends a HTTP request (GET, POST, HEAD are currently supported)
-function sendHttpRequest ($requestType, $baseUrl, $requestData = array(), $removeHeader = FALSE) {
+function sendHttpRequest ($requestType, $baseUrl, $requestData = array(), $removeHeader = FALSE, $allowOnlyHttpOkay = TRUE) {
// Init response
$response = array();
// Start "detecting" the request type
switch ($requestType) {
case 'HEAD': // Send a HTTP/1.1 HEAD request
- $response = sendHeadRequest($baseUrl, $requestData);
+ $response = sendHttpHeadRequest($baseUrl, $requestData, $allowOnlyHttpOkay);
break;
case 'GET': // Send a HTTP/1.1 GET request
- $response = sendGetRequest($baseUrl, $requestData, $removeHeader);
+ $response = sendHttpGetRequest($baseUrl, $requestData, $removeHeader, $allowOnlyHttpOkay);
break;
case 'POST': // Send a HTTP/1.1 POST request
- $response = sendPostRequest($baseUrl, $requestData, $removeHeader);
+ $response = sendHttpPostRequest($baseUrl, $requestData, $removeHeader, $allowOnlyHttpOkay);
break;
default: // Unsupported HTTP request, this is really bad and needs fixing
}
// Sends a HEAD request
-function sendHeadRequest ($baseUrl, $requestData = array()) {
+function sendHttpHeadRequest ($baseUrl, $requestData = array(), $allowOnlyHttpOkay = TRUE) {
// Generate full GET URL
$getUrl = generateGetUrlFromBaseUrlData($baseUrl, $requestData);
+ //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getUrl=' . $getUrl);
// Is there http[s]:// in front of the URL?
if (isFullQualifiedUrl($getUrl)) {
$request .= getConfig('HTTP_EOL');
// Send the raw request
- $response = sendRawRequest($host, $request);
+ $response = sendRawRequest($host, $request, $allowOnlyHttpOkay);
// Return the result to the caller function
return $response;
}
// Send a GET request
-function sendGetRequest ($baseUrl, $requestData = array(), $removeHeader = FALSE) {
+function sendHttpGetRequest ($baseUrl, $requestData = array(), $removeHeader = FALSE, $allowOnlyHttpOkay = TRUE) {
// Generate full GET URL
$getUrl = generateGetUrlFromBaseUrlData($baseUrl, $requestData);
+ //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getUrl=' . $getUrl);
// Is there http[s]:// in front of the URL?
if (isFullQualifiedUrl($getUrl)) {
$request .= getConfig('HTTP_EOL');
// Send the raw request
- $response = sendRawRequest($host, $request);
+ $response = sendRawRequest($host, $request, $allowOnlyHttpOkay);
// Should we remove header lines?
if ($removeHeader === TRUE) {
}
// Send a POST request, sometimes even POST requests have no parameters
-function sendPostRequest ($baseUrl, $requestData = array(), $removeHeader = FALSE) {
+function sendHttpPostRequest ($baseUrl, $requestData = array(), $removeHeader = FALSE, $allowOnlyHttpOkay = TRUE) {
// Copy baseUrl to getUrl
$getUrl = $baseUrl;
$request .= $body;
// Send the raw request
- $response = sendRawRequest($host, $request);
+ $response = sendRawRequest($host, $request, $allowOnlyHttpOkay);
// Should we remove header lines?
if ($removeHeader === TRUE) {
}
// Sends a raw request (string) to given host (hostnames will be solved)
-function sendRawRequest ($host, $request) {
+function sendRawRequest ($host, $request, $allowOnlyHttpOkay = TRUE) {
//* DEBUG: */ die('host='.$host.',request=<pre>'.$request.'</pre>');
// Init errno and errdesc with 'all fine' values
$errno = '0';
$port = 80;
// Initialize array
- $response = array('', '', '');
+ $response = array();
// Default is non-broken HTTP server implementation
$GLOBALS['is_http_server_broken'] = FALSE;
if (!is_resource($resource)) {
// Failed!
logDebugMessage(__FUNCTION__, __LINE__, $errdesc . ' (' . $errno . ')');
- return $response;
+ return array('', '', '');
} elseif ((!stream_set_blocking($resource, 0)) || (!stream_set_timeout($resource, 1))) {
// Cannot set non-blocking mode or timeout
logDebugMessage(__FUNCTION__, __LINE__, socket_strerror(socket_last_error()));
- return $response;
+ return array('', '', '');
}
// Shall proxy be used?
// Get line from stream
$line = fgets($resource, 128);
- // Ignore empty lines because of non-blocking mode
- if (empty($line)) {
+ /*
+ * Ignore empty lines because of non-blocking mode, you cannot use
+ * empty() here as it would also see \r\n as "empty".
+ */
+ if (strlen($line) == 0) {
// uslepp a little to avoid 100% CPU load
usleep(10);
} // END - if
// Add it to response
- //* DEBUG: */ print 'line='.$line.'<br />';
+ //* DEBUG: */ print 'line(' . strlen($line) . ')='.$line.'<br />';
array_push($response, $line);
} // END - while
logDebugMessage(__FUNCTION__, __LINE__, 'Request took ' . (microtime(TRUE) - $start) . ' seconds and returned ' . count($response) . ' line(s).');
} // END - if
- // Skip first empty lines
- $resp = $response;
- foreach ($resp as $idx => $line) {
- // Trim space away
- $line = trim($line);
-
- // Is this line empty?
- if (empty($line)) {
- // Then remove it
- array_shift($response);
- } else {
- // Abort on first non-empty line
- break;
- }
- } // END - foreach
-
//* DEBUG: */ debugOutput('<strong>Request:</strong><pre>'.print_r($request, TRUE).'</pre>');
//* DEBUG: */ debugOutput('<strong>Response:</strong><pre>'.print_r($response, TRUE).'</pre>');
// Proxy agent found or something went wrong?
- if (!isset($response[0])) {
+ if (count($response) == 0) {
// No response, maybe timeout
$response = array('', '', '');
logDebugMessage(__FUNCTION__, __LINE__, 'Invalid empty response array, maybe timed out?');
} // END - if
// Was the request successfull?
- if ((!isInStringIgnoreCase('200 OK', $response[0])) || (empty($response[0]))) {
+ if ((!isHttpStatusOkay($response[0])) && ($allowOnlyHttpOkay === TRUE)) {
// Not found / access forbidden
logDebugMessage(__FUNCTION__, __LINE__, 'Unexpected status code ' . $response[0] . ' detected. "200 OK" was expected.');
$response = array('', '', '');
return $response;
}
+// Is HTTP status okay?
+function isHttpStatusOkay ($header) {
+ // Determine it
+ return in_array(strtoupper(trim($header)), array('HTTP/1.1 200 OK', 'HTTP/1.0 200 OK'));
+}
+
// Sets up a proxy tunnel for given hostname and through resource
function setupProxyTunnel ($host, $proxyHost, $port, $resource) {
// Initialize array
// Found!
$isChunked = TRUE;
break;
- } // END - if
+ } elseif (empty($line)) {
+ // Empty line found (header->body)
+ break;
+ }
} // END - foreach
+ // Save whole body
+ $body = removeHttpHeaderFromResponse($response);
+
// Is it chunked?
+ //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isChunked=' . intval($isChunked));
if ($isChunked === TRUE) {
+ // Make sure, that body is an array
+ assert(is_array($body));
+
// Good, we still have the HTTP headers in there, so we need to get rid
// of them temporarly
//* DEBUG: */ die('<pre>'.htmlentities(print_r(removeHttpHeaderFromResponse($response), TRUE)).'</pre>');
- $tempResponse = http_chunked_decode(implode('', removeHttpHeaderFromResponse($response)));
+ $tempResponse = http_chunked_decode(implode('', $body));
// We got a string back from http_chunked_decode(), so we need to convert it back to an array
- //* DEBUG: */ die('tempResponse['.strlen($tempResponse).']=<pre>'.replaceReturnNewLine(htmlentities($tempResponse)).'</pre>');
+ //* DEBUG: */ die('tempResponse['.strlen($tempResponse).'/'.gettype($tempResponse).']=<pre>'.replaceReturnNewLine(htmlentities($tempResponse)).'</pre>');
// Re-add the headers
- $response = merge_array($GLOBALS['http_headers'], stringToArray(PHP_EOL, $tempResponse));
- } // END - if
+ $response = mergeHttpHeadersWithBody($tempResponse);
+ } elseif (is_array($body)) {
+ /*
+ * Make sure the body is in one array element as many other functions
+ * get disturbed by it.
+ */
+
+ // Put all array elements from body together
+ $body = implode('', $body);
+
+ // Now merge the extracted headers + fixed body together
+ $response = mergeHttpHeadersWithBody($body);
+ }
// Return the unchunked array
return $response;
}
+// Merges HTTP header lines with given body (string)
+function mergeHttpHeadersWithBody ($body) {
+ // Add empty entry to mimic header->body
+ $GLOBALS['http_headers'][] = getConfig('HTTP_EOL');
+
+ // Make sure at least one header is there (which is still not valid but okay here)
+ assert((is_array($GLOBALS['http_headers'])) && (count($GLOBALS['http_headers']) > 0));
+
+ // Merge both together
+ return merge_array($GLOBALS['http_headers'], array(count($GLOBALS['http_headers']) => $body));
+}
+
// Removes HTTP header lines from a response array (e.g. output from send<Get|Post>Request() )
function removeHttpHeaderFromResponse ($response) {
// Save headers for later usage
// Remove line
array_shift($response2);
- // Add full line to temporary global array
- array_push($GLOBALS['http_headers'], $line);
-
// Trim it for testing
$lineTest = trim($line);
// Then stop here
break;
} // END - if
+
+ // Is the last line set and is not ending with \r\n?
+ if ((isset($GLOBALS['http_headers'][count($GLOBALS['http_headers']) - 1])) && (substr($GLOBALS['http_headers'][count($GLOBALS['http_headers']) - 1], -2, 2) != getConfig('HTTP_EOL'))) {
+ // Add it to previous one
+ $GLOBALS['http_headers'][count($GLOBALS['http_headers']) - 1] .= $line;
+ } else {
+ // Add full line to temporary global array
+ array_push($GLOBALS['http_headers'], $line);
+ }
} // END - foreach
// Write back the array
function http_build_query($requestData, $prefix = '', $sep = '', $key = '') {
$ret = array();
foreach ((array) $requestData as $k => $v) {
- if (is_int($k) && $prefix != null) {
+ if (is_int($k) && !is_null($prefix)) {
$k = urlencode($prefix . $k);
} // END - if