function RunQueries() { if (empty($this->_reqs)) { $this->_error = "no queries defined, issue AddQuery() first"; return false; } // mbstring workaround $this->_MBPush(); if (!($fp = $this->_Connect())) { $this->_MBPop(); return false; } //////////////////////////// // send query, get response //////////////////////////// $nreqs = count($this->_reqs); $req = join("", $this->_reqs); $len = 4 + strlen($req); $req = pack("nnNN", SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, $len, $nreqs) . $req; // add header if (!$this->_Send($fp, $req, $len + 8) || !($response = $this->_GetResponse($fp, VER_COMMAND_SEARCH))) { $this->_MBPop(); return false; } $this->_reqs = array(); ////////////////// // parse response ////////////////// $p = 0; // current position $max = strlen($response); // max position for checks, to protect against broken responses $results = array(); for ($ires = 0; $ires < $nreqs && $p < $max; $ires++) { $results[] = array(); $result =& $results[$ires]; $result["error"] = ""; $result["warning"] = ""; // extract status list(, $status) = unpack("N*", substr($response, $p, 4)); $p += 4; $result["status"] = $status; if ($status != SEARCHD_OK) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $message = substr($response, $p, $len); $p += $len; if ($status == SEARCHD_WARNING) { $result["warning"] = $message; } else { $result["error"] = $message; continue; } } // read schema $fields = array(); $attrs = array(); list(, $nfields) = unpack("N*", substr($response, $p, 4)); $p += 4; while ($nfields-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $fields[] = substr($response, $p, $len); $p += $len; } $result["fields"] = $fields; list(, $nattrs) = unpack("N*", substr($response, $p, 4)); $p += 4; while ($nattrs-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $attr = substr($response, $p, $len); $p += $len; list(, $type) = unpack("N*", substr($response, $p, 4)); $p += 4; $attrs[$attr] = $type; } $result["attrs"] = $attrs; // read match count list(, $count) = unpack("N*", substr($response, $p, 4)); $p += 4; list(, $id64) = unpack("N*", substr($response, $p, 4)); $p += 4; // read matches $idx = -1; while ($count-- > 0 && $p < $max) { // index into result array $idx++; // parse document id and weight if ($id64) { $doc = sphUnpackU64(substr($response, $p, 8)); $p += 8; list(, $weight) = unpack("N*", substr($response, $p, 4)); $p += 4; } else { list($doc, $weight) = array_values(unpack("N*N*", substr($response, $p, 8))); $p += 8; if (PHP_INT_SIZE >= 8) { // x64 route, workaround broken unpack() in 5.2.2+ if ($doc < 0) { $doc += 1 << 32; } } else { // x32 route, workaround php signed/unsigned braindamage $doc = sprintf("%u", $doc); } } $weight = sprintf("%u", $weight); // create match entry if ($this->_arrayresult) { $result["matches"][$idx] = array("id" => $doc, "weight" => $weight); } else { $result["matches"][$doc]["weight"] = $weight; } // parse and create attributes $attrvals = array(); foreach ($attrs as $attr => $type) { // handle 64bit ints if ($type == SPH_ATTR_BIGINT) { $attrvals[$attr] = sphUnpackI64(substr($response, $p, 8)); $p += 8; continue; } // handle floats if ($type == SPH_ATTR_FLOAT) { list(, $uval) = unpack("N*", substr($response, $p, 4)); $p += 4; list(, $fval) = unpack("f*", pack("L", $uval)); $attrvals[$attr] = $fval; continue; } // handle everything else as unsigned ints list(, $val) = unpack("N*", substr($response, $p, 4)); $p += 4; if ($type & SPH_ATTR_MULTI) { $attrvals[$attr] = array(); $nvalues = $val; while ($nvalues-- > 0 && $p < $max) { list(, $val) = unpack("N*", substr($response, $p, 4)); $p += 4; $attrvals[$attr][] = sprintf("%u", $val); } } else { $attrvals[$attr] = sprintf("%u", $val); } } if ($this->_arrayresult) { $result["matches"][$idx]["attrs"] = $attrvals; } else { $result["matches"][$doc]["attrs"] = $attrvals; } } list($total, $total_found, $msecs, $words) = array_values(unpack("N*N*N*N*", substr($response, $p, 16))); $result["total"] = sprintf("%u", $total); $result["total_found"] = sprintf("%u", $total_found); $result["time"] = sprintf("%.3f", $msecs / 1000); $p += 16; while ($words-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $word = substr($response, $p, $len); $p += $len; list($docs, $hits) = array_values(unpack("N*N*", substr($response, $p, 8))); $p += 8; $result["words"][$word] = array("docs" => sprintf("%u", $docs), "hits" => sprintf("%u", $hits)); } } $this->_MBPop(); return $results; }
function _ParseSearchResponse($response, $nreqs) { $p = 0; // current position $max = strlen($response); // max position for checks, to protect against broken responses $results = array(); for ($ires = 0; $ires < $nreqs && $p < $max; $ires++) { $results[] = array(); $result =& $results[$ires]; $result["error"] = ""; $result["warning"] = ""; // extract status list(, $status) = unpack("N*", substr($response, $p, 4)); $p += 4; $result["status"] = $status; if ($status != SEARCHD_OK) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $message = substr($response, $p, $len); $p += $len; if ($status == SEARCHD_WARNING) { $result["warning"] = $message; } else { $result["error"] = $message; continue; } } // read schema $fields = array(); $attrs = array(); list(, $nfields) = unpack("N*", substr($response, $p, 4)); $p += 4; while ($nfields-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $fields[] = substr($response, $p, $len); $p += $len; } $result["fields"] = $fields; list(, $nattrs) = unpack("N*", substr($response, $p, 4)); $p += 4; while ($nattrs-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $attr = substr($response, $p, $len); $p += $len; list(, $type) = unpack("N*", substr($response, $p, 4)); $p += 4; $attrs[$attr] = $type; } $result["attrs"] = $attrs; // read match count list(, $count) = unpack("N*", substr($response, $p, 4)); $p += 4; list(, $id64) = unpack("N*", substr($response, $p, 4)); $p += 4; // read matches $idx = -1; while ($count-- > 0 && $p < $max) { // index into result array $idx++; // parse document id and weight if ($id64) { $doc = sphUnpackU64(substr($response, $p, 8)); $p += 8; list(, $weight) = unpack("N*", substr($response, $p, 4)); $p += 4; } else { list($doc, $weight) = array_values(unpack("N*N*", substr($response, $p, 8))); $p += 8; $doc = sphFixUint($doc); } $weight = sprintf("%u", $weight); // create match entry if ($this->_arrayresult) { $result["matches"][$idx] = array("id" => $doc, "weight" => $weight); } else { $result["matches"][$doc]["weight"] = $weight; } // parse and create attributes $attrvals = array(); foreach ($attrs as $attr => $type) { // handle 64bit ints if ($type == SPH_ATTR_BIGINT) { $attrvals[$attr] = sphUnpackI64(substr($response, $p, 8)); $p += 8; continue; } // handle floats if ($type == SPH_ATTR_FLOAT) { list(, $uval) = unpack("N*", substr($response, $p, 4)); $p += 4; list(, $fval) = unpack("f*", pack("L", $uval)); $attrvals[$attr] = $fval; continue; } // handle everything else as unsigned ints list(, $val) = unpack("N*", substr($response, $p, 4)); $p += 4; if ($type == SPH_ATTR_MULTI) { $attrvals[$attr] = array(); $nvalues = $val; while ($nvalues-- > 0 && $p < $max) { list(, $val) = unpack("N*", substr($response, $p, 4)); $p += 4; $attrvals[$attr][] = sphFixUint($val); } } else { if ($type == SPH_ATTR_MULTI64) { $attrvals[$attr] = array(); $nvalues = $val; while ($nvalues > 0 && $p < $max) { $attrvals[$attr][] = sphUnpackU64(substr($response, $p, 8)); $p += 8; $nvalues -= 2; } } else { if ($type == SPH_ATTR_STRING) { $attrvals[$attr] = substr($response, $p, $val); $p += $val; } else { $attrvals[$attr] = sphFixUint($val); } } } } if ($this->_arrayresult) { $result["matches"][$idx]["attrs"] = $attrvals; } else { $result["matches"][$doc]["attrs"] = $attrvals; } } list($total, $total_found, $msecs, $words) = array_values(unpack("N*N*N*N*", substr($response, $p, 16))); $result["total"] = sprintf("%u", $total); $result["total_found"] = sprintf("%u", $total_found); $result["time"] = sprintf("%.3f", $msecs / 1000); $p += 16; while ($words-- > 0 && $p < $max) { list(, $len) = unpack("N*", substr($response, $p, 4)); $p += 4; $word = substr($response, $p, $len); $p += $len; list($docs, $hits) = array_values(unpack("N*N*", substr($response, $p, 8))); $p += 8; $result["words"][$word] = array("docs" => sprintf("%u", $docs), "hits" => sprintf("%u", $hits)); } } $this->_MBPop(); return $results; }
public function _ParseSearchResponse($response, $nreqs) { $p = 0; // current position $max = strlen($response); // max position for checks, to protect against broken responses $results = array(); for ($ires = 0; $ires < $nreqs && $p < $max; ++$ires) { $results[] = array(); $result =& $results[$ires]; $result['error'] = ''; $result['warning'] = ''; // extract status list(, $status) = unpack('N*', substr($response, $p, 4)); $p += 4; $result['status'] = $status; if ($status != SEARCHD_OK) { list(, $len) = unpack('N*', substr($response, $p, 4)); $p += 4; $message = substr($response, $p, $len); $p += $len; if ($status == SEARCHD_WARNING) { $result['warning'] = $message; } else { $result['error'] = $message; continue; } } // read schema $fields = array(); $attrs = array(); list(, $nfields) = unpack('N*', substr($response, $p, 4)); $p += 4; while ($nfields-- > 0 && $p < $max) { list(, $len) = unpack('N*', substr($response, $p, 4)); $p += 4; $fields[] = substr($response, $p, $len); $p += $len; } $result['fields'] = $fields; list(, $nattrs) = unpack('N*', substr($response, $p, 4)); $p += 4; while ($nattrs-- > 0 && $p < $max) { list(, $len) = unpack('N*', substr($response, $p, 4)); $p += 4; $attr = substr($response, $p, $len); $p += $len; list(, $type) = unpack('N*', substr($response, $p, 4)); $p += 4; $attrs[$attr] = $type; } $result['attrs'] = $attrs; // read match count list(, $count) = unpack('N*', substr($response, $p, 4)); $p += 4; list(, $id64) = unpack('N*', substr($response, $p, 4)); $p += 4; // read matches $idx = -1; while ($count-- > 0 && $p < $max) { // index into result array ++$idx; // parse document id and weight if ($id64) { $doc = sphUnpackU64(substr($response, $p, 8)); $p += 8; list(, $weight) = unpack('N*', substr($response, $p, 4)); $p += 4; } else { list($doc, $weight) = array_values(unpack('N*N*', substr($response, $p, 8))); $p += 8; if (PHP_INT_SIZE >= 8) { // x64 route, workaround broken unpack() in 5.2.2+ if ($doc < 0) { $doc += 1 << 32; } } else { // x32 route, workaround php signed/unsigned braindamage $doc = sprintf('%u', $doc); } } $weight = sprintf('%u', $weight); // create match entry if ($this->_arrayresult) { $result['matches'][$idx] = array('id' => $doc, 'weight' => $weight); } else { $result['matches'][$doc]['weight'] = $weight; } // parse and create attributes $attrvals = array(); foreach ($attrs as $attr => $type) { // handle 64bit ints if ($type == SPH_ATTR_BIGINT) { $attrvals[$attr] = sphUnpackI64(substr($response, $p, 8)); $p += 8; continue; } // handle floats if ($type == SPH_ATTR_FLOAT) { list(, $uval) = unpack('N*', substr($response, $p, 4)); $p += 4; list(, $fval) = unpack('f*', pack('L', $uval)); $attrvals[$attr] = $fval; continue; } // handle everything else as unsigned ints list(, $val) = unpack('N*', substr($response, $p, 4)); $p += 4; if ($type & SPH_ATTR_MULTI) { $attrvals[$attr] = array(); $nvalues = $val; while ($nvalues-- > 0 && $p < $max) { list(, $val) = unpack('N*', substr($response, $p, 4)); $p += 4; $attrvals[$attr][] = sprintf('%u', $val); } } else { $attrvals[$attr] = sprintf('%u', $val); } } if ($this->_arrayresult) { $result['matches'][$idx]['attrs'] = $attrvals; } else { $result['matches'][$doc]['attrs'] = $attrvals; } } list($total, $total_found, $msecs, $words) = array_values(unpack('N*N*N*N*', substr($response, $p, 16))); $result['total'] = sprintf('%u', $total); $result['total_found'] = sprintf('%u', $total_found); $result['time'] = sprintf('%.3f', $msecs / 1000); $p += 16; while ($words-- > 0 && $p < $max) { list(, $len) = unpack('N*', substr($response, $p, 4)); $p += 4; $word = substr($response, $p, $len); $p += $len; list($docs, $hits) = array_values(unpack('N*N*', substr($response, $p, 8))); $p += 8; $result['words'][$word] = array('docs' => sprintf('%u', $docs), 'hits' => sprintf('%u', $hits)); } } $this->_MBPop(); return $results; }