Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 0.13.0

Bug #9840 base64 detection
Submitted: 2007-01-15 07:27 UTC Modified: 2007-01-25 18:00 UTC
From: sebastiangiffhorn Assigned: yunosh
Status: Closed Package: SOAP (version 0.9.4)
PHP Version: 5.1.2 OS: All
Roadmaps: (Not assigned)    
Subscription  


 [2007-01-15 07:27 UTC] sebastiangiffhorn (Sebastian)
Description: ------------ The detection of base64 encoded strings within Base.php (function _isBase64(&$value)) does not work correctly as not every base64 encoded string has an "=" at the end.

Comments

 [2007-01-19 18:02 UTC] yunosh (Jan Schneider)
The MIME standard (RFC 2045) which is significant for data encoding in SOAP, uses paddding with "=".
 [2007-01-23 06:14 UTC] sebastiangiffhorn
However padding is only used if neccessary! "If three octets remain, they are processed normally. If fewer than three octets (24 bits) are remaining to encode, the input data is right-padded with zero bits to form an integral multiple of six bits." "...if two octets were remaining to encode, one "=" character is appended to the output; if one octet was remaining, two "=" characters are appended..." This is the reason why it could happen a base64 encoded string (by PHPs base64encode) has no padding with "="
 [2007-01-23 06:52 UTC] yunosh (Jan Schneider)
Of course you are right. Any bright ideas how to determine whether a string is base64 encoded alternatively?
 [2007-01-23 07:02 UTC] sebastiangiffhorn
Unfortunately no. If I had I wouldn't ask ;-) In my case I now append a "=" manually to the encoded string which seems to work for me (I know this is really quick 'n dirty :-D) However I think there has to be a solution, as im not running into these truobles when using the PHP5 internal SOAP implementation...
 [2007-01-23 09:01 UTC] yunosh (Jan Schneider)
Can you provide a testcase? Some reproducable code that triggers this behaviour?
 [2007-01-23 09:54 UTC] sebastiangiffhorn
We have different PDF files which we send to an Jetty application server via SOAP. Here is a sample code which illustrates the problem: <? function isBase64($value) { $l = strlen($value); if ($l) { return $value[$l - 1] == '=' && preg_match('/[A-Za-z=\/\+]+/', $value); } return false; } for($i=0; $i<3; $i++) { $myfile="file".$i.".pdf"; $fh = fopen("file".$i.".pdf", "rb"); $data = fread($fh, filesize("file".$i.".pdf")); fclose($fh); $testbase64 = base64_encode($data); if (isBase64($testbase64)) { echo $myfile." --> True: ".substr($testbase64, -10)."<br/>"; } else { echo $myfile." --> False: ".substr($testbase64, -10)."<br/>"; } } ?> As i dont know if I can upload files here I have uploaded the corresponding PDF files to: http://hosting-saar.de/pdf.zip As you can see the file2.pdf produces a base64 encoded string without padding "=".
 [2007-01-23 10:01 UTC] yunosh (Jan Schneider)
Eh, no. I was actually hoping for an example how to trigger this in the *SOAP* code.
 [2007-01-23 10:23 UTC] sebastiangiffhorn
Hmm... Actually trigger what, Sorry I don't get what you mean exactly
 [2007-01-23 10:30 UTC] yunosh (Jan Schneider)
The broken usage of isBase64().
 [2007-01-23 11:17 UTC] sebastiangiffhorn
I use the detection function in my sample... Generally I could upload the complete PHP code which I'm using for communicating with the application server, however I think this is a bit useless as I can't do the same with the application server itself :-)
 [2007-01-23 12:32 UTC] yunosh (Jan Schneider)
 [2007-01-24 05:38 UTC] sebastiangiffhorn
I tested the patch and it works just great... Unfortunately it works better than I expected, as now every string is detected as base64 binary :-). Do you have any idea on how the PHP5 internal SOAP does the detection of base64 strings, as this seems to work quite well. I think I have to live with the old detection and manually append a "=" to every base64 encoded string...
 [2007-01-24 06:05 UTC] yunosh (Jan Schneider)
Bummer. ext/soap doesn't detect base64 values. It uses guess_zval_convert() if no type is explicitely specified. This function is looking up the type from the value's context. But since you can't tell me a code path where this happens, i.e. no code to reproduce a concrete case where base64 detection fails, I can't analyze the context and whether I can access the type there.
 [2007-01-24 06:45 UTC] sebastiangiffhorn
Here is a short sample how to reproduce the behaviour. Just uncomment the 3 $myString one after another. The XML Output was grabbed with http://simile.mit.edu/httptracer/ <? require_once('SOAP/Client.php'); $client = new SOAP_Client("http://localhost:8881/service/"); //$myString = "A"; // --> Padding with "==" //$myString = "Al"; // --> Padding with "=" //$myString = "All"; // --> No Padding "=" $byteArray = base64_encode($myString); $argument = array("in0" => $byteArray); $client->call("my",$argument); ?> XML: $myString = "A"; // --> Padding with "==" <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <my> <in0 xsi:type="xsd:base64Binary">QQ==</in0> </my> </SOAP-ENV:Body> </SOAP-ENV:Envelope> $myString = "Al"; // --> Padding with "=" <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <my> <in0 xsi:type="xsd:base64Binary">QWw=</in0> </my> </SOAP-ENV:Body> </SOAP-ENV:Envelope> $myString = "All"; // --> No Padding "=" <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <my> <in0 xsi:type="xsd:string">QWxs</in0> </my> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
 [2007-01-24 08:57 UTC] yunosh (Jan Schneider)
This can easily be done by using: $byteArray = new SOAP_Value('in0', 'base64Binary', base64_encode('All')); I'm gonna remove the magic base64 detection completely.
 [2007-01-24 09:28 UTC] sebastiangiffhorn
Thanks this works great, I appreciate all your help.
 [2007-01-25 18:00 UTC] yunosh (Jan Schneider)
This bug has been fixed in CVS. If this was a documentation problem, the fix will appear on pear.php.net by the end of next Sunday (CET). If this was a problem with the pear.php.net website, the change should be live shortly. Otherwise, the fix will appear in the package's next release. Thank you for the report and for helping us make PEAR better.