1

I am using Zend Framework 2's AbstractRestfulController to implement a CRUD API in our project. Using the PUT HTTP method invokes the logic for updating an existing entity.

When receiving a PUT request, the AbstractRestfulController transforms the request body to an array using PHP's parse_str function, but this function does not do what it is supposed to do.

Because it gave me odd results, I tried parse_str with the sample data provided in the PHP docs:

// sample data from the PHP docs
$content = "first=value&arr[]=foo+bar&arr[]=baz";

// put the parsed variables into $parsedParams
parse_str($content, $parsedParams);

var_dumping $parsedParams gives me the following

array(5) { 
    ["first"]=> string(1) "v" 
    ["lue"]=> string(0) "" 
    ["rr"]=> array(2) { 
        [0]=> string(5) "foo b" 
        [1]=> string(1) "b" 
    } 
    ["r"]=> string(0) "" 
    ["z"]=> string(0) "" 
} 

Apparently the character "a" confuses parse_str, but I have absolutely no idea what's causing this odd behavior. The encoding of the PHP file is UTF-8, server is running Ubuntu 14.04 with PHP 5.4 as a Apache 2.4 module inside a Vagrant environment.

What may be the cause of this? I read about issues with the HTML entity & instead of plain &'s, but that doesn't seem to apply here.

UPDATE

I just ran the same code on the command line in interactive mode via SSHing into the Vagrant machine. In interactive mode parse_str works without problem! I then ran my test script from the command line via $ php /var/www/test.php which also worked properly. Is this a problem with the Apache PHP module or configuration?

Subsurf
  • 1,256
  • 1
  • 17
  • 28
  • 2
    Just tried it with PHP v5.4 and it works without any problems. Perhaps your string contains invisible characters that makes PHP choke? Could you try `echo strlen($content)` and see what you get? – silkfire Nov 15 '14 at 14:56
  • copied the one you have posted. http://codepad.viper-7.com/FYbCCx seems fine – Kevin Nov 15 '14 at 15:05
  • strlen($content) gives me a length of 35 which is correct, may it be a problem of my PHP version or something like that? – Subsurf Nov 15 '14 at 15:19
  • I now tried the same code as above in interactive mode on the command line, I have added my findings to the initial question – Subsurf Nov 15 '14 at 15:30

1 Answers1

2

Notice how your strings are split on both & and a?

I think the configuration setting arg_separator.input is incorrectly set to "&" instead of the default "&".

This setting can be set in php.ini, .htaccess, httpd.conf or .user.ini. See: Where a configuration setting may be set.

Test program:

<?php

  echo "arg_separator.input = '", ini_get ('arg_separator.input'), "'\n";

  $content = "first=value&arr[]=foo+bar&arr[]=baz";
  parse_str($content, $parsedParams);

  var_dump ($parsedParams);

Output (somewhat compacted) with different settings in php.ini:

arg_separator.input = '&'
array(2) {
  ["first"] => string(5) "value"
  ["arr"] => array(2) {
    [0] => string(7) "foo bar"
    [1] => string(3) "baz"
  }
}
arg_separator.input = '&amp;'
array(5) {
  ["first"] => string(1) "v"
  ["lue"] => string(0) ""
  ["rr"] => array(2) {
    [0] => string(5) "foo b"
    [1] => string(1) "b"
  }
  ["r"] => string(0) ""
  ["z"] => string(0) ""
}

The configuration setting arg_separator.output also defaults to "&". Setting this to "&amp;" might be okay if you only produce HTML output. But you will run into trouble if you want to use http_build_query() to produce an HTTP Location: header, or in other situations where an HTML entity reference is not suitable.

Test program:

<?php

  echo "arg_separator.output = '", ini_get ('arg_separator.output'), "'\n";

  $q = http_build_query (array ('a' => 0, 'b' => 1, 'c' => 2));
  echo $q, "\n";

Output with different settings in php.ini:

arg_separator.output = '&'
a=0&b=1&c=2
arg_separator.output = '&amp;'
a=0&amp;b=1&amp;c=2
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
  • Thanks a lot, this was causing the issue! Would have taken me years to figure that out by myself. When setting up the Vagrant environment I copied the php.ini from our production server (a shared environment) to the Vagrant machine, guess I have to look out for this problem on the production server too. Can I safely leave arg_seperator.output as "&" though? – Subsurf Nov 17 '14 at 11:00