Attachments with php's built-in SoapClient? - php

Is there a way I can add a soap attachment to a request using PHP's built-in SoapClient classes? It doesn't look like it's supported, but maybe I can manually build the mime boundaries? I know the PEAR SOAP library supports them, but in order to use that I have to rewrite my entire library to use it.

Why don't you just send files using Data URI scheme rather than implement SoapAttachment ? Here is an example :
Client
$client = new SoapClient(null, array(
'location' => "http://localhost/lab/stackoverflow/a.php?h=none",
'uri' => "http://localhost/",
'trace' => 1
));
// Method 1 Array
// File to upload
$file = "golf3.png";
// First Example
$data = array();
$data['name'] = $file;
$data['data'] = getDataURI($file, "image/png");
echo "Example 1: ";
echo ($return = $client->upload($data)) ? "File Uploaded : $return bytes" : "Error Uploading Files";
// Method 2 Objects
// File to upload
$file = "original.png";
// Second Example
$attachment = new ImageObj($file);
$param = new SoapVar($attachment, SOAP_ENC_OBJECT, "ImageObj");
$param = new SoapParam($param, "param");
echo "Example 2: ";
echo ($return = $client->uploadObj($attachment)) ? "File Uploaded : $return bytes" : "Error Uploading Files";
Output
Example 1: File Uploaded : 976182 bytes
Example 2: File Uploaded : 233821 bytes
Server
class UploadService {
public function upload($args) {
$file = __DIR__ . "/test/" . $args['name'];
return file_put_contents($file, file_get_contents($args['data']));
}
public function uploadObj($args) {
$file = __DIR__ . "/test/" . $args->name;
$data = sprintf("data://%s;%s,%s", $args->mime, $args->encoding, $args->data);
return file_put_contents($file, file_get_contents($data));
}
}
try {
$server = new SOAPServer(NULL, array(
'uri' => 'http://localhost/'
));
$server->setClass('UploadService');
$server->handle();
} catch (SOAPFault $f) {
print $f->faultstring;
}
Client Util
// Function Used
function getDataURI($image, $mime = '') {
return 'data: ' . (function_exists('mime_content_type') ?
mime_content_type($image) : $mime) . ';base64,' .
base64_encode(file_get_contents($image));
}
// Simple Image Object
class ImageObj{
function __construct($file, $mime = "") {
$this->file = $file;
$this->name = basename($file);
if (function_exists('mime_content_type')) {
$this->mime = mime_content_type($file);
} elseif (function_exists('finfo_open')) {
$this->mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
} else {
$this->mime = $mime;
}
$this->encoding = "base64";
$this->data = base64_encode(file_get_contents($file));
}
}

Yes, you can build the MIME component of the message using something like imap_mail_compose.
You'll need to construct a multipart message as they do in the first example, putting the XML from the $request parameter, from an overridden SoapClient::__doRequest method, into the first part of the MIME message.
Then you can do as others have shown in the first imap_mail_compose example to add one or more messages parts with attachments. These attachements can, but do not have to be base64 encoded, they can just as well be binary. The encoding for each part is specified by part-specific headers.
You'll also need to cook up an appropriate set of HTTP headers, per the SwA Document #Baba linked to earlier.
Once it's all said and done, you should have something looking like the examples from that document:
MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
start="<claim061400a.xml#claiming-it.com>"
Content-Description: This is the optional message description.
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <claim061400a.xml#claiming-it.com>
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="cid:claim061400a.tiff#claiming-it.com"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-ID: <claim061400a.tiff#claiming-it.com>
...binary TIFF image...
--MIME_boundary--
And you can send that across the wire with the aforementioned overridden SoapClient::__doRequest method. Things I have noticed in trying to implement it myself thus far:
You may need to create an href URI reference from each SOAP node to the corresponding attachment, something like href="cid:claim061400a.tiff#claiming-it.com" above
You will need to extract the boundary component from the MIME content returned by imap_mail_compose for use in an HTTP Content-Type header
Don't forget the start component of the Content-Type header either, it should look something like this:
imap_mail_compose appears fairly minimal (but low hanging fruit), if it proves insufficient, consider Mail_Mime instead
Content-Type: Multipart/Related; boundary=MIME_boundary;
type=text/xml; start=""
Lastly, I'm not sure how evenly the various implementations of SwA are out there on the Internet... Suffice it to say, I've not been able to get an upload to a remote service with a crude implementation of what I've described above yet. It does seem like SwA is the typical SOAP attachment paradigm of choice though, from what I gather reading around on the net.

Related

How to download a base64 image in PHP from a web service?

I admit I have a lot of trouble with this problem (I don't know much about PHP and SOAP.
I have to get product pictures for an ecommerce via a web service of a provider (SOAP).
As shown in the picture below, the product pictures are converted to base64.
Example for a product picture
I need to retrieve all the pictures to upload them in a folder on my site and write the path of each picture in a CSV file.
The code below allows me to retrieve all the products that are sent to me via the web service. I recover all the products with the function RecupEtatStock() then, with the help of a loop, for each product I search if there are images with the function RecupPhotoProduct().
$wsdl = "https://sinex-saas.com/B00UWSUG9Z34TN22/Services/WebServiceStandard.asmx?WSDL";
$client = new SoapClient($wsdl);
$password = "????";
$username = "????";
$reffab = 4;
$codefab = 2;
$i = 0;
$fp = fopen(plugin_dir_path(__FILE__).'file.csv', 'w+');
$dataRecupererEtatStock = RecupEtatStock($username, $password, $client);
foreach ($dataRecupererEtatStock as $fields) {
$dataRecupPhotoProduit = RecupPhotoProduit($username, $password, $client, $fields->CodeFab, $fields->RefFab, $i);
$fields->image = $dataRecupPhotoProduit;
fputcsv($fp, get_object_vars($fields));
$i+=1;
}
fclose($fp);
Here is what the RecupPhotoProduct() function looks like. If there is no picture, the function returns null, otherwise it retrieves what the save_image() function returns.
function RecupPhotoProduit($pUsername, $pPassword, $pClient, $pCodeFab, $pReffab, $pi) {
$optionsRecupererPhotoProduit = array(
'user' => $pUsername,
'password' => $pPassword,
'codeFab' => $pCodeFab,
'refFab' => $pReffab,
);
$responseRecupererPhotoProduit = $pClient->RecupererPhotoProduit($optionsRecupererPhotoProduit);
$array = get_object_vars($responseRecupererPhotoProduit);
if(empty($array)) {
$responseRecupererPhotoProduit = null;
} else {
$responseRecupererPhotoProduit = $responseRecupererPhotoProduit->RecupererPhotoProduitResult;
$responseRecupererPhotoProduit = save_image($responseRecupererPhotoProduit, $pi);
}
return $responseRecupererPhotoProduit;
}
The above function allows me to retrieve the string in "RetrievePhotoProductResult" from this XML result:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<RecupererPhotoProduitResponse xmlns="http://tempuri.org/">
<RecupererPhotoProduitResult>/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACEAJoDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKKK5jxlZvq1pHpq3VxbROGaZoJNhYYwASOSOScewqoRcnZDSuUfEmq2k2pRw21zFLJCpD7HB2HnIJHTjr3rB3Fmz9/P4E5/lkfkKzINAs/DN/HYae8zwvH5h85wx3Z+nC8Z/CrpYHkjcCO45Of6sf0Fd0I8sbFothuMjHY7sfgDj9FH40xic4+QdRtLfmM/qx/CoTKqDc8kagZYyMcAdi/PYdBTWlQSxxfuxJIuY4j1cDsB3HckVQE+455Gfp15/qf0FWIHx0CAY7nAwP/ZR+tUBIjE7XRuSCVPOe/TuemPSpo35wFQnONuOCR2+g70MDX0jU7ez1LzrudYoAQzSOQioCCAW7DJPA7V3SOkiK6MGVhkMpyDXktzaw6pKlhcmRoLk7WKkA4PVvqT09q6DwdoS+GLpbe0vbuWxkLL5U0uVQnkEDscrjjj5q561Nv3kS0d5RRRXKSFFFFABRRRQAUUUUAFFFFABXLX9z9o1CYqcqp2D8OP55re1K7Wx0+a4ZlXavBY4AJ4Ga5G20abW1urS6jkg0/wCQLMkuHm7nOOg7Yrpw9o3myo9zGu7aXVfEU8Nku+4t7QEq6sEYkkqu739RnAzW3YeDriU6fd3l4YZYsvcQQNujlYjgH2X9ea3tohSa2CNHEMRhgOB0wS3U/QU4X8NizR3EwCADYnl4bPcBRyRTnVb1RpKDUblNPCOiQWl9G9p50N4zS3UcjbllJ68HoOOg4py2Ni7QS/Yrf7SmI4HIbdErDkA9cYHbrT5NceTK2+nyOpGMyNt/QZNUvtl2BgWi842ne5IA6Y+lYqb6sUJRtqTHwpoeo6TcWz2IigvHaWdIWK75CeXyOcnHWq974PWS9F3HfSLEsBja2+6jHs5PqP1q1DrkluixyWBCDoUk/wDigM/nVhtUtr5oo03k53NA42s3oOeCM+macakr6MS1nZbHCzWd7pU9hcaoqRySXWzbbhnU5PyHPuO3QGujimYMNmC38PpuByP1AraUSERW5aMoxIIxkFsksPUY7YrD1PQpdKE93pkb3AnnWSWOSXAQHhiM9PX610wqp+7LqVJcrsdhDKk8Ec0ZykihlPsRkVJWP4fvEntpYAwLQufqASeD6YO4Y9AK2K4pLldjFhRRRSAKKKKACiiigAoorN1y/aw05niV2mkYRxhF3EE9/wABk/hTSbdkBmakBruonT5YkbTIlJlkduGfOCMe3OPfPpW/HGkcaxxqFRRhQPSsS1s4NOtFsoUYGEhsMDIWODwQeSADjNQ3t1JGn2K3IUzhSVjcnap7Ke279ACa0ntZbGsqdoXZYvb03lz5FiCWQ4abOQMf3R0OPU9O2aSCytreVPPmjElxjy3lf55W6kYPJOKt6dYpbwISozwR8uCD0/L0FY/idSfEnhM7ScX0hJx0/dNUIdOPNLlfZ/grmxNPbjSrq7spIZvJSR0ZWDqrqDxx6EdK5mHU9fvdDs9VE+labYiwS4lu7iLeHkYZZQu4bVH4k5qfwXbibwdeW8haJZbq7VmxgqC7DPNQf8IIl3DprR69dPbWUKJbRtCjxAqMb9pGCe+TmqVludMVTpylCT2e7Vzf0G6k1nw7ZX15ZrbT3EOXjAIwM8YzyAeo+tRNBp2pT3VrbGOWS2lWOePGPKJGfTk454rSsLe4tbRYrq9kvZgSTPIioWyeBhQBx0rG8PW1xB4h8TyywSRxzXkbROykBwIwCQe4zU9zC0ZOcu233r5k0by6TJ5s6tPaHgylcyxD1Pdl/X61tqySRhlKujjIIOQwP8xTXjV2xlRIRjkZJXPTFY8TS6VdJbIdlpdtiDzB/qZD1XHoecD1+tIxepBLbjQtUjvLKBTbTu5uCrdOAT9T8ox9CK6ZHWWNZEYMjAMrA8EHvWK8cMsEkZRmS4OxpmbDMfVR7dab4dnMXn6W6Mn2U4jznBXuAT1wf0YVpNXV+xU4cpvUUUVkZhRRRQAUUUUAFYV1m88T28QkwlrEWePafm3e/p8o/Ot2sDT3H9t6nPJFtJmESuFIL8AD8sHkVpT6saRrTrGY3kkJXapy68MB1PNc3pMH27UJp5FyoPIDYwTjp9BtX8DWpqd4j6ZMqh1LhVXcuNwJAJH4VR0y9stK0Nr/AFC5it4S2Wd+OWOce5PoKnUtKd+Xqc7qeran/wAJDqGmxalPbxXWq21oJgQTboYdxCZ4BYjGa1LC6k0TxudDbV5ryzuLTzQt5MHkhlDABd3U7gc4PpxVqzi8KeJP7UW3WG7a5ZHvI23q+5RhG2tgrwOCMVgeIPh0qyi90SNZCExLbTylmkP99XYn5scYPp1FWmtnoehGVKT9lU93S2q62Wv9fqz0GfJhkGcEoQCe3Fc4k0vlSot+BLJEFimWU4XgDbs6Dofm9647TPG9/wCHn+zX4mnhiIV7a4BE8Q/2SeT9DkHHBrux4w8NNPBD/a9n5lwisik9QegPHB9jVRvT0tc562Dq0Xtdd0XtIZm05N0zSsGYEsclefu574qzNcxwY3tluyDkmqH9ozXAIhj8tWOEOMuw9cdqlgsOd85OTyVzyfqaiS1bkY+zS1mchJpPh6C/drm4gfUTN9oa4vLsCVMnIy2RhR2UDtXV6hp8V5p80Alx565WUsSfMHKMPxGai1WDw5p9u17qlpp0cbMAZJoFJdj26ZY+1S6frematBKdNvEk+z43qIyGj9MoQCOOnFDdzarOVWKaTt+BBpt9FNYQXRhC3TKVlz/A4OGA9OQfzrJ1ua4hvI7+3n8qVR8gK5DOflAPseM+1XI0Fvf6jDnCC48xc/7agn9RVfVAZbF/LiWaRc7EYEjdjg8c06TfNqcy5nqzV8L+If8AhINMinktzBceUjyKOV+bI+U/VWHPpW7XjfhvxpY6IHtjd3ss0kwyJLaCONcHlBscnHLYyM5NeyVm7X0ICiiikAUUUUAFc3YITNqqAfaWFyzGNiRtG4nAz+fHrXSVhWX7jxLqEPlbVlCyB8n5iQPX6HpWkHoyouzuV9RJksHIRFWOSNBtJJAz05+tZOsWc0/hjT57aC6lns7qOeNrdA7Q4GCwQ8SAZ+7154rq9VhafSrqNBl9m5cDqRyP5VU0KUSWY2btuMg54A6j8cGp5tbmsavLPnSOd8OW2qX3jCTWbt7mSCOy+zCaez+y+YxbOFjJLYHqe54rt65HxN4mvNL1yHT1ubLT7d7fzlurqJ5vMbOCgVSMY65PWtbwvq1xrmgw39zFEju7qrRE7ZFBwHAPIB9DyKck2rmmIhOUVVastF/XT7i3qOkaZqyAajY29yFHBlQEqPY9RXmUGnaxo6SadYaNPcStNJJbXUUSmGTcfkZmPTaMda9PIN+5QZ+yqcMf+ep9B/sjv69OlSPeQxl1bzPk+8BGx/pVQlKOxFLESprleq7DNOtXtLGCOZxJciNRNLj7745P4mrVA5UEA4IyOKKyMG23dmP4hnNtbW839ky36rLy8CB5LXggSopB3Ee3NYHhi2vW1zVb0jUpbeW2jRL2+gEU7OpPyIuANuOckDmtGfxlAPEVppdnavdRS3JtZrxWxHFLtLbB/eYAc46fWujl+ZQpG7J5+bBA9atXR1KUqUOWUd/yuYjpu1a+cnCBo1ZtucfKT2qDUYnXTpC7mDIGJACCM5/X/GtXR8yxXF3/AM/E7Mp9VHyj+VUPFcwWwjhMfmLISHGSMA8Z49Caql8SRgpK1rHktpr+kS3n2W107T5bxi0amC1cSFu53MgHuefWvf68s+H/AIO0FydQjgkeb5bhWnOSisWAXjC8hcnIPDdq9TrNpp2ZmFFFFIAooooAKwNcIsdRstUaRljTMTgZIJP3cgfjzW/UF5apeWklvJ91x19COQfzqoSs7jRXnvfJlCiPfuUMmG5b6CsezjksNQe02rGHPm2+/kKpPK8dwSR9CKdp81w8YsrsR/b4idwi+VmQE5C55A5H1Bq7LpZnt2+5BMCGh28iMj19c9DVSiomrUVFNblG88PTXGtSa1pWsS2FzPEIZj5Cyq6qeMBuh+lZ8cdl4TsXt59UZbea5L3N1NtUSzOcuvA4+UcBelbtrdPceZbyFobtcJIpb7o/vL/Q1YlubWx02SYRsYYIy/lohZyB6L1JP60lKxSqyklF6rTtfy1sZ2nan4e1i4kg02/SeQJvMcUrfKuQMgdhnHStQ2UJ28yjaNoxK3SsTwlp91suNc1OLy9S1Ng7RkcwQj/Vxe2Byfc1ys3iDXNQTVNSgl1aGG0uJI4jaQxNbwqhxmQN88h4Jbb0FPVvRmn1ZTm403ou/c7y+Gn6bYy3t5JJFbQJukcuxwPcDr1qrBr+kayx02Ca633ETKD9mli+XHJDlQAcdOaj12GXW/A1xHbr9rkurVGUQEJ5ucE7d2cZ7A1i6Wl43iHTX0yDXba0RWGoHVZG2SDb8oUMTl891wKN1qxU6MHTcm9Vf8F95JN8PYkOmQ6dqd9Da2kpYo1wcopB5iwPlbJ6+5rfvpZFtlt45AZp/wB1A7A70XHzuxPoATmrd3dxQQl5c7CdoQAh2bPAUe9Q21hJKzXd6cXEhHyDBEaA52e+e5/wqbt7mc606llNiW85tUjhGzy48IIsYYL0BU/xVlXdsPEGuvAk7CCBTHMB/d6fQkktj/dPpV++nfT4pIwyJkP9nzyemS3rhfb1q3odk9pYK86KlzMA0oH8PGAv4D9Sa0vyrmRNRx+yWrGwtdNs47SzgSGCMAKi+wx+J9zVmiisTIKKKKACiiigAooooA57xJayQINWsLeN76MBDk7dwzxz7H+ZqeDWorq3IjZDcKAJFU52nH+eta08K3EEkL/ddSp/GuBubW6tmupLDyINQcgPJImVcqe/6jNdFOPtI26opao27hPOZGJIkB+WRfvD/wCt7GnxahJAz/aI95I2m4gHzYHqOo/Ws631a3n1CaxKyR3MMaysWQhCD1IPfHQ1oRjAyMY6jac4H1qJR5dy3yqN1v8A1/X9I0YdTgnOY5o2yw4zgqO/41i3XhfSLu7nZvtcMF27PdQQXjJDKfVkH97vjHvViSGKXmSJGPqV5/OoPssI+Xyx1GOT/jURv0HSnON+R2Nn7Xb2kEce6G3jRNqrnhMcADtjFVZdQNwA1vA03IxJKCIww7gdSfYZpNNgt1lz5Eec4yVz/OteQZXeQCy5KluxxR1Iu1KzMq3UQ3f2q4drhwm7zQmQoP8AdH8IH4k1oXl9b2Fv51xIiKeFywG49hWFf63a6ba2sU++ZpZBDGlvllyeu4jqPXHSsmRLrVLmUam0M0RnDW8YTiNR03HvzzjtW8aPMy5xjeyNfS0m1rV2u76BBHauXh757IfbGGOPdTXU1Q0eDytORyuHnPmtnrz90H3ChR+FX6xm7y0MmFFFFQIKKKKACiiigAooooAK5zV4At+2AMyKHA/Q/wAh+ddHWD4p0a/1fT0GmXiWt5ESUd03KwI6H05wcj0rWjPklcadmcNrcW/WlhcAxS221lJID5J4PseRSW09zZtYrb3Tw2VoCDbquRJGeMMTz8p6fWqkFn4iiviPEgWS7UGNHjUKrp25HXJ6H1FXNvOeOecsevbJ+vQ+hrsVpK5ZcXX9Vjt74taQT3Cu32OJX2h1HRZGPRsZORxVj+3yLm2iFkTbyRlpp9w/cnjaNvVsnPI6YrPCLjjpj3zgf+zL+opGjOfuKfYPxz2+jdvep9nEa02LT+JNVFjdG1tIILxZGW28xt8bIMfO+OQeuVHSm3Opajdais4vZFhERiNuwyjM3RyeufTHrVQqM5JA77iSfof6Gp4og3AQH+HZnGfVf6imoRWwilY20dtfWdvbjyovNLiMMcEk5bP+1nmuvt7YSSLCQP3xEYHTIP3sf8B3H8K5W6h1F1d9JTzL5cNCHUHc2cZx6joR7V0/g/QdftH+3eIr6Ke4KnbFHGAFJxzn2GR/wI8VNSooxaE3Y7GiiiuEgKKKKACiiigAooooAKKKKACiiigDlfFaq1xDkZ+Tkeo5rmJFCeYcZKhj83fBA5+oPNFFd9H4EWtiYIDLs5/1rJnPPyrkH6jpn061EVUoG2jmNWx2+Y4I+nf60UVoMQgLkjqN5z7r3/EdasxKvzAqCAyJg9we34dqKKTA19EQRa9tGTmQjLcnhW5+tdjRRXHX+IiW4UUUViIKKKKACiiigD//2Q==</RecupererPhotoProduitResult>
</RecupererPhotoProduitResponse>
</soap:Body>
</soap:Envelope>
So for this example, the MIME64 encoded text is :
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
And this is what my save_image() function looks like. It decodes the base64 image from the "RetrievePhotoProductResult" part of the previous XML and uploads it to my WordPress plugin directory.
function save_image( $base64_img, $title ) {
$base64_img = str_replace('data:image/png;base64,', '', $base64_img);
$base64_img = str_replace(' ', '+', $base64_img);
$data = base64_decode($base64_img);
$file = plugin_dir_path(__FILE__) . $title . '.png';
return file_put_contents($file, $data);
}
But here is my problem, the images download well in my directory. However, I can't open them.
For example, if I try to open them with Paint, this is what I get (Whether I open an image with Paint or not, it's the same thing. I think the problem is the base64 encoding):
Paint cannot read this file. It is not a valid bitmap file or its format is not currently supported.
And if I want to access an image from my ecommerce site, I have a simple white dot that appears:
I have a simple white dot that appears
And here is what the base64 string looks like after decoding:
the base64 string
Do you know how I could download a base64 image via a php web service?
<?php
$encode = "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";
$decode = base64_decode($encode);
$size = getImageSizeFromString($decode);
var_dump($size);
if (empty($size['mime']) || strpos($size['mime'], 'image/') !== 0) {
die('Base64 value is not a valid image');
}
$ext = substr($size['mime'], 6);
$img_file = "filename.{$ext}";
file_put_contents($img_file, $decode);
echo $ext;
?>
this will work for all valid images.

XML-JSON content negotiation

Im looking to only display certain things from pages like this: http://sc2ranks.com/api/psearch/am/MxGPezz/1t/division/Felanis%20Sierra?appKey=sentinelgaming.net . So far I am able to display something but its not even the correct number, using the php below. Can someone show me how I would display the "achivement-points" of this player from this XML web page?
$url = 'http://sc2ranks.com/api/psearch/am/MxGPezz/1t/division/Felanis%20Sierra?appKey=sentinelgaming.net';
$xml = file_get_contents($url);
echo $xml->achievement-points;
Thanks
The content-type of this file varies depending on the Accept header or the format query parameter. It seems you can retrieve at least XML or JSON.
The default you get from file_get_contents() will be JSON because it does not include an Accept request header, but the default from a browser will be XML because browsers usually include an XML mime type in their Accept request header.
To get JSON:
$url = 'http://sc2ranks.com/api/psearch/am/MxGPezz/1t/division/Felanis%20Sierra?appKey=sentinelgaming.net';
// &format=json is not strictly necessary,
// but it will give you fewer surprises
$json = file_get_contents($url.'&format=json');
$records = json_decode($json);
echo $records[0]->achievement_points, "\n";
To get XML:
$sxe = simplexml_load_file($url.'&format=xml');
echo (string) $sxe->record->{'achievement-points'}, "\n";
To use the $sxe object see this SimpleXML cheat sheet.
Instead of using the format param you could set the Accept header. You can also add some abstraction to getting a url so that you can retrieve the content type and encoding as well. See example below.
function get_url($url, $context=null) {
$response = file_get_contents($url, false, $context);
$ctypeheaders = preg_grep('/^Content-Type:\s/i', $http_response_header);
$ctype = NULL;
if ($ctypeheaders) {
$ctype = end($ctypeheaders);
$ctype = end(explode(':', $ctype, 2));
$ctype = explode(';', $ctype, 2);
$charset = isset($ctype[1]) ? $ctype[1] : '';
if ($charset && preg_match('/charset\s*=\s*([^\s]+)/i', $charset, $matches)) {
$charset = $matches[1];
}
$ctype[1] = $charset;
$ctype = array_map('trim', $ctype);
}
return array($response, $ctype);
}
You can then use get_url() like so:
// With no accept header, just see what we get:
list($content, $contenttype) = get_url($url);
list($type, $encoding) = $contenttype;
// $type will be 'application/xml' or 'application/json'
// $encoding is very handy to know too
// Or we can specify an accept header:
$opt_accept_xml = stream_context_create(array(
'http' => array(
'header' => "Accept: application/xml\r\n"
)
));
list($content, $contenttype) = get_url($url, $opt_accept_xml);
Maybe:
echo $xml->record[0]->achievement-points;

PHP SOAP Transferring Files

I am trying to learn how to transfer files (.zip files) between a client and server using PHP and SOAP. Currently I have a set up that looks something like this:
require('libraries/nusoap/nusoap.php');
$server = new nusoap_server;
$server->configureWSDL('server', 'urn:server');
$server->wsdl->schemaTargetNamespace = 'urn:server';
$server->register('sendFile',
array('value' => 'xsd:string'),
array('return' => 'xsd:string'),
'urn:server',
'urn:server#sendFile');
But I am unsure on what the return type should be if not a string? I am thinking of using a base64_encode.
To be more clear I have posted both the server.php code and client.php code. Please see below:
## server.php ##
require_once('lib/nusoap.php'); //include required class for build nnusoap web service server
// Create server object
$server = new soap_server();
// configure WSDL
$server->configureWSDL('Upload File', 'urn:uploadwsdl');
// Register the method to expose
$server->register('upload_file', // method
array('file' => 'xsd:string','location' => 'xsd:string'), // input parameters
array('return' => 'xsd:string'), // output parameters
'urn:uploadwsdl', // namespace
'urn:uploadwsdl#upload_file', // soapaction
'rpc', // style
'encoded', // use
'Uploads files to the server' // documentation
);
// Define the method as a PHP function
function upload_file($encoded,$name) {
$location = "uploads\\".$name; // Mention where to upload the file
$current = file_get_contents($location); // Get the file content. This will create an empty file if the file does not exist
$current = base64_decode($encoded); // Now decode the content which was sent by the client
file_put_contents($location, $current); // Write the decoded content in the file mentioned at particular location
if($name!="")
{
return "File Uploaded successfully..."; // Output success message
}
else
{
return "Please upload a file...";
}
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
=====================================================================
## client.php ##
require_once('lib/nusoap.php'); //include required class for build nnusoap web service server
$wsdl="http://localhost:81/subhan/webservice3/server.php?wsdl"; // SOAP Server
if($_POST['submit'])
{
$tmpfile = $_FILES["uploadfiles"]["tmp_name"]; // temp filename
$filename = $_FILES["uploadfiles"]["name"]; // Original filename
$handle = fopen($tmpfile, "r"); // Open the temp file
$contents = fread($handle, filesize($tmpfile)); // Read the temp file
fclose($handle); // Close the temp file
$decodeContent = base64_encode($contents); // Decode the file content, so that we code send a binary string to SOAP
}
$client=new soapclient($wsdl) or die("Error"); // Connect the SOAP server
$response = $client->__call('upload_file',array($decodeContent,$filename)) or die("Error"); //Send two inputs strings. {1} DECODED CONTENT {2} FILENAME
// Check if there is anny fault with Client connecting to Server
if($client->fault){
echo "Fault {$client->faultcode} <br/>";
echo "String {$client->faultstring} <br/>";
}
else{
print_r($response); // If success then print response coming from SOAP Server
}
<form name="name1" method="post" action="" enctype="multipart/form-data">
<input type="file" name="uploadfiles"><br />
<input type="submit" name="submit" value="uploadSubmit"><br />
</form>
=================================================
All you need to do is download the nusoap.php which will be seen in soap library http://sourceforge.net/projects/nusoap/
This is fully tested and it will 100% work without fail.
In client.php, change this:
if($_POST['submit'])
{
...
}
$client=new soapclient($wsdl) or die("Error"); // Connect the SOAP server
$response = $client->__call('upload_file',array($decodeContent,$filename)) or die("Error"); //Send two inputs strings. {1} DECODED CONTENT {2} FILENAME
to this:
if($_POST['submit'])
{
...
$client=new soapclient($wsdl) or die("Error"); // Connect the SOAP server
$response = $client->__call('upload_file',array($decodeContent,$filename)) or die("Error"); //Send two inputs strings. {1} DECODED CONTENT {2} FILENAME
}
Transferring files over SOAP is something that gets everybody the first time (myself included). You need to open and read the document and then transfer it as a string. Here's how I would do it.
$handle = fopen("mypackage.zip", "r");
$contents = fread($handle, filesize("mypackage.zip"));
fclose($handle);
//$contents now holds the byte-array of our selected file
Then send $contents as your string through SOAP and reassemble it on the other side.

Zend_Mail and =0D=0A=3D=3D=3D=3D=3D

I'm writing a help desk pipe handler to pipe incoming e-mails as helpdesk ticket replies. Some e-mails are coming in perfectly fine, others are coming in as a jumble of the text and =3D's all munged into one giant string. Does anyone have an idea on how to decode that into plain text.
For reference, this is my mail parser function:
public function parseEmailMessage(Zend_Mail_Message $msg)
{
if ($msg->isMultiPart()) {
$arrAttachments = array();
$body = '';
// Multipart Mime Message
foreach (new RecursiveIteratorIterator($msg) as $part) {
try {
$mimeType = strtok($part->contentType, ';');
// Parse file name
preg_match('/name="(?<filename>[a-zA-Z0-9.\-_]+)"/is', $part->contentType, $attachmentName);
// Append plaintext results to $body
// All other content parts will be treated as attachments
switch ($mimeType) {
case 'text/plain':
$body .= trim($part->getContent()) . "\n";
break;
case 'text/html':
$body .= trim(strip_tags($part->getContent));
break;
default:
$arrAttachments[] = array(
'attachment_mime' => $mimeType,
'attachment_name' => $this->filterFileName($attachmentName['filename']),
'base64data' => trim($part->getContent())
);
}
} catch (Zend_Mail_Exception $e) {
// ignore
}
}
return array($body, $arrAttachments);
} else {
// Plain text message
return array(trim($msg->getContent()), array());
}
}
I'll take a guess that somehow the content type is not correctly specified and Zend doesn't know how to decode it. I know I've seen this before, but I can't remember where or how it was 'solved'.
It looks like quoted-printable being treated like plain text.

How to select content type from HTTP Accept header in PHP

I'm trying to build a standard compliant website framework which serves XHTML 1.1 as application/xhtml+xml or HTML 4.01 as text/html depending on the browser support. Currently it just looks for "application/xhtml+xml" anywhere in the accept header, and uses that if it exists, but that's not flexible - text/html might have a higher score. Also, it will become more complex when other formats (WAP, SVG, XForms etc.) are added. So, does anyone know of a tried and tested piece of PHP code to select, from a string array given by the server, either the one best supported by the client or an ordered list based on the client score?
Little snippet from my library:
function getBestSupportedMimeType($mimeTypes = null) {
// Values will be stored in this array
$AcceptTypes = Array ();
// Accept header is case insensitive, and whitespace isn’t important
$accept = strtolower(str_replace(' ', '', $_SERVER['HTTP_ACCEPT']));
// divide it into parts in the place of a ","
$accept = explode(',', $accept);
foreach ($accept as $a) {
// the default quality is 1.
$q = 1;
// check if there is a different quality
if (strpos($a, ';q=')) {
// divide "mime/type;q=X" into two parts: "mime/type" i "X"
list($a, $q) = explode(';q=', $a);
}
// mime-type $a is accepted with the quality $q
// WARNING: $q == 0 means, that mime-type isn’t supported!
$AcceptTypes[$a] = $q;
}
arsort($AcceptTypes);
// if no parameter was passed, just return parsed data
if (!$mimeTypes) return $AcceptTypes;
$mimeTypes = array_map('strtolower', (array)$mimeTypes);
// let’s check our supported types:
foreach ($AcceptTypes as $mime => $q) {
if ($q && in_array($mime, $mimeTypes)) return $mime;
}
// no mime-type found
return null;
}
example usage:
$mime = getBestSupportedMimeType(Array ('application/xhtml+xml', 'text/html'));
You can leverage apache's mod_negotiation module. This way you can use the full range of negotiation capabilities the module offers, including your own preferences for the content type (e,g, "I really want to deliver application/xhtml+xml, unless the client very much prefers something else").
basic solution:
create a .htaccess file withAddHandler type-map .varas contents
create a file foo.var withURI: foo
URI: foo.php/html
Content-type: text/html; qs=0.7
URI: foo.php/xhtml
Content-type: application/xhtml+xml; qs=0.8as contents
create a file foo.php with<?php
echo 'selected type: ', substr($_SERVER['PATH_INFO'], 1);as contents.
request http://localhost/whatever/foo.var
For this to work you need mod_negotiation enabled, the appropriate AllowOverride privileges for AddHandler and AcceptPathInfo not being disabled for $_SERVER['PATH_INFO'].
With my Firefox sending "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8" and the example .var map the result is "selected type: xhtml".
You can use other "tweaks" to get rid of PATH_INFO or the need to request foo.var, but the basic concept is: let mod_negotiation redirect the request to your php script in a way that the script can "read" the selected content-type.
So, does anyone know of a tried and tested piece of PHP code to selectIt's not a pure php solution but I'd say mod_negotiation has been tried and tested ;-)
Pear::HTTP 1.4.1 has a method string negotiateMimeType( array $supported, string $default)
<?php
require 'HTTP.php';
foreach(
array(
'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5',
'text/*;q=0.3, text/html;q=0.8, application/xhtml+xml;q=0.7, */*;q=0.2',
'text/*;q=0.3, text/html;q=0.7, */*;q=0.8',
'text/*, application/xhtml+xml',
'text/html, application/xhtml+xml'
) as $testheader) {
$_SERVER['HTTP_ACCEPT'] = $testheader;
$http = new HTTP;
echo $testheader, ' -> ',
$http->negotiateMimeType( array('application/xhtml+xml', 'text/html'), 'application/xhtml+xml'),
"\n";
}
printstext/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, /;q=0.5 -> application/xhtml+xml
text/*;q=0.3, text/html;q=0.8, application/xhtml+xml;q=0.7, */*;q=0.2 -> text/html
text/*;q=0.3, text/html;q=0.7, */*;q=0.8 -> application/xhtml+xml
text/*, application/xhtml+xml -> application/xhtml+xml
text/html, application/xhtml+xml -> text/html
edit: this might not be so good after all...
My firefox sends Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
text/html and application/xhtml+xml have q=1.0 but PEAR::HTTP (afaik) doesn't let you chose which one you prefer, it returns text/html no matter what you pass as $supported. This may or may not be sufficient for you. see my other answer(s).
Just for the record, Negotiation is a pure PHP implementation for dealing with content negotiation.
Merged #maciej-Łebkowski and #chacham15 solutions with my issues fixes and improvements. If you pass $desiredTypes = 'text/*' and Accept contains text/html;q=1 then text/html will be returned.
/**
* Parse, sort and select best Content-type, supported by a user browser.
*
* #param string|string[] $desiredTypes The filter of desired types. If &null then the all supported types will returned.
* #param string $acceptRules Supported types in the HTTP Accept header format. $_SERVER['HTTP_ACCEPT'] by default.
* #return string|string[]|null Matched by $desiredTypes type or all accepted types.
* #link Inspired by http://stackoverflow.com/a/1087498/3155344
*/
function resolveContentNegotiation($desiredTypes = null, $acceptRules = null)
{
if (!$acceptRules) {
$acceptRules = #$_SERVER['HTTP_ACCEPT'];
}
// Accept header is case insensitive, and whitespace isn't important.
$acceptRules = strtolower(str_replace(' ', '', $acceptRules));
$sortedAcceptTypes = array();
foreach (explode(',', $acceptRules) as $acceptRule) {
$q = 1; // the default accept quality (rating).
// Check if there is a different quality.
if (strpos($acceptRule, ';q=') !== false) {
// Divide "type;q=X" into two parts: "type" and "X"
list($acceptRule, $q) = explode(';q=', $acceptRule, 2);
}
$sortedAcceptTypes[$acceptRule] = $q;
}
// WARNING: zero quality is means, that type isn't supported! Thus remove them.
$sortedAcceptTypes = array_filter($sortedAcceptTypes);
arsort($sortedAcceptTypes, SORT_NUMERIC);
// If no parameter was passed, just return parsed data.
if (!$desiredTypes) {
return $sortedAcceptTypes;
}
$desiredTypes = array_map('strtolower', (array) $desiredTypes);
// Let's check our supported types.
foreach (array_keys($sortedAcceptTypes) as $type) {
foreach ($desiredTypes as $desired) {
if (fnmatch($desired, $type)) {
return $type;
}
}
}
// No matched type.
return null;
}
PEAR's HTTP2 library supports parsing all types of Accept headers. It's installable via composer and PEAR.
Examples can be found at the documentation or my blog post.
Client may accept a list of mime-types in the response. In the other hand the order of the response is very important for client side. PHP Pear HTTP2 is the best to deal with language, charset, and mimetypes.
$http = new HTTP2();
$supportedTypes = array(
'text/html',
'application/json'
);
$type = $http->negotiateMimeType($supportedTypes, false);
if ($type === false) {
header('HTTP/1.1 406 Not Acceptable');
echo "You don't want any of the content types I have to offer\n";
} else {
echo 'I\'d give you data of type: ' . $type . "\n";
}
Here is a good tutorial: https://cweiske.de/tagebuch/php-http-negotiation.htm

Categories