Question

Donc, mon site vient de lancer le serveur aujourd'hui et je pense que cette fonction est le coupable. Est-ce que quelqu'un peut me dire quel est le problème? Je n'arrive pas à comprendre:

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
Était-ce utile?

La solution

Quelque chose comme ça ne serait-il pas plus simple? (OK, je sais que ce n'est pas identique au code envoyé):

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

(La conversion en VB.NET devrait être triviale!)

Remarque: si vous utilisez souvent ce logiciel, vous pouvez améliorer les performances de Regex.

L’une consiste à utiliser une expression précompilée qui nécessite une réécriture légère.

La seconde consiste à utiliser une forme non-capturante de l'expression régulière; Les expressions rationnelles .NET implémentent la syntaxe (? :), ce qui permet d'effectuer un regroupement sans entraîner de pénalité de performances si le texte capturé est mémorisé comme référence arrière. En utilisant cette syntaxe, l'expression régulière ci-dessus peut être modifiée en:

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

Autres conseils

Cette ligne est également incorrecte:

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

Il est garanti de toujours mettre indexNextLeftBracket à indexOfInput, car à ce stade, le caractère à la position indiquée par indexOfInput est déjà toujours un '<'. Faites ceci à la place:

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

Et ajoutez également une clause à l'instruction if pour vous assurer que votre chaîne est suffisamment longue pour cette expression.

Enfin, comme d’autres l’ont déjà dit, ce code sera une bête à maintenir, si vous pouvez le faire fonctionner. Le mieux est de chercher une autre solution, comme une regex ou même simplement remplacer tous les '& Lt;' avec &lt;.

En plus d'autres bonnes réponses, vous pouvez en savoir plus sur les invariants de boucle a un peu. Le fait de retirer et de remettre les éléments sur la chaîne que vous vérifiez pour terminer votre boucle devrait déclencher toutes sortes de sonneries d’alarme. :)

Juste une supposition, mais est-ce que c'est comme le coupable? indexOfInput = str.IndexOf (indexChars (i)) 'recherche d'une instance de indexChar

Conformément à la document Microsoft , retournez Valeur - La position d'index de valeur si cette chaîne est trouvée ou -1 si ce n'est pas le cas. Si la valeur est vide, la valeur renvoyée est 0.

Alors, indexOfInput est peut-être défini sur 0?

Que se passe-t-il si votre code tente de nettoyer la chaîne <a?

Comme je l'ai lu, il trouve indexChar à la position 0, mais ensuite indexNextLeftBracket et indexRightBracket valent tous les deux 0, vous tombez dans la condition else, puis vous insérez un &; > " en position -1, qui sera probablement inséré au début, vous donnant la chaîne ><a. Le nouvel indexRightBracket devient alors 0, vous supprimez donc de la position 0 pour 0 caractères, ce qui vous laisse avec <input type="hidden" name="tax". Ensuite, le code retrouve le <input name="tax" type="hidden" code dans le code et vous êtes prêt pour les courses avec une boucle infinie consommant de la mémoire.

Même si je me trompe, vous devez vous faire passer des tests unitaires pour vous assurer que ces cas extrêmes fonctionnent correctement. Cela devrait également vous aider à trouver le code de la boucle si je ne suis pas basé.

En règle générale, même si vous corrigez ce bogue, il ne sera jamais très robuste. Analyser le HTML est difficile, et les listes noires HTML vont toujours avoir des trous. Par exemple, si je veux vraiment insérer une balise <=>, je l'écrirai simplement comme <=> et votre code l'ignorera. Votre meilleur choix consiste à impliquer un analyseur HTML réel et à n'autoriser que le (très petit) sous-ensemble de balises que vous souhaitez réellement. Ou encore mieux, utilisez une autre forme de balisage et supprimez toutes les balises HTML (en utilisant à nouveau un analyseur HTML réel contenant une description).

Je devrais utiliser un vrai compilateur, mais mindpiler me dit que la ligne str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) génère à nouveau une balise non valide de sorte que, lorsque vous répétez une boucle, elle retrouve la même erreur & ";" correctifs " il essaie encore, trouve l'erreur " répare " elle, etc.

FWIW présente un extrait de code qui supprime les balises HTML non désirées d'une chaîne (c'est en C # mais le concept se traduit)

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 ) );
}

Classe 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 "";
    }
}

Cela ne semble pas fonctionner dans un cas simpliste <a<a<a, ni même <a>Test</a>. Avez-vous testé cela du tout?

Personnellement, je déteste analyser des chaînes de ce genre - je ne vais donc même pas essayer de déterminer où se trouve votre erreur. Il faudrait un débogueur et plus de maux de tête que ce que je suis prêt à mettre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top