WebSurfer's Home

トップ > Blog 2   |   ログイン
APMLフィルター

スパムコメントの表示

by WebSurfer 2011年6月17日 22:48

スパムコメントはいかなる場合も一般閲覧者の目に触れないようにしたいというのが普通だと思います。

しかしながら、バージョン 2.0 ではコントロールパネルで「コメント確認後に公開」にチェックを入れておかないと、自動モデレーションでスパムに分類されたコメントを含め、すべてのコメントが公開されてしまいます。

また、管理者が閲覧した場合は、スパムを含めてすべてのコメントが表示されますが、同じスパムコメントが 2 回づつ表示されてしまうという不具合があります。

上記の不具合を解消して、コメントの表示が期待通りになるよう、User controls/CommentView.ascx.cs の OnLoad メソッドの一部を以下のように変更しました。

if (this.NestingSupported)
{
  // コメントをネストして表示するオプションを選ぶと以下が
  // 実行される。その場合は、期待通り、スパムに分類された
  // コメントは一般閲覧者には表示されないし、管理者に対し
  // て同じスパムが 2 回表示されるということもない。
  if (this.Post != null)
  {
    this.AddNestedComments(
      path, 
      this.Post.NestedComments, 
      this.phComments, 
      canViewUnpublishedPosts);
  }
}
else
{
  // コメントをネストして表示しない場合は以下が実行される。
  // その場合「コメント確認後に公開」にチェックしないと:
  // 1) 一般閲覧者にスパムコメントが表示されてしまう。
  // 2) 管理者にはスパムコメントが 2 回表示されてしまう。
                    
  //foreach (var comment in
  //  this.Post.Comments.Where(
  //    comment => comment.Email != "pingback" && 
  //      comment.Email != "trackback"))
  //{
  //  if (comment.IsApproved)
  //  {
  //    this.CommentCounter++;
  //  }

  //  if (!comment.IsApproved && 
  //    BlogSettings.Instance.EnableCommentsModeration)
  //  {
  //    continue;
  //  }

  //  var control = (CommentViewBase)this.LoadControl(path);
  //  control.Comment = comment;
  //  control.Post = this.Post;
  //  this.phComments.Controls.Add(control);
  //}

  // Add unapproved comments
  //if (canViewUnpublishedPosts)
  //{
  //  foreach (var comment in this.Post.Comments)
  //  {
  //    if (comment.Email == "pingback" || 
  //      comment.Email == "trackback")
  //    {
  //            continue;
  //        }

  //        if (comment.IsApproved)
  //        {
  //            continue;
  //        }

  //        var control = (CommentViewBase)this.LoadControl(path);
  //        control.Comment = comment;
  //        control.Post = this.Post;
  //        this.phComments.Controls.Add(control);
  //    }
  //}

  // AddNestedComments と同じ内容(再帰呼び出しを除く)とすれ
  // ば期待した結果となる。
  foreach (Comment comment in this.Post.Comments)
  {
    if ((!comment.IsApproved && 
      BlogSettings.Instance.EnableCommentsModeration) &&
      (comment.IsApproved || !canViewUnpublishedPosts))
    {
      continue;
    }

    if (comment.IsSpam && !canViewUnpublishedPosts)
    {
      continue;
    }

    if (comment.Email == "pingback" || 
      comment.Email == "trackback")
    {
      continue;
    }

    var control = (CommentViewBase)this.LoadControl(path);
    control.Comment = comment;
    control.Post = this.Post;
    this.phComments.Controls.Add(control);

    if (comment.IsApproved)
    {
      this.CommentCounter++;
    }
  }
}

Tags:

BlogEngine.NET 2.0

W3C 検証にパスしない

by WebSurfer 2011年6月13日 23:23

BlogEngine.NET はバージョン 2.0 になって W3C Markup Validation Service にパスしなくなってしまいました。

原因は、以下のように、外部スクリプトファイルの定義にクエリ文字列 &minify= が追加されたことによります。& そのままでなく、HTML エンコードして & にしないとパスしません。

<script 
  type="text/javascript" 
  src="/BlogEngine2/js.axd?path=Scripts%2fblog.js&minify=">
</script>
<script 
  type="text/javascript" 
  src="/BlogEngine2/js.axd?path=%2fBlogEngine2%2fadmin%2fwidget.js&minify=">
</script>

この問題を解決するには、Core.Utils の ResolveScriptUrl メソッドを以下のように修正します。

public static string ResolveScriptUrl(string url, bool minify)
{
  var minifyQuery = (minify ? "&minify=" : String.Empty);

  //return string.Format("{0}js.axd?path={1}{2}", 
  //  Utils.RelativeWebRoot,
  //  HttpUtility.UrlEncode(url),
  //  minifyQuery);

  return string.Format("{0}js.axd?path={1}{2}",
    Utils.RelativeWebRoot,
    HttpUtility.UrlEncode(url),
    HttpUtility.HtmlEncode(minifyQuery));
}

さらに、ページングする際に &page=n(n はページ番号)というクエリ文字列がページャーのリンクの URL に追加される場合があります。その場合はやはり W3C Markup Validation は通りません。この問題はバージョン 1.6.1 にもありましたが、今まで気がつきませんでした。(汗)

App_Code/Control/PostPager.cs の PageUrl メソッド

これはバージョン 2.0 のページャー用に追加されたものです(バージョン 1.6.1 にはありません)。

private static string PageUrl()
{
  var path = 
    HttpContext.Current.Request.RawUrl.
    Replace("Default.aspx", string.Empty);
  if (path.Contains("?"))
  {
    if (path.Contains("page="))
    {
      var index = path.IndexOf("page=");
      path = path.Substring(0, index);
    }
    else
    {                    
      // ここで単純に path += "&amp;"; としてもダメ。
      path += "&";
    }
  }
  else
  {
    path += "?";
  }

  // これを追加。
  path = path.Replace("&", "&amp;");

  return path + "page={0}";
}

User controls/PostList.ascx.cs の InitPaging メソッド

これはバージョン 2.0 と 1.6.1 両方にあります。バージョン 2.0 では、これを使うページャーは style="display: none" となっており表示はされませんが、html コードには現れてくるので修正が必要です。

private void InitPaging()
{            
  var path = 
    this.Request.RawUrl.Replace("Default.aspx", string.Empty);

  path = path.Contains("?") ? 
    (path.Contains("page=") ? 
      path.Substring(0, path.IndexOf("page=")) 
      : string.Format("{0}&", path))
    : string.Format("{0}?", path);

  var page = this.GetPageIndex();
  var url = string.Format("{0}page={{0}}", path);

  // 下記の追加のみ
  url = url.Replace("&", "&amp;");

  this.hlNext.HRef = string.Format(url, page);
  this.hlPrev.HRef = string.Format(url, page + 2);

  if (page == 0)
  {
    this.hlNext.Visible = false;
  }
  else
  {
     ((BlogBasePage)this.Page).AddGenericLink(
       "next", 
       "Next page", 
       this.hlNext.HRef);
  }

  if (this.hlPrev.Visible)
  {
    ((BlogBasePage)this.Page).AddGenericLink(
      "prev", 
      "Previous page", 
      string.Format(url, page + 2));
  }
}

Tags:

BlogEngine.NET 2.0

日本語の著者名の問題

by WebSurfer 2011年6月13日 23:14

各記事の左上に著者名が表示されます。この記事では By WebSurfer がそれです。この著者名をクリックすると、その著者が投稿した記事が選択され表示されるようになっています。(BlogEngine.NET は複数の投稿者を許しています)

ところが、著者名に日本語(たぶん、その他の Multi-Byte 文字も)を使うと、著者名のリンクをクリックしても何も選択されない(従って記事は何も表示されない)という問題があります。

例えば、著者名が "日本太郎" の場合、リンクの URL には以下のように設定されます。

http://surferonwww.info/BlogEngine2/author/日本太郎.aspx

このリンクをクリックすると、ブラウザはこれを URL エンコードしてからサーバーに送信し、これを受けたサーバーは、URL をデコードしてから UrlRewrite モジュールで以下のように書き換えます。

http://surferonwww.info/BlogEngine2/default.aspx?name=日本太郎

default.aspx.cs で、以下のコードで著者名を取得しようとしていますが、URL エンコードしてない生 UTF-8 なので正しく取得できません。

string author = Server.UrlDecode(Request.QueryString["name"]);

結果、著者名が日本語の場合は、著者名が正しく取得できないので著者に関連する記事を選択できず、何も表示されないということになります。

この問題を解決するには、default.aspx.cs に渡すクエリ文字列を URL エンコードしてやります。さらに、default.aspx.cs でクエリ文字列から著者名を取得する際デコードしないようにします。

具体的には以下のとおり修正しました。これで問題なく動いています。

Core/Web/HttpModule/UrlRewrite.cs の ContextBeginRequest メソッド

else if (url.Contains("/AUTHOR/"))
{
  // 日本語の author 名が認識されないので修正。具体的には、
  // author → context.Server.UrlEncode(author) としたのみ。
                
  var author = ExtractTitle(context, url);
  context.RewritePath(
    string.Format("{0}default{1}?name={2}{3}", 
      Utils.RelativeWebRoot, 
      BlogSettings.Instance.FileExtension, 
      context.Server.UrlEncode(author), 
      GetQueryString(context)),
    false);
}

default.aspx.cs の DisplayAuthors メソッド

private void DisplayAuthors()
{
  if (!string.IsNullOrEmpty(Request.QueryString["name"]))
  {
    // UrlDecode は不要なので以下の行を変更。
    //string author = Server.UrlDecode(Request.QueryString["name"]);

    string author = Request.QueryString["name"];

    PostList1.ContentBy = ServingContentBy.Author;
    PostList1.Posts = 
      Post.GetPostsByAuthor(author).ConvertAll(
        new Converter<Post, IPublishable>(delegate(Post p) 
          { return p as IPublishable; }));
    Title = "All posts by " + Server.HtmlEncode(author);
  }
}

なお、この問題は 1.6.1 では発生しません。

1.6.1 の場合、RemoveIllegalCharacters メソッドで UrlEncode が使われ、さらにそれから '%' 文字が除去された著者名がリンクの URL のクエリ文字列に設定されます。従って、DisplayAuthors メソッドで取得できる author はクエリ文字列に設定されたものと全く同じです。

それが Post.GetPostsByAuthor メソッドの引数として渡され、Post.Author で取得した著者名に RemoveIllegalCharacters メソッドを適用した文字列と比較され、一致する記事が選択されます。

ただし、Title に表示される著者名は、RemoveIllegalCharacters メソッドで変換された文字列になります(正しい日本語にはなりません)。

Tags:

BlogEngine.NET 2.0

About this blog

ここブログ2は日々の出来事、ブログ1はプログラミング関係のトピックスになっています。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar