Domanda

Quindi oggi ho appena rimosso il mio sito dal server e penso che questa sia la causa. Qualcuno può dirmi qual è il problema? Non riesco a capirlo:

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
È stato utile?

Soluzione

Qualcosa del genere non sarebbe più semplice? (OK, so che non è identico al codice pubblicato):

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

(La conversione in VB.NET dovrebbe essere banale!)

Nota: se lo esegui spesso, ci sono due miglioramenti delle prestazioni che puoi apportare a Regex.

Uno è usare un'espressione precompilata che richiede una riscrittura leggermente.

Il secondo è usare una forma non catturante dell'espressione regolare; Le espressioni regolari .NET implementano la sintassi (? :), che consente di eseguire il raggruppamento senza incorrere nella penalità prestazionale del testo acquisito che viene ricordato come riferimento. Usando questa sintassi, l'espressione regolare sopra potrebbe essere cambiata in:

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

Altri suggerimenti

Anche questa riga è errata:

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

È garantito che setta sempre indexNextLeftBracket uguale a indexOfInput, perché a questo punto il carattere nella posizione a cui fa riferimento indexOfInput è già sempre un '<'. Fallo invece:

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

E aggiungi anche una clausola all'istruzione if per assicurarti che la tua stringa sia abbastanza lunga per quell'espressione.

Infine, come altri hanno già detto, questo codice sarà una bestia da mantenere, se riuscirai a farlo funzionare. Meglio cercare un'altra soluzione, come un regex o anche semplicemente sostituire tutto '& Lt;' con &lt;.

Oltre ad altre buone risposte, potresti leggere un po 'su loop invariants a un po. Estrarre e rimettere roba sulla corda che controlli per terminare il tuo loop dovrebbe innescare tutti i tipi di campanelli d'allarme. :)

Solo un'ipotesi, ma è come il colpevole? indexOfInput = str.IndexOf (indexChars (i)) 'trova istanza di indexChar

Per documenti Microsoft , ritorno Valore - La posizione dell'indice del valore se viene trovata quella stringa o -1 se non lo è. Se il valore è vuoto, il valore restituito è 0.

Quindi forse indexOfInput è impostato su 0?

Cosa succede se il tuo codice tenta di pulire la stringa <a?

Mentre lo leggo, trova indexChar nella posizione 0, ma poi indexNextLeftBracket e indexRightBracket sono entrambi uguali a 0, cadi nella condizione else e quindi inserisci un " > " nella posizione -1, che presumibilmente inserirà all'inizio, dandoti la stringa ><a. Il nuovo indexRightBracket diventa quindi 0, quindi elimini dalla posizione 0 per 0 caratteri, lasciandoti con <input type="hidden" name="tax". Quindi il codice trova di nuovo <input name="tax" type="hidden" nel codice e sei in corsa con un ciclo infinito che consuma memoria.

Anche se sbaglio, è necessario sottoporsi ad alcuni test unitari per rassicurarsi sul fatto che questi casi limite funzionano correttamente. Ciò dovrebbe anche aiutarti a trovare il codice di loop effettivo se sono off-base.

In generale però, anche se risolvi questo particolare bug, non sarà mai molto robusto. L'analisi dell'HTML è difficile e le blacklist HTML avranno sempre buchi. Ad esempio, se voglio davvero ottenere un tag <=>, lo scrivo semplicemente come <=> e il tuo codice lo ignorerà. La soluzione migliore è coinvolgere un vero parser HTML e consentire solo il sottoinsieme (molto piccolo) di tag che si desidera effettivamente. O ancora meglio, usa qualche altra forma di markup e rimuovi tutti i tag HTML (usando ancora un vero parser HTML con qualche descrizione).

Dovrei eseguirlo attraverso un vero compilatore, ma il mindpiler mi dice che la riga str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) sta rigenerando un tag non valido in modo tale che quando si ripercorre nuovamente trova lo stesso errore " fixes " esso, riprova, trova l'errore " corregge " esso, ecc.

FWIW ecco uno snippet di codice che rimuove tag HTML indesiderati da una stringa (è in C # ma il concetto si 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 ) );
}

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

Ciò non sembra funzionare per un <a<a<a caso semplicistico, o anche <a>Test</a>. Hai provato questo?

Personalmente, odio analizzare le stringhe in questo modo - quindi non proverò nemmeno a capire dove si trova il tuo errore. Richiederebbe un debugger e più mal di testa di quello che sono disposto a inserire.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top