HTTP response contains text I don't understand - php

I have a PHP script that receives a file and returns a response.
The PHP script returns the response like this:
echo "<response><status>success</status><message>file received: test.txt</message></response>";
When I make the POST request from PuTTY, the response I receive is this:
6b
<response><status>success</status><message>file received: test.txt</message></response>
Depending on the response, the 6b could be something else as well? Is this the length of the response in hex, or something else?
The PHP script. Currently, I'm working on simply being able to POST a file and receive and parse the response, hence the PHP file is barebones.
<?php
if (array_key_exists('file',$_FILES) && $_FILES['file']['size'] != 0)
{
$status = 'success';
$message = "File received: " . $_FILES['file']['name'];
}
else
{
$status = 'failed';
$message = "No file received.";
}
$reply = "<response>"
."<status>" . $status . "</status>"
."<message>" . $message . "</message>"
."</response>";
echo $reply;
?>
I am establishing a RAW connection over port 80 on putty, and making the POST request like this:
POST /file_post.php HTTP/1.1
Host: example.com
Connection: Keep-Alive
Content-Length: 212
UserAgent: Mozilla/5.0
Content-Type: multipart/form-data; boundary=---------------------8ce9826eb81af6a
-----------------------8ce9826eb81af6a
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: application/octet-stream
TestData
-----------------------8ce9826eb81af6a--
Reponse received

This is Chunked Transfer Encoding http://en.wikipedia.org/wiki/Chunked_transfer_encoding
You can send request in http 1.0 instead of 1.1 to avoid this or you can decode it easily (check this out http://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example ) really easy to decode ,
Or use php-curl, it will automatically decode the response for you.

Related

Parse socket data on a PHP socket_listener

I was able to open a PHP TCP listener socket, but I don't know how to parse the buffer. The client that connects to my socket send a text/html with an additional boundary data with a xml file and an image file.
How can I parse the response to get the XML file on one side and the Image on the other side?
server = socket_create_listen(8086);
socket_getsockname($server, $addr, $port);
if (!$server) {
$message = 'Start TCP socket: Ko. Could not create socket.';
$this->logger->info($message);
die($message);
} else {
$message = 'Start TCP socket: Ok. TCP socket opened on: ' . $addr . ':' . $port . '.';
$this->logger->info($message);
while ($c = socket_accept($server)) {
socket_getpeername($c, $raddr, $rport);
$this->logger->info("Received Connection from $raddr:$rport\n");
$data = '';
while ($bytes = socket_recv($c, $r_data, 1024, MSG_WAITALL)) {
$data .= $r_data;
}
//Edited: Explode with double line and got data
$parsedData = explode("\r\n\r\n", $data);
$xml = new \SimpleXMLElement($parsedData[2]);
print_r($xml);
else {
echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($c)) . "\n";
}
socket_close($c);
}
}
fclose($server);
This is the output I received:
Received Connection from :59048
Read 3096 bytes from socket_recv(). Closing socket...POST /test HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
Content-Type: multipart/form-data;boundary=-------------------------7e13971310878
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: 0.0.0.0:7200
Content-Length: 516032
Connection: Keep-Alive
Cache-Control: no-cache
---------------------------7e13971310878
Content-Disposition: form-data; name="file.xml";filename="file.xml";
Content-Type: text/xml
Content-Length: 2273
<EventNotificationAlert version="2.0" xmlns="http://www.isapi.org/ver20/XMLSchema">
<ipAddress></ipAddress>
<ipv6Address></ipv6Address>
<portNo></portNo>
<!--REST OF XML DATA-->
</EventNotificationAlert>
---------------------------7e13971310878
Content-Disposition: form-data;name="image.jpg";filename="image.jpg";
Content-Type: image/pjpeg
Content-Length: 7164
����JFIF���
!"$"^C
EDITED: I was able to got the XML data by using "explode" function, but I don't know how to get the 2 images as image files. Any suggestion?
Any help would be really appreciated!
Thank you!
I write my final solution here:
1 - Explode the data in a string to an array(using \r\n\r\n):
$parsedData = explode("\r\n\r\n", $data);
2 - XML is actually on position 2 (position 0 and 1 contain POST HTTP Header and boundary start section):
$xml = new \SimpleXMLElement($parsedData[2]);
Image is on position 4 (array position 3 contains headers such as Content-Disposition that must be skipped):
The code to save the data as an image is:
//Generate GD image from raw string.
if (!$source = #imagecreatefromstring($parsedData[4])){
$message = 'Save Image: Ko. Img path: "' . $imgFullPath . '". Error details: ' . error_get_last()['message'];
$this->logger->error($message);
}else {
//Save GD image on disk
imagejpeg($source, $imgFullPath);
//Clean resources.
imagedestroy($source);
$message = 'Save Image: Ok. Image saved successfully on path: "' . $imgFullPath . '"...';
$this->logger->info($message);
$this->io->writeln($message);

PHP + cURL for live video streaming (can cURL work with infinite data?)

Good day!
I have video server with different streams and server which clients are communicating with. My goal is to make a script going to specific stream on request, taking a chunk of data and returnig this chunk to client.
My idea is similar with this: to use cURL for authorization, capture some raw data and create callback function echoing data every chunk.
Problem is I've failed to find any mentions of using cURL with "endless data"; when I try it with my script it just goes to forever loading then crash with 504 error from nginx.
I don't understand what the difference for cURL between my data and "30 million characters long", if I use buffersize and flush() as well.
With no more introductions, here is my code:
public function callback($curl, $data)
{
ob_get_clean();
if (($data === false) || ($data == null))
{
throw new Exception (curl_error($curl) . " " . curl_errno($curl));
}
$length = strlen($data);
header("Content-type: video/mp4");
header("Transfer-encoding: chunked");
header("Connection: keep-alive");
header("Cache-Control: max-age=2592000, public");
header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT');
header("Last-Modified: ".gmdate('D, d M Y H:i:s', #filemtime($this->path)) . ' GMT' );
echo $data;
ob_flush();
flush();
return $length;
}
public function getStreamChunk($camera_id)
{
$url = "http://example.com/$camera_id:0:0?format=mp4"; //url of noted video server
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_HEADER => 0,
CURLOPT_USERPWD => "$this->login:$this->pass",
CURLOPT_BUFFERSIZE => (1024*1024),
CURLOPT_WRITEFUNCTION => array($this, "callback")
)
);
curl_exec($curl);
curl_close($curl);
}
It workes for pictures (from the same server), there's no echo for cURL errors, so problem in infinite source and, I suspect, in headers. I've checked headers for responce from video server via browser, but can't find any overlooked mistake in my solution.
Here's headers from video server:
Response Headers
Connection: keep-alive
Content-Type: video/mp4
Date: Wed, 30 May 2018 07:31:34 GMT
Server: nginx/1.12.2
Transfer-Encoding: chunked
Request Headers
Accept: */*
Accept-Encoding: identity;q=1, *;q=0
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
Authorization: Basic <...>
Connection: keep-alive
Cookie: <...>
Host: <...>
Range: bytes=0-
Referer: http://example.com/$camera_id:0:0?format=mp4
User-Agent: <...>
Solutions from here I also tried, but
1) I've already explained my problem with "30 million characters" answer C:
2) Solution with HTTP_RANGE isn't working for me as well (I tried) because of same error: long loading and crash.
UPD. I think I missed "Content-Range:" header; in the end you can use it without knowing size, like this: "bytes 1024-2047/*", but can't figure out how to use it properly in my case yet.
I've figured out what's the problem.
My code is working, there's no need for any other headers, except for cURL option:
CURLOPT_FOLLOWLOCATION => 1
So yeah, cURL CAN work with infinite data. Here's working solution for video proxing via cURL, if anyone else is interested.

Object reference not set to an instance of an object in SOAP web services in PHP

I am a beginner in Soap Web Services. I have looked over all the questions and answers related to mine but they have different scenarios and code and they don't seem to match with my requirement.
I am using a webservice created by a third party for product listing. I want to just fetch some data so that I may know the basic workflow of how Webservices work. Here is my current code
require_once('nuSOAP/lib/nusoap.php');
$wsdl = "http://ws.anchordistributors.com/anchorwebservice.asmx?wsdl";
$client = new nusoap_client($wsdl, 'wsdl');
// Input params
$username = "mylogin_id";
$password = "mylogin_password";
// In this demo, we use json data , you can use any other data format for same
$json = '{"param1":"value1","param2":"value2"}';
$client->setCredentials($username, $password);
$error = $client->getError();
if ($error)
{
echo $error; die();
}
$action = "GetCountries"; // webservice method name
$result = array();
if (isset($action))
{
$result['response'] = $client->call($action, $json);
}
echo "<h3>Output : </h3>";
print_r ($result['response']);
echo "<h2>Request</h2>";
echo "<pre>" . htmlspecialchars($client->request, ENT_QUOTES) . "</pre>";
echo "<h2>Response</h2>";
echo "<pre>" . htmlspecialchars($client->response, ENT_QUOTES) . "</pre>";
This is what I am getting back:
Output :
Array ( [faultcode] => soap:Server [faultstring] =>
System.Web.Services.Protocols.SoapException: Server was unable to
process request. ---> System.NullReferenceException: Object reference
not set to an instance of an object. at
AnchorWebservice.AnchorWebservice.AuthenticateUser(String sFunction)
at AnchorWebservice.AnchorWebservice.GetCountries() --- End of inner
exception stack trace --- [detail] => ) Request
POST /anchorwebservice.asmx HTTP/1.0 Host: ws.anchordistributors.com
User-Agent: NuSOAP/0.9.5 (1.123) Content-Type: text/xml;
charset=ISO-8859-1 SOAPAction:
"http://tempuri.org/AnchorWebservice/AnchorWebservice/GetCountries"
Authorization: Basic ODI1NjQ3OkVJTExDODI1 Content-Length: 401
{"param1":"value1","param2":"value2"}
Response
HTTP/1.1 500 Internal Server Error. Connection: close Date: Fri, 06
Oct 2017 18:47:28 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322 Cache-Control: private Content-Type:
text/xml; charset=utf-8 Content-Length: 744
soap:Server
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException:
Object reference not set to an instance of an object. at
AnchorWebservice.AnchorWebservice.AuthenticateUser(String sFunction)
at AnchorWebservice.AnchorWebservice.GetCountries() --- End of
inner exception stack trace ---
I have no idea why is this creating issue on what logic. Being a beginner I don't know the sense of the issue. I just want to be able to use GetCountries method to fetch the array of countries.

Php server 5.3.3 doesn't detect attachment file in my Post requests (5.4.3 does)

I'm using android volley - http multipart request to post a mime file to my php server. Php 5.4.3 can catch the attachment file but php 5.3.3 didn't:
$_FILES['uploadedfile'] == empty array
(the request is good - good request length).
Can someone explains? Why php 5.3.3 didn't? Thanks, I'm new in PHP.
How to send a “multipart/form-data” POST in Android with Volley
My http request:
{MultipartFormEntity#830061806024}
multipart = {HttpBrowserCompatibleMultipart#830061809784}
parts = {ArrayList#830059119584} size = 1
0 = {FormBodyPart#830067533016}
body = {ByteArrayBody#830067487680}
header = {Header#830067537968} "[Content-Disposition: form-data; name="uploadedfile"; filename="test.mim", Content-Type: application/octet-stream, Content-Transfer-Encoding: binary]"
name = {String#830059743272} "uploadedfile"
boundary = {String#830061809752} "6ANZ75BgJPrWEv1L0jU9o-IKj5ftRzcpKiBqY7N"
charset = {CharsetICU#830037109480} "java.nio.charset.CharsetICU[UTF-8]"
subType = {String#830057480912} "form-data"
contentType = {BasicHeader#830061692384} "Content-Type: multipart/form-data; boundary=6ANZ75BgJPrWEv1L0jU9o-IKj5ftRzcpKiBqY7N; charset=UTF-8"
name = {String#830037147880} "Content-Type"
value = {String#830061806056} "multipart/form-data; boundary=6ANZ75BgJPrWEv1L0jU9o-IKj5ftRzcpKiBqY7N; charset=UTF-8"
contentLength = 4299
This code broke php function:
try {
entityBuilder.setCharset(CharsetUtils.get("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
>> Content-Type =
multipart/form-data; boundary=1ft_IEmfaejQeazBUZDaPUqA-bkzkalk0; charset=UTF-8
In fact, this code above made php server doesn't get the uploaded file since it having charset type after boundary part. The Content-Type below make my code works:
multipart/form-data; boundary=1ft_IEmfaejQeazBUZDaPUqA-bkzkalk0
I guest in some version, php server dont recognize uploaded file in first case. Thanks BNK very much for your suggestion.

Send JSON data to PHP using XMLHttpRequest w/o jQuery

I am trying to send JSON data from a form using the XMLHttpRequest object. I can send the data using the following function. There are no errors displayed in FireBug and the JSON-data in the request is displayed well formed by FireBug.
However, I send the data to echo.php, what simply returns the content:
<?php
print_r($_POST);
print_r($_GET);
foreach (getallheaders() as $name => $value) {
echo "$name: $value\n";
}
echo file_get_contents('php://input');
?>
The POST-array is always empty, but I can see the JSON string returned by file_get_contents. How does that happen? What am I doing wrong?
output of echo.php
Array
(
)
Array
(
)
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: eo,de-de;q=0.8,de;q=0.6,en-us;q=0.4,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Referer: http://localhost/form.html
Content-Length: 88
Cookie: {{..to much data..}}
Pragma: no-cache
Cache-Control: no-cache
{"type":"my_type","comment":"commented"}
the sending function:
function submit(){
var data={};
data.type=document.form.type.value;
data.comment=document.form.comment.value;
//get right XMLHttpRequest object for current browsrer
var x=ajaxFunction();
var string = JSON.stringify(data);
x.open('POST','echo.php',true);
x.setRequestHeader('Content-type','application/json; charset=utf-8');
x.setRequestHeader("Content-length", string.length);
x.setRequestHeader("Connection", "close");
x.onreadystatechange = function(){
if (x.readyState != 4) return;
if (x.status != 200 && x.status != 304) {
alert('HTTP error ' + req.status);
return;
}
data.resp = JSON.parse(x.responseText);
if(data.resp.status=='success'){
alert('That worked!');
}else{
alert('That didn\'t work!');
}
}
x.send(string);
return false; //prevent native form submit
}
PHP does not process JSON requests automatically like it does with form-encoded or multipart requests. If you want to use JSON to send requests to PHP, you're basically doing it correctly with file_get_contents(). If you want to merge those variables into your global $_POST object you can, though I would not recommend doing this as it might be confusing to other developers.
// it's safe to overwrite the $_POST if the content-type is application/json
// because the $_POST var will be empty
$headers = getallheaders();
if ($headers["Content-Type"] == "application/json")
$_POST = json_decode(file_get_contents("php://input"), true) ?: [];
Quick note: you should not be sending a charset with your Content-Type for application/json. This should only be sent with text/* Content-Types.
You forgot to name your variables in the send function.
The good way to use it is
x.send('name1='+string+'&name2=value2');
Given that, I think you will have to change the content-length header. I don't think it is usefull to send it.
One another thing you can do is try with GET method.
You can also try to change your content-type header by that one :
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")

Categories