Вопрос

Итак, сегодня мой сайт был удален с сервера, и я думаю, что виновата эта функция.Может ли кто-нибудь сказать мне, в чем проблема?Кажется, я не могу этого понять:

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
Это было полезно?

Решение

Разве что-то подобное не будет проще? (ОК, я знаю, что он не идентичен опубликованному коду):

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

(Преобразование в VB.NET должно быть тривиальным!)

Примечание. Если вы выполняете это часто, вы можете внести в Regex два улучшения производительности.

Одним из них является использование предварительно скомпилированного выражения, которое требует небольшой переписывания.

Во-вторых, нужно использовать не захватывающую форму регулярного выражения; Регулярные выражения .NET реализуют синтаксис (? :), который позволяет выполнять группировку без снижения производительности захваченного текста, который запоминается как обратная ссылка. Используя этот синтаксис, вышеприведенное регулярное выражение можно изменить на:

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

Другие советы

Эта строка также неверна:

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

Гарантируется, что indexNextLeftBracket всегда устанавливается равным indexOfInput, поскольку в этот момент символ в позиции, на которую ссылается indexOfInput, уже всегда равен «<». Сделайте это вместо этого:

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

А также добавьте предложение в оператор if, чтобы убедиться, что ваша строка достаточно длинна для этого выражения.

Наконец, как уже говорили другие, этот код будет чудовищным для поддержки, если вы вообще сможете заставить его работать. Лучше всего искать другое решение, например, регулярное выражение или просто заменить все '& Lt;' с &lt;.

В дополнение к другим хорошим ответам, вы можете немного прочитать о инвариантах цикла a немного. Вытягивание и возврат материала в строку, которую вы проверяете, чтобы завершить цикл, должны вызывать всевозможные сигналы тревоги. :)

Просто предположение, но похоже ли это на виновника? indexOfInput = str.IndexOf (indexChars (i)) 'найти экземпляр indexChar

Согласно документам Microsoft , возврат Значение - Позиция индекса значения, если эта строка найдена, или -1, если это не так. Если значение равно Пусто, возвращаемое значение равно 0.

Так, возможно, indexOfInput устанавливается в 0?

Что произойдет, если ваш код попытается очистить строку <a?

Когда я это прочитал, он находит indexChar в позиции 0, но затем indexNextLeftBracket и indexRightBracket равны 0, вы попадаете в условие else, а затем вставляете «>» в ​​позицию -1, который предположительно будет вставлен в начале, даю тебе веревку ><a.Затем новый indexRightBracket становится равным 0, поэтому вы удаляете из позиции 0 0 символов, оставляя вас с ><a.Затем код находит <a снова в коде, и вы отправляетесь в гонку с бесконечным циклом, потребляющим память.

Даже если я ошибаюсь, вам нужно провести несколько модульных тестов, чтобы убедиться, что эти крайние случаи работают правильно.Это также должно помочь вам найти реальный код цикла, если я отклонился от базы.

Вообще говоря, даже если вы исправите эту конкретную ошибку, она никогда не будет надежной.Анализировать HTML сложно, а в черных списках HTML всегда будут дыры.Например, если я действительно хочу получить <input type="hidden" name="tax" отметьте, я просто напишу это как <input name="tax" type="hidden" и ваш код проигнорирует это.Лучше всего задействовать настоящий анализатор HTML и разрешить только то (очень маленькое) подмножество тегов, которое вам действительно нужно.Или, что еще лучше, используйте какую-нибудь другую форму разметки и удалите все HTML-теги (опять же используя настоящий анализатор HTML с определенным описанием).

Мне нужно было бы запустить его через настоящий компилятор, но разумный ворлер сказал мне, что строка str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) повторно генерирует недопустимый тег, так что при повторном цикле он обнаруживает ту же ошибку " исправления & Quot; он снова пытается найти ошибку " исправляет " это и т. д.

FWIW представляет собой фрагмент кода, который удаляет нежелательные теги HTML из строки (это на C #, но концепция переводит)

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

MatchEvaluator class

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

Похоже, это не работает для упрощенного <a<a<a или даже <a>Test</a>. Вы проверяли это вообще?

Лично я ненавижу такой разбор строк - поэтому я даже не собираюсь пытаться выяснить, где ваша ошибка. Это потребует отладчика и больше головной боли, чем я хочу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top