2011-03-04 9 views
6

Estoy haciendo una búsqueda de texto completo en mi tabla MySQL "páginas". Estoy mostrando una lista de páginas que coinciden con la palabra clave en su "título" (texto sin formato, VARCHAR, 255) o "contenido" (html, TEXTO). Cuando la coincidencia se encuentra en el campo "contenido", me gustaría mostrar el fragmento en el que se encontró la coincidencia. No tengo idea de cómo hacerlo.Recuperando el contexto coincidente de la búsqueda de texto completo de MySQL en PHP (y seguridad)

¿Puede ponerme en la dirección correcta?

$query = ' SELECT 
       *, 
       MATCH(title, content) AGAINST("'.$keyword.'") AS score 
      FROM 
       page 
      WHERE 
       MATCH(title, content) AGAINST("'.$keyword.'") 
      ORDER BY 
       score 
      DESC '; 
$result = mysql_query($query) or die (mysql_error()); 
if(mysql_num_rows($result) > 0) { 
    $output .= '<p>Your keyword matches the following pages:</p>'; 
    while($row = mysql_fetch_assoc($result)){ 

     $title  = htmlentities($row['title']); 
     $content = htmlentities(strip_tags($row['content'])); 
     $content = limit_text($content, 250); // Cuts it down to 250 characters plus ... 

     $output .= '<h2>'.$title.'</h2>'; 
     if(trim($content) != '') { 
      $output .= '<p>'.$content.'</p>'; // I'd like to place a snippet here with the matched context 
     }   
    } 
} else { 
    $output .= '<p>Keyword not found...</p>';  
} 

Además, tengo una pregunta con respecto a la seguridad. En este momento estoy comprobando $keyword de tres maneras:

  • No blanco?
  • ¿Más de 2 caracteres?
  • ¿No es peligroso? (Ver más abajo)

Puedo utilizar una expresión regular para que coincida con lo siguiente, para ver si la entrada del usuario es peligroso

<script|&lt;script|&gt;script|document.|alert|bcc:|cc:|x-mailer:|to:|recipient|truncate|drop table 

Esto podría ser un poco ridícula y fácil de solucionar, pero es al menos una forma mínima de protección contra exploits XSS. ¿Cuál es la forma recomendada para proteger el filtrado de una palabra clave destinada a la búsqueda? ¿Es PHPIDS exagerado?

+0

En respuesta a la parte de seguridad de su pregunta, use [PDO] (http://php.net/manual/en/ref.pdo-mysql.php) si puede. De lo contrario, al menos debería ejecutar '$ keyword' a través de' mysql_real_escape_string() '. – glomad

+0

Su protección xss es débil. También es seguro decir que 'drop table' puede ** nunca ** ser para atacar este código porque' mysql_query() 'no permite el apilamiento de consultas. – rook

+0

@itchy gracias, investigaré 'PDO', pero por ahora solo usaré' mysql_real_escape_string() ', gracias. @Rook, gracias por sus ideas, me doy cuenta de esto, es por eso que estoy buscando una alternativa. – maartenmachiels

Respuesta

6

Esto debería comenzar en el "contexto "... parte

// return the part of the content where the keyword was matched 
function get_surrounding_text($keyword, $content, $padding) 
{ 
    $position = strpos($content, $keyword); 
    // starting at (where keyword was found - padding), retrieve 
    // (padding + keyword length + padding) characters from the content 
    $snippet = substr($content, $position - $padding, (strlen($keyword) + $padding * 2)); 
    return '...' . $snippet . '...'; 
} 

$content = 'this is a really long string of characters with a magic word buried somewhere in it'; 
$keyword = 'magic'; 
echo get_surrounding_text($keyword, $content, 15); // echoes '... string with a magic word in it...' 

Esta función no tiene en cuenta los casos en los límites de relleno irían fuera de la cadena de contenido, como cuando la palabra clave se encuentra cerca del principio o al final del contenido. Tampoco da cuenta de múltiples coincidencias, etc. Pero con suerte, al menos, debe apuntar en la dirección correcta.

2

En lugar de tratar de filtrar la variable $keywords usted mismo, usted puede simplemente utilizar un prepared statement y nunca preocuparse por perder un potencial de explotación:

<?php 
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); 
$stmt->bindParam(':name', $name); 
$stmt->bindParam(':value', $value); 

// insert one row 
$name = 'one'; 
$value = 1; 
$stmt->execute(); 

// insert another row with different values 
$name = 'two'; 
$value = 2; 
$stmt->execute(); 
?> 
+0

Gracias por esto ... Encontré un buen tutorial http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/ que me servirá comenzó en PDO. – maartenmachiels

0

probablemente me conseguir el $ palabra clave para una función limpiarlo primero si yo fuera tú. y para el registro, sería mejor poner todas las palabras en $ palabra clave en matriz para que pueda usar boolean search si es necesario. (como poner + delante de cada palabra para obtener Y efecto)

Cuestiones relacionadas