Login   Register  
PHP Classes
elePHPant
Icontem

File: buscador_inc.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Patricio Cardó  >  Buscador  >  buscador_inc.php  >  Download  
File: buscador_inc.php
Role: Class source
Content type: text/plain
Description: class file
Class: Buscador
Crawl and search files and Web pages
Author: By
Last change: abrir_url method was fixed to open within security environments
Date: 2010-08-05 07:16
Size: 17,872 bytes
 

Contents

Class file image Download
<?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&uacute;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;
	}
}
?>