Проблема с HTTPModule: замена текста при отображении страницы - PullRequest
1 голос
/ 11 октября 2011

Я пишу HTTPModule, который будет искать все почтовые ссылки на веб-странице, обфусцировать адрес электронной почты и конечные параметры, а затем помещать вновь запутанную строку обратно в документ HTML. Затем я использую небольшой JavaScript-код, чтобы скрыть ссылку mailto в браузере, чтобы она работала правильно, когда пользователь щелкает ссылку.

До сих пор я успешно запутывал и не запутывал информацию без проблем. Проблема, с которой я сталкиваюсь, заключается в размещении запутанных строк обратно в поток. Если ссылка mailto появляется в документе только один раз, то она идеально помещает запутанную строку вместо ссылки mailto, но если существует более одной ссылки mailto, размещение строк выглядит случайным. Я почти уверен, что это связано с положением индексов соответствия регулярному выражению, поскольку функция циклически просматривает совпадения и в основном увеличивает длину HTML, проходящего через поток. Я собираюсь опубликовать здесь некоторый стратегически отредактированный код, чтобы узнать, есть ли у кого-нибудь идея о том, как правильно настроить таргетинг размещения обфусцированной строки.

Я также публикую свою работу по запутыванию строки в надежде, что это может помочь кому-то, пытающемуся сделать то же самое.

public override void Write(byte[] buffer, int offset, int count)
  {
      byte[] data = new byte[count];
      Buffer.BlockCopy(buffer, offset, data, 0, count);
      string html = System.Text.Encoding.Default.GetString(buffer);

      //--- Work on the HTML from the page. We want to pass it through the 
      //--- obfusication function before it is sent to the browser.
      html = html.Replace(html, obfuscate(html));

      byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
      _strmHTML.Write(outdata, 0, outdata.GetLength(0));
  }


protected string obfuscate(string input)
    {

      //--- Declarations
      string email = string.Empty;
      string obsEmail = string.Empty;
      string matchedEMail = string.Empty;
      int matchIndex = 0;
      int matchLength = 0;

      //--- This is a REGEX to grab any "a href=mailto" tags in the document.
      MatchCollection matches = Regex.Matches(input, @"<a href=""mailto:[a-zA-Z0-9\.,|\-|_@?= &]*"">", RegexOptions.Singleline | RegexOptions.IgnoreCase);

      //--- Because of the nature of doing a match search with regex, we must now loop through the results
      //--- of the MatchCollection.
        foreach (Match match in matches)
        {

            //--- Get the match string
            matchedEMail = match.ToString();
            matchIndex = match.Index;
            matchLength = match.Length;

            //--- Obfusicate the matched string.
            obsEmail = obfusucateEmail(@match.Value.ToString());

           //--- Reform the entire HTML stream. THis has to be added back in at the right point.
           input = input.Substring(0, matchIndex) + obsEmail + input.Substring(matchIndex + matchLength);                 
        }

      //--- Return the obfuscated result.
      return input;
    }



protected string obfusucateEmail(string input)
  {

      //--- Declarations
      string email = string.Empty;
      string obsEmail = string.Empty;

      //--- Reset these value, in case we find more than one match.
      email = string.Empty;
      obsEmail = string.Empty;

      //--- Get the email address out of the array
      email = @input;

      //--- Clean up the string. We need to get rid of the beginning of the tag, and the end >. First,
      //--- let's flush out all quotes.
      email = email.Replace("\"", "");

      //--- Now, let's replace the beginning of the tag.
      email = email.Replace("<a href=mailto:", "");

      //--- Finally, let's get rid of the closing tag.
      email = email.Replace(">", "");


      //--- Now, we have a cleaned mailto string. Let's obfusicate it.
      Array matcharray = email.ToCharArray();

      //--- Loop through the CharArray and encode each letter.
      foreach (char letter in matcharray)
      {
          //Convert each letter of the address to the corresponding ASCII code.
          //Add XX to each value to break the direct ASCII code to letter mapping. We'll deal
          // with subtracting XX from each number on the JavaScript side.
          obsEmail += Convert.ToInt32((letter) + 42).ToString() + "~";
      }

      //--- Before we return the obfusicated value, we need to reform the tag.
      //--- Remember, up above, we stripped all this out. Well now, we need 
      //--- to add it again.
      obsEmail = "<a href=\"mailto:" + obsEmail + "\">";

      return obsEmail;
  }

Я ценю любые идеи!

Спасибо, Mike

Ответы [ 2 ]

1 голос
/ 11 октября 2011

Еще одна вещь, которую вы можете сделать, это использовать оценщик совпадений в вашем регулярном выражении ....

protected string ObfuscateUsingMatchEvaluator(string input)
{
            var re = new Regex(@"<a href=""mailto:[a-zA-Z0-9\.,|\-|_@?= &]*"">",            RegexOptions.IgnoreCase | RegexOptions.Multiline);
            return re.Replace(input, DoObfuscation);

}

protected string DoObfuscation(Match match)
{
       return obfusucateEmail(match.Value);
}
0 голосов
/ 11 октября 2011

В зависимости от ваших требований к производительности (помимо прочего, от размера вашего документа), вы можете рассмотреть возможность использования HTML Agility Pack вместо вашего регулярного выражения для анализа и манипулирования вашим HTML.Вы можете использовать Linq to Objects или XPath для идентификации всех ваших тегов mailto.

Вы сможете изменить приведенный ниже пример (из вики-страница codeplex ), чтобы найти теги mailto:

HtmlDocument doc = new HtmlDocument();
 doc.Load("file.htm");
 foreach(HtmlNode link in doc.DocumentElement.SelectNodes("//a[@href"])
 {
    HtmlAttribute att = link["href"];
    if (att.Value.StartsWith("mailto:") EncryptValue(att);
 }
 doc.Save("file.htm");
...