protected function decodeLine($line)
{
$tokens = [];
$stack = [];
/*
We start to decode the response here. The understood tokens are:
literal
"literal" or also "lit\\er\"al"
(literals*)
All tokens are returned in an array. Literals in braces (the last understood
token in the list) are returned as an array of tokens. I.e. the following response:
"foo" baz bar ("f\\\"oo" bar)
would be returned as:
array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
*/
// replace any trailing <NL> including spaces with a single space
$line = rtrim($line) . ' ';
while (($pos = strpos($line, ' ')) !== false) {
$token = substr($line, 0, $pos);
if (!strlen($token)) {
continue;
}
while ($token[0] === '(') {
array_push($stack, $tokens);
$tokens = [];
$token = substr($token, 1);
}
if ($token[0] === '"') {
if (preg_match('%^\\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) {
$tokens[] = $matches[1];
$line = substr($line, strlen($matches[0]));
continue;
}
}
if ($stack && $token[strlen($token) - 1] === ')') {
// closing braces are not separated by spaces, so we need to count them
$braces = strlen($token);
$token = rtrim($token, ')');
// only count braces if more than one
$braces -= strlen($token) + 1;
// only add if token had more than just closing braces
if (rtrim($token) != '') {
$tokens[] = rtrim($token);
}
$token = $tokens;
$tokens = array_pop($stack);
// special handline if more than one closing brace
while ($braces-- > 0) {
$tokens[] = $token;
$token = $tokens;
$tokens = array_pop($stack);
}
}
$tokens[] = $token;
$line = substr($line, $pos + 1);
}
// maybe the server forgot to send some closing braces
while ($stack) {
$child = $tokens;
$tokens = array_pop($stack);
$tokens[] = $child;
}
return $tokens;
}