<?php
class buscador{
// para definirlo durante el contructor
public $convertir_enlace = "convertir_enlace_inc.php";
public $xhtml_parte = "xhtml_parte_inc.php";
public $bd = array(); // archivo con la función para buscar en base de datos
private $extensor = array(); /* matriz de objetos para abrir archivos
cada elemento es: "extensión del archivo"=>
array(
"src"=>"archivo donde se encuentra la clase",
"func"=>"nombre de la función que devuelve html o texto plano"
"args"=>argumento adicional al objeto de búsqueda para pasar a la func
)
*/
// para configurar una vez creado el objeto
public $largo = 64; // número de caracteres en cada línea
public $num_lineas = 2;
public $pre_resalte = "<strong>";
public $post_resalte = "</strong>";
public $archivos = array(); // archivos donde buscar
public $puntajes = array("title"=>5,"h1"=>4,"h2"=>3,"h3"=>2);
public $excepto = array(); // lista de archivos y directorios a evitar
public $admitidos = array("php","html"); /* lista de extensiones en las que se buscan,
ordenadas según prioridad para la simplificación de resultados
*/
public $basepost = false;
// generados por las funciones
public $enl = false; // objeto de la clase convertir_enlace
public $dom = false; // objeto de la clase xhtml_parte
public $con = array(); // lista de frases a encontrar
public $sin = array(); // lista de frases que hacen omitir a los resultados
public $resultados = array();
public $log = array();
private $patron_i = ""; // expresión regular para $con
private $patron_e = ""; // expresión regular para $sin
function traslog(){
if($this->enl->log){
foreach($this->enl->log as $entry){
$this->log[] = $entry;
}
}
if($this->dom->log){
foreach($this->dom->log as $entry){
$this->log[] = $entry;
}
}
}
function buscador(){
// cargar el objeto convertir_enlace
// cargar los objetos para abrir distintas extensiones
// incorporar archivo de clase y archivo que llama a $excepto
// arg: url de clase convertir_enlace, url de clase xhtml_parte[, objeto de búsqueda en base de datos[, matriz de extensores]]
$this->convertir_enlace = (func_num_args()>0)?func_get_arg(0):$this->convertir_enlace;
$this->xhtml_parte = (func_num_args()>1)?func_get_arg(1):$this->xhtml_parte;
if($this->incluir($this->convertir_enlace) && $this->incluir($this->xhtml_parte)){
$this->enl = new convertir_enlace($_SERVER["PHP_SELF"]);
$this->dom = new xhtml_parte();
if(func_num_args()>2){
$bd = func_get_arg(2);
if(is_array($bd) && isset($bd["func"]) && isset($bd["src"])){
if($this->incluir($bd["src"])){
$this->bd = $bd;
}
}else{
$this->log[] = 'buscador->bd must be an array like: array("src"=>"dbsearch.php","func"=>"dbsearchin"),
where dbsearchin is a function which first argument is buscador object.';
}
};
$this->extensor = (func_num_args()>3)?func_get_arg(3):$this->extensor;
if(is_array($this->extensor)){
foreach($this->extensor as $ext=>$dat){
if(isset($dat["src"],$dat["func"])){
if(!$this->incluir($dat["src"]) || !function_exists($dat["func"])){
$this->log[] = "source file or function does not exists for extension ".$ext;
unset($this->extensor[$ext]);
}
}else{
$this->log[] = "source file and function name must be setted for each extension manager";
}
}
}else{
$this->log[] = "extensor must be an array";
}
}else{
return false;
}
}
function incluir(){
if(func_num_args()>0){
$archivo = func_get_arg(0);
if(file_exists($archivo)){
include_once($archivo);
$rtrn = true;
}else{
$error = "'".$archivo."' does not exists";
$this->log[] = $error;
$rtrn = false;
}
}else{
$error = "archivo argument has not been defined";
$this->log[] = $error;
$rtrn = false;
}
return $rtrn;
}
function discriminar(){
// separa frases positivas, negativas e indicadores especiales
// arg: cadena
if(func_num_args()>0){
$criterio = " ".func_get_arg(0)." ";
$re_1 = '%\s(\x27[^\x27]+?\x27|\x22[^\x22]+?\x22|-|filetype:(\w+)|\S+)\s%ims';
if(preg_match_all($re_1,$criterio,$frases)){
$con = true;
foreach($frases[1] as $k=>$fras){
if($frases[2][$k]!=""){
$this->admitidos = $frases[2][$k];
}elseif($fras=="-"){
$con = false;
}else{
$frase = htmlentities($fras,ENT_NOQUOTES);
if($con){
$this->patron_i .= (count($this->con)==0)?'':'|';
$this->patron_i .= '\b'.preg_quote($fras,'%');// las palabras deben comenzar en ocurrencias
$this->con[] = preg_replace('%^[\x22\x27]|[\x22\x27]$%ms','',$frase);
}else{
$this->patron_e .= (count($this->sin)==0)?'':'|';
$this->patron_e .= '\b'.$$this->excluidos.'\b';// las ocurrencias deben coincidir con la palabra
$this->sin[] = preg_replace('%^[\x22\x27]|[\x22\x27]$%ms','',$frase);
}
}
}
$rtrn = true;
}else{
$rtrn = false;
$this->log[] = $criterio." no parece un criterio de búsqueda";
}
}else{
$rtrn = false;
$this->log[] = "Debe definirse criterio en discriminar(\$criterio)";
}
return $rtrn;
}
function recorrer(){
// genera lista de rutas desde el directorio
$actual_dir = (func_num_args()>0 && is_string(func_get_arg(0)))?
$this->enl->desde_url(func_get_arg(0)):$this->enl->este["ruta"] ;
if(is_dir($actual_dir)){
$dir = dir($actual_dir);
if(count($this->admitidos)==0){
$this->log[]="there must be at least one extension to search on directoy; it may be declared throught ".
"buscador->adimitidos or throught 'filetype:' at search criteria";
$rtrn = false;
}else{
$actual_dir = preg_replace('%/$%','',$actual_dir);
while(false!==($entrada=$dir->read())){
$ruta = $actual_dir."/".$entrada;
if(!in_array($ruta,$this->excepto) && !in_array($entrada,$this->excepto) && $entrada != "." && $entrada != ".."){
if(is_file($ruta)){
$exten = preg_replace('%^.+\.(\w+)(?:[\?#].*)?$%ims','$1',$entrada);
if(in_array($exten, $this->admitidos)){
$this->archivos[] = $this->enl->desde_ruta($ruta);
}
}elseif(is_dir($ruta)){
$this->log[] = "<br />Intentando entrar al directorio: ".$ruta;
$this->recorrer($ruta);
}
}
}
}
}else{
$this->log[] = $actual_dir." is not a valid directory";
}
}
function abrir_url(){
// obtener el texto de una url mediante get o post
// arg: url/archivo, get/post
if(func_num_args()>0){
$url = func_get_arg(0);
$argum = (func_num_args()>1 )?func_get_arg(1):false;
if (ini_get('allow_url_fopen') == '1') { // '1'
if($argum && is_array($argum)){
$argumentos = http_build_query($argum);
$opts = array('http' =>array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $argumentos
)
);
}else{
$opts = array('http' =>array('method' => 'GET'));
}
$context = stream_context_create($opts);
$content = @file_get_contents($url,false,$context);
if($content === false){
$content = "";
$this->log = "content of ".$url." cannot be getted";
}
} else {
$parsedUrl = parse_url($url);
$host = $parsedUrl['host'];
$path = (isset($parsedUrl['path']))?$parsedUrl['path']:'/';
$path .= (isset($parsedUrl['query']))?'?' . $parsedUrl['query']:'';
$port = (isset($parsedUrl['port']))?$parsedUrl['port']:80;
$timeout = 10;
$content = "";
$fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$fp) {
$$this->log[] = "$errstr ($errno) @ ".$url;
$content = "";
} else {
if($argum && is_array($argum)){
$metodo = "POST";
$argumentos = http_build_query($argum);
$largocont = "Content-length: ".strlen($argumentos)."\r\n\r\n";
}else{
$metodo = "GET";
$argumentos = "";
$largocont = "Content-length: ".$_SERVER["HTTP_CONTENT_LENGTH"]."\r\n\r\n";
}
$out = "$metodo /$path HTTP/1.1\r\n".
"Accept: ".$_SERVER["HTTP_ACCEPT"]."\r\n".
"Accept-Language: ".$_SERVER["HTTP_ACCEPT_LANGUAGE"]."\r\n".
"Host: ".$_SERVER["HTTP_HOST"]."\r\n".
"Referer: ".$_SERVER["HTTP_REFERER"]."\r\n".
"Cookie: ".$_SERVER["HTTP_COOKIE"]."\r\n".
"User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n".
"Content-type: ".$_SERVER["HTTP_CONTENT_TYPE"]."\r\n".
"Accept-Encoding: ".$_SERVER["HTTP_ACCEPT_ENCODING"]."\r\n".
"Accept-Charset: ".$_SERVER["HTTP_ACCEPT_CHARSET"]."\r\n".
"Keep-Alive: ".$_SERVER["HTTP_KEEP_ALIVE"]."\r\n".
"Connection: ".$_SERVER["HTTP_CONNECTION"]."\r\n".
$largocont.
$argumentos;
fwrite($fp, $out);
while (!feof($fp)) {
$content .= fgets($fp, 128);
}
fclose( $fp );
$pos = strpos($content, "\r\n\r\n");
$content = substr($content, $pos + 4);
}
}
$rtrn = $content;
}else{
$this->log[] = "no argument for url in abrir_url";
$rtrn = false;
}
return $rtrn;
}
function oraciones(){
if(func_num_args()>0){
$texto = strip_tags(func_get_arg(0));
if(strlen($texto)<$this->largo){
$rtrn = $texto;
}else{
$ll = 0;
$frass = array();
foreach($this->con as $terio){
$pos = 0;
$leng = strlen($terio);
while($this->largo> ($leng + $pos)){
$pos = stripos($texto,$terio,($pos+$leng));
if($pos===false){
break;
}else{
$frass[$pos]= $terio;
}
}
}
$lineas = "";
ksort($frass);
$largotexto = strlen($texto);
while($largotexto>$this->largo && $ll<$this->num_lineas){
$largo = strlen($texto);
$maximo = 0;
$actual = reset($frass);
$pos = key($frass);
if($pos+$this->largo > $largotexto){
$orac = substr($texto,-$this->largo);
}else{
$orac = substr($texto,$pos,$this->largo);
}
while(next($frass)!==false){
$limite = $pos+$this->largo;
$dens = 1;
$it = 0;
if(key($frass) < $limite){
$dens = 2;
while(next($frass)!==false){
if(key($frass) < $limite){
$dens ++;
}else{
break;
}
$it++;
}
for($i=0;$i<$it;$i++){
$actual = prev($frass);
}
}
if($dens>$maximo){
$maximo=$dens;
$orac = substr($texto,$pos,$this->largo);
}
$pos = key($frass);
}
$texto = str_replace($orac,'',$texto);
$ll++;
$lineas .= ($lineas)?"<br />":"";
$lineas .= $orac;
}
$lineas = preg_replace('%\s+%ms',' ',$lineas);
$lineas = preg_replace('%'.$this->patron_i.'%ims',$this->pre_resalte.'$0'.$this->post_resalte,$lineas);
$rtrn = $lineas;
}
}else{
$this->log[] = "content is needed at oraciones(\$content)";
$rtrn = false;
}
return $rtrn;
// redacta las oraciones a mostrar
}
function calidad(){
// dado el contenido, dar puntaje según $con y $puntajes
if(func_num_args()>0){
$contenido = func_get_arg(0);
$puntaje = 0;
$encontrados = 0;
$titulo = "";
if(is_string($contenido)){
if(strlen($contenido)>4){
$cont = strip_tags($contenido);
/*
*/
if($this->patron_e == "" || !preg_match('%'.$this->patron_e.'%ims',$cont)){
$texto = $contenido;
foreach($this->puntajes as $tag=>$pun){
$tags = $this->dom->etiquetas($texto,$tag,'*','*','nido');
foreach($tags as $t=>$c){
if(isset($c[2]) && preg_match_all('%'.$this->patron_i.'%ims',$c[2],$ma)){
$encontrados += count($ma);
$puntaje += $pun * $encontrados;
}
}
$texto = $this->dom->eliminar(false,$contenido,$tag);
}
$cont2 = strip_tags($texto);;
if(preg_match_all('%'.$this->patron_i.'%ims',$cont2,$ma)){
$encontrados += count($ma);
$puntaje += $encontrados;
$titu = $this->dom->etiquetas($contenido,"title",false,false,'cont');
if(count($titu) > 0 && $titu[0] !=""){
$titulo = $titu[0];
}
}
}
}
$rtrn = array("puntaje"=>$puntaje,"encontrados"=>$encontrados,"titulo"=>$titulo);
}else{
$this->log[] = "content must be a string at calidad(\$content)";
$rtrn = false;
}
}else{
$this->log[] = "content is needed at calidad(\$content)";
$rtrn = false;
}
return $rtrn;
}
function barrer(){
// uno a uno los archivos, revisar si existen.
// Si son html abrirlos, si no convertirlos
// Buscar que no estén los $sin
// Ponderar según calidad()
if(is_array($this->archivos)){
$rtrn = true;
foreach($this->archivos as $archivo){
if(is_string($archivo)){
$file = $archivo;
$param = false;
}elseif(is_array($archivo) &&
isset($archivo[0]) && is_string($archivo[0]) &&
isset($archivo[1]) && is_array($archivo[1])){
$file = $archivo[0];
$param = $archivo[1];
}else{
$this->log[] = "wrong item definition at ".var_export($archivo,true);
$file = false;
}
if($file){
$url = $this->enl->desde_ruta($file);
$exten = preg_replace('%^.+\.(\w+)(?:[\?#].*)?$%ims','$1',$url);
$contenido = $this->abrir_url($url,$param);
if(array_key_exists($exten,$this->extensor)){
if(isset($this->extensor[$exten]["args"])){
$contenido = call_user_func($this->extensor[$exten]["func"],
$contenido,$this,$this->extensor[$exten]["args"]);
}else{
$contenido = call_user_func($this->extensor[$exten]["func"],$contenido,$this);
}
}
$calidad = $this->calidad($contenido);
if(is_array($calidad) && $calidad["encontrados"] > 0){
$calidad["titulo"] = ($calidad["titulo"]!="")?$calidad["titulo"]:$url;
$calidad["oraciones"] = $this->oraciones($contenido);
$calidad["url"] = $url;
$this->resultados[]=$calidad;
}
}
}
}else{
$this->log[] = "\$buscador->archivos must be an array of string with url or ".
"array with url and an array of arguments for post data";
$rtrn = false;
}
return $rtrn;
}
function por_enlaces(){
// permitiría moverse por los vínculos que hay en los documentos, de manera de sólo indicar el dominio y que busque allí
if(func_num_args()>0){
$contenido = func_get_arg(0);
}
}
function en_matriz($sin,$titulo,$orac){
$rtrn = false;
foreach($this->resultados as $k=>$v){
if($k!=$sin && $v["titulo"]==$titulo && $v["oraciones"]==$orac){
$rtrn = true;
break;
}
}
return $rtrn;
}
function ordenar(){
$titulo = array();
$oraciones = array();
$url = array();
$puntaje = array();
$encont = array();
foreach ($this->resultados as $key => $row) {
$titulo[$key] = $row['titulo'];
$oraciones[$key] = $row['oraciones'];
$url[$key] = $row['url'];
$puntaje[$key] = $row['puntaje'];
$encont[$key] = $row['encontrados'];
}
array_multisort($puntaje,SORT_DESC,$encont,SORT_DESC,$titulo,SORT_ASC,$oraciones, SORT_ASC, $url);
$matriz = array();
foreach ($puntaje as $key => $row) {
$matriz[]=array('titulo'=>$titulo[$key],
'oraciones'=>$oraciones[$key],
'url'=>$url[$key],
'puntaje'=>$puntaje[$key],
'encontrados'=>$encont[$key]
);
}
return $matriz;
}
function simplificar(){
// elimina las redundancias cuando encuentra por ej. html y un php que lo abre
foreach($this->resultados as $kr=>$res){
foreach($this->resultados as $k=>$v){
if($k!=$kr && $v["titulo"]==$res["titulo"] && $v["oraciones"]==$res["orac"]){
$nombarch1 = basename($res["url"]);
$exten1 = substr($nombarch1,strrpos(".",$nombarch1));
$nombarch2 = basename($v["url"]);
$exten2 = substr($nombarch2,strrpos(".",$nombarch2));
// si la extensión primera está después en prioridad que la extensión segunda
if(in_array($exten1,$this->admitidos) && in_array($exten2,$this->admitidos)
&& array_search($exten1,$this->admitidos) > array_search($exten2,$this->admitidos)){
unset($this->resultados[$kr]);
}else{
unset($this->resultados[$k]);
}
}
}
}
}
function buscar(){
// argumentos: criterio, recorrer_directorio, simplificar
if(func_num_args()>0){
$criterio = func_get_arg(0);
if($this->discriminar($criterio)){
$recorr = (func_num_args()>1 && func_get_arg(1))?func_get_arg(1):false;
if(is_string($recorr)){
$this->recorrer($recorr);
}elseif($recorr){
$this->recorrer();
}
$rtrn = array();
if(count($this->archivos)>0){
$this->barrer();
}
if(isset($this->bd["func"]) && function_exists($this->bd["func"])){
$bdres = call_user_func($this->bd["func"],$this);
if(is_array($bdres)){
$this->resultados = array_merge($this->resultados, $bdres);
}
}
$rtrn = $this->resultados;
}else{
$rtrn = false;
}
}else{
$rtrn = false;
}
$this->traslog();
return $rtrn;
}
}
?> |