How to retrieve particular header fields from a raw HTTP response? - php

This is what $result returns :
HTTP/1.1 200 OK
Server: SERVER
Content-Type: text/xml;charset=utf-8
Connection: close
Expires: Tue, 26 Mar 2013 00:28:45 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Tue, 26 Mar 2013 00:28:45 GMT
Content-Length: 290
Connection: keep-alive
Set-Cookie: KEY=isbgvigbiwsb124252525252; Domain=www.website.com; Expires=Tue, 26-Mar-13 02:28:44 GMT; Path=/; HttpOnly
Set-Cookie: session=12345566789:abc1231552662626262; Domain=www.website.com; Expires=Thu, 25-Apr-2013 00:28:43 GMT; Path=/
<login>
<success>1</success>
<player>
<id>1234567</id>
<AnotherId>123456</AnotherId>
<email>email#email.com</email>
<accountinformation>
<id>123456</id>
<name>namehere</name>
<number>1234360</number>
</accountinformation>
</player>
</login>
I want to retrieve the KEY cookie from the response. Currently my code is as follows
//a cURL function would be here
$result = curl_exec($ch);
list($body, $split) = explode("\r\n\r\n", $result, 2);
$arr = explode("\r\n", $body);
$start = explode(":", $arr[10]);
$end = explode(";", $start[1]);
$INFO_I_NEED = $end[0];
What would be a simpler way of performing this action ? since it needs to be done 3/4 times for different parsing areas.

It looks like preg_match_all might be what you are looking for. Using this answer as inspiration try:
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $m);
You could then write a function like this:
function getCookies($result) {
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $m);
return($m)
}
$result = curl_exec($ch);
$cookiesArray = getCookies($result);
The return value of the function will be an array of all the cookie values. So $cookiesArray will hold:
array (
0 => 'KEY=isbgvigbiwsb124252525252',
1 => 'session=12345566789:abc1231552662626262',
)

Put it inside a function so you can reuse when need be:
<?php
//a cURL function would be here
$result = curl_exec($ch);
$INFO_I_NEED = myExplode($result);
function myExplode($data){
list($body, $split) = explode("\r\n\r\n", $result, 2);
$arr = explode("\r\n", $body);
$start = explode(":", $arr[10]);
$end = explode(";", $start[1]);
return($end[0]);
}
?>

Related

calDAV "PROPFIND" call "401 Unauthorized" response from calendar.yahoo.com server

I am trying to send yahoo calendars(caldav) a request to get "current-user-principal" But In response I am getting "401 Unauthorized" error. Before this request I am making another request to get "OPTIONS" which is giving "200 OK" response.
Request call is
PROPFIND / HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXX=
Host: calendar.yahoo.com:443
Depth: 0
Prefer: return-minimal
Content-type: application/xml; charset=utf-8
Content-Length: 85
User-Agent: DAViCalClient
Connection: close
Request Response is:
string(613) "HTTP/1.1 401 Unauthorized
WSHost: tardis012.cal.bf1.yahoo.com
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Thu, 18-Feb-2021 03:44:03 GMT
WWW-Authenticate: Basic realm="YahooCalendar"
WWW-Authenticate: OAuth realm="YahooCalendar"
Content-Length: 0
Date: Fri, 19 Feb 2021 03:44:03 GMT
Age: 1
Server: ATS
Referrer-Policy: no-referrer-when-downgrade
Connection: close
Strict-Transport-Security: max-age=15552000
Expect-CT: max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only"
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
I am using a client library which has a function to make server request
function DoRequest( $relative_url = "" ) {
if(!defined("_FSOCK_TIMEOUT")){ define("_FSOCK_TIMEOUT", 10); }
$headers = array();
$headers[] = $this->requestMethod." ". $this->base_url . $relative_url . " HTTP/1.1";
$headers[] = "Authorization: Basic ".base64_encode($this->user .":". $this->pass );
$headers[] = "Host: ".$this->server .":".$this->port;
foreach( $this->headers as $ii => $head ) {
$headers[] = $head;
}
$headers[] = "Content-Length: " . strlen($this->body);
$headers[] = "User-Agent: " . $this->user_agent;
$headers[] = 'Connection: close';
$this->httpRequest = join("\r\n",$headers);
$this->xmlRequest = $this->body;
$fip = fsockopen( $this->protocol . '://' . $this->server, $this->port, $errno, $errstr, _FSOCK_TIMEOUT); //error handling?
if ( !(get_resource_type($fip) == 'stream') ) return false;
if ( !fwrite($fip, $this->httpRequest."\r\n\r\n".$this->body) ) { fclose($fip); return false; }
$rsp = "";
while( !feof($fip) ) { $rsp .= fgets($fip,8192); }
fclose($fip);
$this->headers = array(); // reset the headers array for our next request
$this->ParseResponse($rsp);
return $rsp;
}
Here is class init.
$cal = new CalDAVClient("https://calendar.yahoo.com/", "piyush138", "XXXXXXXXXXX", "calendar" );
Link to library
The following request gives "200 ok" response which runs before above request:
Request to server
OPTIONS / HTTP/1.1
Authorization: Basic cGl5dXNoMTM4OkQxZzF0YWxoZWw=
Host: calendar.yahoo.com:443
Content-Length: 0
User-Agent: DAViCalClient
Connection: close
Response from server
string(668) "HTTP/1.1 200 OK
WSHost: tardis030.cal.bf1.yahoo.com
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Thu, 18-Feb-2021 03:44:01 GMT
DAV: 1, 3, calendar-access
MS-Author-Via: DAV
Allow: HEAD, MKCOL, POST, PROPFIND, ACL, COPY, REPORT, OPTIONS, PUT, DELETE, MKCALENDAR, MOVE, GET, PROPPATCH
Content-Length: 0
Date: Fri, 19 Feb 2021 03:44:02 GMT
Age: 3
Server: ATS
Referrer-Policy: no-referrer-when-downgrade
Connection: close
Strict-Transport-Security: max-age=15552000
Expect-CT: max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only"
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
I also tried simplifying my password but that didn't work either
I have found the Solution.
I was using the conventional password in server call but in actual I had to use "APP Password" which you can create from
your yahoo account Under "Account security" tab.

PHP: SoapClient Response code from HTTP headers

I'm trying to extract the Soap response's HTTP status code.
So for instance i have :
$client = new SoapClient($wsdl);
$client->__setSoapHeaders(
new SoapHeader(
$nameSpace,
'Security',
$secHeaderValue,
true
)
);
// The actual call
$response = $client->Complete($paramswebservice)
So now i'm getting the response headers, this way :
$responseHeaders = $client->__getLastResponseHeaders();
var_dump($responseHeaders);
This is the result of the vardump : a string formatted this way (web browser - page source code)
What i am doing right now to extract the http status code '200' :
/**
* Returns the HTTP Status code of $response
* #param string $response
* #return string
*/
function extract_response_http_code($response) {
$tmp = explode('\n', $response);
$array = explode(' ', $tmp[0]);
return $array[1];
}
I really don't like this solution. I would like a more robust / consistent one. Any suggestions ?
EDIT 1
As asked in the comments :
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 1315
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Thu, 30 Mar 2017 08:52:15 GMT
PHP code demo
<?php
$result="HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 1315
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Thu, 30 Mar 2017 08:52:15 GMT";
preg_match("/HTTP\/\d\.\d\s*\K[\d]+/", $result,$matches);
print_r($matches);
Output:
Array
(
[0] => 200
)

PHP get some parts from shell_exec

I need your help guys i have some php code running on my server:
<?php
if ($_GET['id'])
$id = $_GET['id'];
$json = file_get_contents('http://www.youtubeinmp3.com/fetch/?format=JSON&video=http://www.youtube.com/watch?v=' . $id);
$data = json_decode($json, true);
$stream = $data['link'];
$url = $stream;
$output = shell_exec ('curl -I -L ' . $url);
echo "<pre>$output</pre>";
?>
and it outputs this when i go to:http://146.185.137.252/new.php?id=HgzGwKwLmgM
it outputs this:
HTTP/1.1 302 Moved Temporarily
Date: Sat, 11 Feb 2017 01:25:56 GMT
Content-Type: text/html
Connection: keep-alive
Set-Cookie: __cfduid=db002cf41b2472eb20de42ec65b16029a1486776356; expires=Sun, 11-Feb-18 01:25:56 GMT; path=/; domain=.youtubeinmp3.com; HttpOnly
X-Powered-By: PHP/5.5.38
Location: //w23.youtubeinmp3.com/download/get/?id=HgzGwKwLmgM&r=kT7YFcbHgX3m25ULP3GeWulVx9OmT2qd&t=Queen+-+Don%27t+Stop+Me+Now+%28Official+Video%29
Server: cloudflare-nginx
CF-RAY: 32f40283e57d148b-AMS
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 11 Feb 2017 01:25:56 GMT
Content-Type: audio/mpeg
Content-Length: 3499136
Last-Modified: Fri, 18 Nov 2016 18:09:22 GMT
Connection: keep-alive
Content-Disposition: attachment; filename="Queen - Don't Stop Me Now (Official Video).mp3"
Accept-Ranges: bytes
Expires: 0
ETag: "582f43d2-356480"
Accept-Ranges: bytes
but i don't need al that stuff i only need to two things:
the (Location:) and the (Content-Disposition: attachment; filename=)
in two different variables so in this case i need:
//w23.youtubeinmp3.com/download/get/?id=HgzGwKwLmgM&r=kT7YFcbHgX3m25ULP3GeWulVx9OmT2qd&t=Queen+-+Don%27t+Stop+Me+Now+%28Official+Video%29
and
Queen - Don't Stop Me Now (Official Video) (i dont want the .mp3 btw)
i've searched the web everywhere but to be honest i'm a total noob at this
so if anyone can help me out that would be amazing
This code is tested. Response was copied from my Browser.
I just used curl to do the curl request and used curl_getinfo($ch,CURLINFO_REDIRECT_URL) to get the redirect link.
I also added getting the header which you do not need unless there are issues and you'd like to see the response header.
PHP
<?php
header('content-type: text/plain');
$id='HgzGwKwLmgM';
$json = file_get_contents('http://www.youtubeinmp3.com/fetch/?format=JSON&video=http://www.youtube.com/watch?v=' . $id);
$json = json_decode($json, true);
$url = $json['link'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$header = curl_exec($ch);
$link = curl_getinfo($ch,CURLINFO_REDIRECT_URL);
echo "\nLINK: $link\n\nHEADER: $header";
?>
RESPONSE:
LINK: http://w23.youtubeinmp3.com/download/get/?id=HgzGwKwLmgM&r=aRDQ1MGdfkY3Mm6EFxQqEVqgd9FHf81q&t=Queen+-+Don%27t+Stop+Me+Now+%28Official+Video%29
HEADER: HTTP/1.1 302 Moved Temporarily
Date: Sun, 12 Feb 2017 16:23:39 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d27df4bad722b0449b88b37d4b9d9b7341486916619; expires=Mon, 12-Feb-18 16:23:39 GMT; path=/; domain=.youtubeinmp3.com; HttpOnly
X-Powered-By: PHP/5.5.38
Location: //w23.youtubeinmp3.com/download/get/?id=HgzGwKwLmgM&r=aRDQ1MGdfkY3Mm6EFxQqEVqgd9FHf81q&t=Queen+-+Don%27t+Stop+Me+Now+%28Official+Video%29
Server: cloudflare-nginx
CF-RAY: 330162e8b07e115f-DFW
If you only want the filename and the the title as you wrote on your question.
you can simply use them like this
$link = $data['link'];
$title = $data['title'];
once you have that, you can print it or make a link with it like this
echo "<a href=$link>$title</a>";
Unless you want to save the file, you don't need the curl (and the shell_Exec) part
it would look something like this:
<?php
if (isset($_GET['id'])) {
$id = $_GET['id'];
$json = file_get_contents('http://www.youtubeinmp3.com/fetch/?format=JSON&video=http://www.youtube.com/watch?v=' . $id);
$data = json_decode($json, true);
$link = $data['link'];
$title = $data['title'];
echo "<a href=$link>$title</a>";
}
?>

How to parse the header returned by cURL?

I am trying to communicate to an API using cURL. One of the methods require that I pass the value of the ININ-ICWS-CSRF-Token header (ie. WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zNmZjN2MxYWJmODBYCjEwLjAuNC4xNjA=) and the Set-Cookie (ie. icws_904586002=bf7c7783-6766-4c4f-862b-48f25a9a3741) so I need to extract them so I can pass them later in my code.
Here is what I did to extract the header and the body from the cURL/API respond:
$respond = curl_exec($ch);
//throw cURL exception
if($respond === false){
$errorNo = curl_errno($ch);
$errorMessage = curl_error($ch);
throw new ApiException($errorMessage, $errorNo);
}
list($header, $body) = explode("\r\n\r\n", $respond, 2);
echo '<pre>';
print_r($header);
echo '</pre>';
This is the content of the $header value:
HTTP/1.1 201 Created
ININ-ICWS-CSRF-Token: WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zNmZjN2MxYWJmODBYCjEwLjAuNC4xNjA=
ININ-ICWS-Session-ID: 904586002
Set-Cookie: icws_904586002=bf7c7783-6766-4c4f-862b-48f25a9a3741; Path=/icws/904586002
Location: /icws/904586002/connection
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Type: application/vnd.inin.icws+JSON; charset=utf-8
Date: Wed, 06 May 2015 17:13:44 GMT
Server: HttpPluginHost
Content-Length: 237
I would like to get in return results like this
the value of "ININ-ICWS-CSRF-Token" is "WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zNmZjN2MxYWJmODBYCjEwLjAuNC4xNjA="
the value of the "cookie" is "ININ-ICWS-CSRF-Token: WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zNmZjN2MxYWJmODBYCjEwLjAuNC4xNjA="
You can use the http_parse_headers function to parse the headers.
$hdr_array = http_parse_headers($header);
foreach ($hdr_array as $name => $value) {
echo "The value of '$name' is '$value'<br>";
}
If you don't have http_parse_headers, you can use the code in Pedro Lobito's answer.
<?php
$myHeader = <<< LOL
HTTP/1.1 201 Created
ININ-ICWS-CSRF-Token: WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zNmZjN2MxYWJmODBYCjEwLjAuNC4xNjA=
ININ-ICWS-Session-ID: 904586002
Set-Cookie: icws_904586002=bf7c7783-6766-4c4f-862b-48f25a9a3741; Path=/icws/904586002
Location: /icws/904586002/connection
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Type: application/vnd.inin.icws+JSON; charset=utf-8
Date: Wed, 06 May 2015 17:13:44 GMT
Server: HttpPluginHost
Content-Length: 237
LOL;
preg_match_all('/(.*?Token): (.*?)\s+/', $myHeader, $matches, PREG_PATTERN_ORDER);
$tokenName = $matches[1][0];
$token = $matches[2][0];
echo <<< LOL
the value of "$tokenName" is "$token"
the value of the "cookie" is "$tokenName: $token"
LOL;
?>

Getting page with fsockopen

I'm trying to access http://www.example.com:4380/apid/request?method=getXMLTable&name=1&ui=UI&id=12345. It should give back output as XML.
This is the code:
<?
$host = "www.example.com";
$path = "/apid/request?method=getXMLTable&name=1&ui=UI&id=12345";
$port = 4380;
$fp = fsockopen($host, $port, $errno, $errstr, 30);
$buffer ="";
if (!$fp) {
echo "ERR!!<br>";
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET ".$path." HTTP/1.1\r\n";
$out .= "Host: ".$host."\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
$buffer .= fgets($fp, 1024);
}
fclose($fp);
}
?>
Anyhow I'm getting not the XML output, but this response:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Wed, 02 Apr 2014 16:16:43 GMT
Cache-Control: no-store
Cache-Control: no-cache
Cache-Control: must-revalidate
Cache-Control: pre-check=0
Cache-Control: post-check=0
Cache-Control: max-age=0
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/xml
Transfer-Encoding: chunked
Vary: Accept-Encoding
Date: Wed, 02 Apr 2014 16:16:43 GMT
Connection: close 2000 0
I can access pages like 'www.example.com/path/to/file' with the presented code without any problems. I guess I make any mistake with port(not standard http ) or request. Every clue would be very welcome.
EDIT:
I can't use any http module! Socket is a must in this case!
I have tried with the code below, but I get nothing in $body:
list($header, $body) = explode("\n\n", $buffer, 2);
echo http_chunked_decode($body);
You are getting a Transfer-Encoding: chunked response. You need to use http_chunked_decode to decode it (you can find a PHP version here, if you don't have pecl_http).
list($header, $body) = explode("\n\n", $buffer, 2);
echo http_chunked_decode($body);
But as the other commenter said, you should really use file_get_contents if you have allow_url_fopen enabled or curl otherwise. They handle the chunked encoding for you.

Categories