예제 #1
0
 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;
 }
예제 #2
0
 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;
 }
예제 #3
0
 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;
 }