Pregunta

Así que hoy acabo de sacar mi sitio del servidor y creo que esta función es la culpable.Alguien puede decirme cuál es el problema?Parece que no puedo entenderlo:

Public Function CleanText(ByVal str As String) As String    
'removes HTML tags and other characters that title tags and descriptions don't like
    If Not String.IsNullOrEmpty(str) Then
        'mini db of extended tags to get rid of
        Dim indexChars() As String = {"<a", "<img", "<input type=""hidden"" name=""tax""", "<input type=""hidden"" name=""handling""", "<span", "<p", "<ul", "<div", "<embed", "<object", "<param"}

        For i As Integer = 0 To indexChars.GetUpperBound(0) 'loop through indexchars array
            Dim indexOfInput As Integer = 0
            Do 'get rid of links
                indexOfInput = str.IndexOf(indexChars(i)) 'find instance of indexChar
                If indexOfInput <> -1 Then
                    Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1
                    Dim indexRightBracket As Integer = str.IndexOf(">", indexOfInput) + 1
                    'check to make sure a right bracket hasn't been left off a tag
                    If indexNextLeftBracket > indexRightBracket Then 'normal case
                        str = str.Remove(indexOfInput, indexRightBracket - indexOfInput)
                    Else
                        'add the right bracket right before the next left bracket, just remove everything
                        'in the bad tag
                        str = str.Insert(indexNextLeftBracket - 1, ">")
                        indexRightBracket = str.IndexOf(">", indexOfInput) + 1
                        str = str.Remove(indexOfInput, indexRightBracket - indexOfInput)
                    End If
                End If
            Loop Until indexOfInput = -1
        Next
    End If
    Return str
End Function
¿Fue útil?

Solución

¿No sería algo así como más simple? (OK, sé que no es idéntico al código publicado):

public string StripHTMLTags(string text)
{
    return Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
}

(¡La conversión a VB.NET debería ser trivial!)

Nota: si está ejecutando esto con frecuencia, hay dos mejoras de rendimiento que puede realizar en Regex.

Una es usar una expresión precompilada que requiera reescribir ligeramente.

El segundo es usar una forma no capturadora de la expresión regular; Las expresiones regulares .NET implementan la sintaxis (? :), que permite que la agrupación se realice sin incurrir en la penalización de rendimiento del texto capturado que se recuerda como referencia. Usando esta sintaxis, la expresión regular anterior podría cambiarse a:

@"<(?:.|\n)*?>"

Otros consejos

Esta línea también está mal:

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1

Se garantiza que siempre establece indexNextLeftBracket igual a indexOfInput, porque en este punto el carácter en la posición referida por indexOfInput ya es siempre un '<'. Haga esto en su lugar:

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput+1) + 1

Y también agregue una cláusula a la instrucción if para asegurarse de que su cadena sea lo suficientemente larga para esa expresión.

Finalmente, como otros han dicho, este código será una bestia para mantener, si es que puedes hacerlo funcionar. Lo mejor es buscar otra solución, como una expresión regular o incluso simplemente reemplazar todo '& Lt;' con &lt;.

Además de otras buenas respuestas, puede leer un poco sobre invariantes de bucle a un poco. Al tirar y volver a colocar cosas en la cadena que verifica para terminar su ciclo, debe activar todo tipo de alarmas. :)

Solo una suposición, pero ¿es esto como el culpable? indexOfInput = str.IndexOf (indexChars (i)) 'buscar instancia de indexChar

Por documentos de Microsoft , Volver Valor - La posición de índice del valor si se encuentra esa cadena, o -1 si no lo es. Si el valor está vacío, el valor de retorno es 0.

¿Entonces quizás indexOfInput se establece en 0?

¿Qué sucede si su código intenta limpiar la cadena? <a?

Mientras lo leo, encuentra indexChar en la posición 0, pero luego indexNextLeftBracket e indexRightBracket son iguales a 0, caes en la condición else y luego insertas un ">" en la posición -1, que presumiblemente se insertará al principio. dándote la cuerda ><a.El nuevo indexRightBracket entonces se convierte en 0, por lo que elimina de la posición 0 los 0 caracteres, dejándolo con ><a.Entonces el código encuentra el <a en el código nuevamente y estarás listo para las carreras con un bucle infinito que consume memoria.

Incluso si me equivoco, necesita realizar algunas pruebas unitarias para asegurarse de que estos casos extremos funcionan correctamente.Eso también debería ayudarte a encontrar el código de bucle real si no estoy en la base.

Sin embargo, en términos generales, incluso si solucionas este error en particular, nunca será muy sólido.Analizar HTML es difícil y las listas negras de HTML siempre tendrán agujeros.Por ejemplo, si realmente quiero conseguir un <input type="hidden" name="tax" etiquétalo, lo escribiré como <input name="tax" type="hidden" y tu código lo ignorará.Su mejor opción es involucrar un analizador HTML real y permitir solo el subconjunto (muy pequeño) de etiquetas que realmente desea.O incluso mejor, use alguna otra forma de marcado y elimine todas las etiquetas HTML (nuevamente usando un analizador HTML real de alguna descripción).

Tendría que ejecutarlo a través de un compilador real, pero el mindpiler me dice que la línea str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) está volviendo a generar una etiqueta no válida, de modo que cuando vuelva a recorrerlo encuentre el mismo error " arregla " , intenta de nuevo, encuentra el error " corrige " eso, etc.

FWIW es un fragmento de código que elimina las etiquetas HTML no deseadas de una cadena (está en C # pero el concepto se traduce)

public static string RemoveTags( string html, params string[] allowList )
{
    if( html == null ) return null;
    Regex regex = new Regex( @"(?<Tag><(?<TagName>[a-z/]+)\S*?[^<]*?>)",
                             RegexOptions.Compiled | 
                             RegexOptions.IgnoreCase | 
                             RegexOptions.Multiline );
    return regex.Replace( 
                   html, 
                   new MatchEvaluator( 
                       new TagMatchEvaluator( allowList ).Replace ) );
}

Clase MatchEvaluator

private class TagMatchEvaluator
{
    private readonly ArrayList _allowed = null;

    public TagMatchEvaluator( string[] allowList ) 
    { 
        _allowed = new ArrayList( allowList ); 
    }

    public string Replace( Match match )
    {
        if( _allowed.Contains( match.Groups[ "TagName" ].Value ) )
            return match.Value;
        return "";
    }
}

Eso no parece funcionar para un caso simplista <a<a<a, o incluso <a>Test</a>. ¿Probaste esto en absoluto?

Personalmente, odio el análisis de cadenas como este, así que ni siquiera voy a tratar de averiguar dónde está tu error. Requeriría un depurador y más dolor de cabeza del que estoy dispuesto a poner.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top