/**
* Parses a IMSP fetchaddress response text string into key-value pairs
*
* @param string $server_response The raw fetchaddress response.
*
* @return array Address book entry information as key=>value pairs.
*/
protected function _parseFetchAddressResponse($server_response)
{
$abook = '';
if (!preg_match("/^\\* FETCHADDRESS /", $server_response)) {
$this->_imsp->_logger->err('Did not receive a FETCHADDRESS response from server.');
throw new Horde_Imsp_Exception('Did not receive the expected response from the server.');
}
/* NOTES
* Parse out the server response string
*
* After choping off the server command response tags and
* explode()'ing the server_response string
* the $parts array contains the chunks of the server returned data.
*
* The predifined 'name' field starts in $parts[1].
* The server should return any single item of data
* that contains spaces within it as a double quoted string.
* So we can interpret the existence of a double quote at the beginning
* of a chunk to mean that the next chunk(s) are part of
* the same value. A double quote at the end of a chunk signifies the
* end of that value and the chunk following that can be interpreted
* as a key name.
*
* We also need to watch for the server returning a {} response for the
* value of the key as well. */
// Was the address book name a {}?
if (preg_match("/(^\\* FETCHADDRESS )({)([0-9]{1,})(\\}\$)/", $server_response, $tempArray)) {
$abook = $this->_imsp->receiveStringLiteral($tempArray[3]);
$chopped_response = trim($this->_imsp->receive());
} else {
// Take off the stuff from the beginning of the response
$chopped_response = trim(preg_replace("/^\\* FETCHADDRESS /", '', $server_response));
}
$parts = explode(' ', $chopped_response);
/* If addres book was sent as a {} then we must 'push' a blank
* value to the start of this array so the rest of the routine
* will work with the correct indexes. */
if (!empty($abook)) {
array_unshift($parts, ' ');
}
// Was the address book name quoted?
$numOfParts = count($parts);
$name = $parts[0];
$firstNameIdx = 1;
$firstChar = substr($name, 0, 1);
if ($firstChar == "\"") {
for ($i = 1; $i < $numOfParts; $i++) {
$lastChar = substr($parts[$i], strlen($parts[$i]) - 1, 1);
$firstNameIdx++;
if ($lastChar == "\"") {
break;
}
}
}
// Now start working on the entry name
$name = $parts[$firstNameIdx];
$firstChar = substr($name, 0, 1);
// Check to see if the first char of the name string is a double quote
// so we know if we have to extract more of the name.
if ($firstChar == "\"") {
$name = ltrim($name, "\"");
for ($i = $firstNameIdx + 1; $i < $numOfParts; $i++) {
$name .= ' ' . $parts[$i];
$lastChar = substr($parts[$i], strlen($parts[$i]) - 1, 1);
if ($lastChar == "\"") {
$name = rtrim($name, "\"");
$nextKey = $i + 1;
break;
}
}
// Check for {}
} elseif (preg_match('/\\{(\\d+)\\}/', $name, $matches)) {
$name = $this->_imsp->receiveStringLiteral($matches[1]);
$response = $this->_imsp->receive();
$parts = explode(' ', $response);
$numOfParts = count($parts);
$nextKey = 0;
} else {
// If only one chunk for 'name' then we just have to point
// to the next chunk in the array...which will hopefully
// be '2'
$nextKey = $firstNameIdx + 1;
}
$lastChar = '';
$entry['name'] = $name;
// Start parsing the rest of the response.
for ($i = $nextKey; $i < $numOfParts; $i += 2) {
$key = $parts[$i];
/* Check for {} */
if (@preg_match(Horde_Imsp_Client_Base::OCTET_COUNT, $parts[$i + 1], $tempArray)) {
$server_data = $this->_imsp->receiveStringLiteral($tempArray[2]);
$entry[$key] = $server_data;
/* Read any remaining data from the stream and reset
* the counter variables so the loop will continue
* correctly. Note we set $i to -2 because it will
* be incremented by 2 before the loop will run again */
$parts = $this->_imsp->getServerResponseChunks();
$i = -2;
$numOfParts = count($parts);
} else {
// Not a string literal response
@($entry[$key] = $parts[$i + 1]);
// Check to see if the value started with a double
// quote. We also need to check if the last char is a
// quote to make sure we REALLY have to check the next
// elements for a closing quote.
if (@substr($parts[$i + 1], 0, 1) == '"' && substr($parts[$i + 1], strlen($parts[$i + 1]) - 1, 1) != '"') {
do {
$nextElement = $parts[$i + 2];
// Was this element the last one?
$lastChar = substr($nextElement, strlen($nextElement) - 1, 1);
$entry[$key] .= ' ' . $nextElement;
// NOW, we can check the lastChar.
if ($lastChar == '"') {
$done = true;
$i++;
} else {
// Check to see if the next element is the
// last one. If so, the do loop will terminate.
$done = false;
$lastChar = substr($parts[$i + 3], strlen($parts[$i + 3]) - 1, 1);
$i++;
}
} while ($lastChar != '"');
// Do we need to add the final element, or were
// there only two total?
if (!$done) {
$nextElement = $parts[$i + 2];
$entry[$key] .= ' ' . $nextElement;
$i++;
}
// Remove the quotes sent back to us from the server.
if (substr($entry[$key], 0, 1) == '"') {
$entry[$key] = substr($entry[$key], 1, strlen($entry[$key]) - 2);
}
if (substr($entry[$key], strlen($entry[$key]) - 1, 1) == '"') {
$entry[$key] = substr($entry[$key], 0, strlen($entry[$key]) - 2);
}
} elseif (@substr($parts[$i + 1], 0, 1) == '"' && substr($parts[$i + 1], -1, 1) == '"') {
// Remove the quotes sent back to us from the server.
if (substr($entry[$key], 0, 1) == '"') {
$entry[$key] = substr($entry[$key], 1, strlen($entry[$key]) - 2);
}
if (substr($entry[$key], -1, 1) == '"') {
$entry[$key] = substr($entry[$key], 0, strlen($entry[$key]) - 2);
}
}
}
}
return $entry;
}