#region Using
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using BlogEngine.Core;
using BlogEngine.Core.Web.Controls;
#endregion
public partial class User_controls_CommentView : UserControl, ICallbackEventHandler
{
private string _Callback;
#region ICallbackEventHandler Members
public string GetCallbackResult()
{
return _Callback;
}
public void RaiseCallbackEvent(string eventArgument)
{
string[] args = eventArgument.Split(new string[] { "-|-" }, StringSplitOptions.None);
string author = args[0];
string email = args[1];
string website = args[2];
string country = args[3];
string content = args[4];
bool notify = bool.Parse(args[5]);
Comment comment = new Comment();
comment.Id = Guid.NewGuid();
comment.Author = Server.HtmlEncode(author);
comment.Email = email;
comment.Content = Server.HtmlEncode(content);
comment.IP = Request.UserHostAddress;
comment.Country = country;
comment.DateCreated = DateTime.Now;
comment.Parent = Post;
comment.IsApproved = !BlogSettings.Instance.EnableCommentsModeration;
if (Page.User.Identity.IsAuthenticated)
comment.IsApproved = true;
if (website.Trim().Length > 0)
{
if (!website.ToLowerInvariant().Contains("://"))
website = "http://" + website;
Uri url;
if (Uri.TryCreate(website, UriKind.Absolute, out url))
comment.Website = url;
}
if (notify && !Post.NotificationEmails.Contains(email))
Post.NotificationEmails.Add(email);
//else if (!notify && Post.NotificationEmails.Contains(email))
// Post.NotificationEmails.Remove(email);
Post.AddComment(comment);
SetCookie(author, email, website, country);
string path = "~/themes/" + BlogSettings.Instance.Theme + "/CommentView.ascx";
CommentViewBase control = (CommentViewBase)LoadControl(path);
control.Comment = comment;
control.Post = Post;
using (StringWriter sw = new StringWriter())
{
control.RenderControl(new HtmlTextWriter(sw));
_Callback = sw.ToString();
}
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
if (Post == null)
Response.Redirect(Utils.RelativeWebRoot);
if (!Page.IsPostBack && !Page.IsCallback)
{
if (Request.QueryString["deletecomment"] != null)
DeleteComment();
if (!string.IsNullOrEmpty(Request.QueryString["approvecomment"]))
ApproveComment();
if (!string.IsNullOrEmpty(Request.QueryString["approveallcomments"]))
ApproveAllComments();
string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/CommentView.ascx";
//Add approved Comments
foreach (Comment comment in Post.Comments)
{
CommentViewBase control = (CommentViewBase)LoadControl(path);
if (comment.IsApproved || !BlogSettings.Instance.EnableCommentsModeration)
{
control.Comment = comment;
control.Post = Post;
phComments.Controls.Add(control);
}
}
//Add unapproved comments
foreach (Comment comment in Post.Comments)
{
CommentViewBase control = (CommentViewBase)LoadControl(path);
if (!comment.IsApproved && Page.User.Identity.IsAuthenticated)
{
control.Comment = comment;
control.Post = Post;
phComments.Controls.Add(control);
}
}
if (BlogSettings.Instance.IsCommentsEnabled)
{
if (!Post.IsCommentsEnabled || (BlogSettings.Instance.DaysCommentsAreEnabled > 0 &&
Post.DateCreated.AddDays(BlogSettings.Instance.DaysCommentsAreEnabled) < DateTime.Now.Date))
{
phAddComment.Visible = false;
lbCommentsDisabled.Visible = true;
}
BindCountries();
GetCookie();
BindLivePreview();
}
else
{
phAddComment.Visible = false;
}
InititializeCaptcha();
}
btnSave.Click += new EventHandler(btnSave_Click);
}
private void ApproveComment()
{
foreach (Comment comment in Post.NotApprovedComments)
{
if (comment.Id == new Guid(Request.QueryString["approvecomment"]))
{
Post.ApproveComment(comment);
int index = Request.RawUrl.IndexOf("?");
string url = Request.RawUrl.Substring(0, index);
Response.Redirect(url, true);
}
}
}
private void ApproveAllComments()
{
Post.ApproveAllComments();
int index = Request.RawUrl.IndexOf("?");
string url = Request.RawUrl.Substring(0, index);
Response.Redirect(url, true);
}
private void DeleteComment()
{
foreach (Comment comment in Post.Comments)
{
if (comment.Id == new Guid(Request.QueryString["deletecomment"]))
{
Response.Write(Request.Url);
Post.RemoveComment(comment);
int index = Request.RawUrl.IndexOf("?");
string url = Request.RawUrl.Substring(0, index) + "#comment";
Response.Redirect(url, true);
}
}
}
private void btnSave_Click(object sender, EventArgs e)
{
if (!IsCaptchaValid || !Page.IsValid)
Response.Redirect(Post.RelativeLink.ToString(), true);
SaveComment();
SetCookie(txtName.Text, txtEmail.Text, txtWebsite.Text, ddlCountry.SelectedValue);
Response.Redirect(Post.RelativeLink.ToString() + "#addcomment", true);
}
///
/// Saves a comment made from a postback. This only runs when
/// the browser doesn't support AJAX.
///
private void SaveComment()
{
Comment comment = new Comment();
comment.Id = Guid.NewGuid();
comment.Author = txtName.Text;
comment.Email = txtEmail.Text;
comment.IP = Request.UserHostAddress;
comment.Country = ddlCountry.SelectedValue;
comment.Content = Server.HtmlEncode(txtContent.Text);
comment.DateCreated = DateTime.Now;
comment.Parent = Post;
if (txtWebsite.Text.Trim().Length > 0)
{
if (!txtWebsite.Text.ToLowerInvariant().Contains("://"))
txtWebsite.Text = "http://" + txtWebsite.Text;
Uri website;
if (Uri.TryCreate(txtWebsite.Text, UriKind.Absolute, out website))
comment.Website = website;
}
comment.IsApproved = !BlogSettings.Instance.EnableCommentsModeration;
if (Page.User.Identity.IsAuthenticated)
comment.IsApproved = true;
Post.AddComment(comment);
}
///
/// Binds the country dropdown list with countries retrieved
/// from the .NET Framework.
///
public void BindCountries()
{
StringDictionary dic = new StringDictionary();
List col = new List();
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
RegionInfo ri = new RegionInfo(ci.Name);
if (!dic.ContainsKey(ri.EnglishName))
dic.Add(ri.EnglishName, ri.TwoLetterISORegionName.ToLowerInvariant());
if (!col.Contains(ri.EnglishName))
col.Add(ri.EnglishName);
}
col.Sort();
ddlCountry.Items.Add(new ListItem("[Not specified]", ""));
foreach (string key in col)
{
ddlCountry.Items.Add(new ListItem(key, dic[key]));
}
if (ddlCountry.SelectedIndex == 0 && Request.UserLanguages != null && Request.UserLanguages[0].Length == 5)
{
ddlCountry.SelectedValue = Request.UserLanguages[0].Substring(3);
this.SetFlagImageUrl();
}
}
private void BindLivePreview()
{
string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/CommentView.ascx";
CommentViewBase control = (CommentViewBase)LoadControl(path);
Comment comment = new Comment();
comment.Content = string.Empty;
comment.DateCreated = DateTime.Now;
comment.IP = Request.UserHostAddress;
if (!string.IsNullOrEmpty(txtName.Text))
comment.Author = txtName.Text;
if (!string.IsNullOrEmpty(txtEmail.Text))
comment.Email = txtEmail.Text;
if (txtWebsite.Text.Trim().Length > 0)
{
if (!txtWebsite.Text.ToLowerInvariant().Contains("://"))
txtWebsite.Text = "http://" + txtWebsite.Text;
Uri website;
if (Uri.TryCreate(txtWebsite.Text, UriKind.Absolute, out website))
comment.Website = website;
}
control.Comment = comment;
control.Post = Post;
phLivePreview.Controls.Add(control);
}
///
/// Validates that the name of the person writing posting a comment
/// cannot be the same as the author of the post.
///
protected void CheckAuthorName(object sender, ServerValidateEventArgs e)
{
e.IsValid = true;
if (!Page.User.Identity.IsAuthenticated)
{
if (txtName.Text.ToLowerInvariant() == Post.Author.ToLowerInvariant())
e.IsValid = false;
}
}
private void SetFlagImageUrl()
{
if (!string.IsNullOrEmpty(ddlCountry.SelectedValue))
{
imgFlag.ImageUrl = Utils.RelativeWebRoot + "pics/flags/" + ddlCountry.SelectedValue + ".png";
}
else
{
imgFlag.ImageUrl = Utils.RelativeWebRoot + "pics/pixel.png";
}
}
#region Cookies
///
/// Sets a cookie with the entered visitor information
/// so it can be prefilled on next visit.
///
private void SetCookie(string name, string email, string website, string country)
{
HttpCookie cookie = new HttpCookie("comment");
cookie.Expires = DateTime.Now.AddMonths(24);
cookie.Values.Add("name", Server.UrlEncode(name));
cookie.Values.Add("email", email);
cookie.Values.Add("url", website);
cookie.Values.Add("country", country);
Response.Cookies.Add(cookie);
}
///
/// Gets the cookie with visitor information if any is set.
/// Then fills the contact information fields in the form.
///
private void GetCookie()
{
HttpCookie cookie = Request.Cookies["comment"];
if (cookie != null)
{
txtName.Text = Server.UrlDecode(cookie.Values["name"]);
txtEmail.Text = cookie.Values["email"];
txtWebsite.Text = cookie.Values["url"];
ddlCountry.SelectedValue = cookie.Values["country"];
this.SetFlagImageUrl();
}
else if (Page.User.Identity.IsAuthenticated)
{
MembershipUser user = Membership.GetUser();
txtName.Text = user.UserName;
txtEmail.Text = user.Email;
txtWebsite.Text = Request.Url.Host;
}
}
#endregion
#region CAPTCHA
///
/// Gets whether or not the user is human
///
private bool IsCaptchaValid
{
get
{
if (ViewState["captchavalue"] != null)
{
return Request.Form[ViewState["captchafield"].ToString()] == ViewState["captchavalue"].ToString();
}
return false;
}
}
///
/// Initializes the captcha and registers the JavaScript
///
private void InititializeCaptcha()
{
if (ViewState["captchavalue"] == null)
{
ViewState["captchavalue"] = Guid.NewGuid().ToString();
ViewState["captchafield"] = Guid.NewGuid().ToString();
}
StringBuilder sb = new StringBuilder();
sb.Append("function SetCaptcha(){");
sb.Append("var form = $('" + Page.Form.ClientID + "');");
sb.Append("var el = document.createElement('input');");
sb.Append("el.type = 'hidden';");
sb.Append("el.name = '" + ViewState["captchafield"] + "';");
sb.Append("el.value = '" + ViewState["captchavalue"] + "';");
sb.Append("form.appendChild(el);}");
Page.ClientScript.RegisterClientScriptBlock(GetType(), "captchascript", sb.ToString(), true);
Page.ClientScript.RegisterOnSubmitStatement(GetType(), "captchayo", "SetCaptcha()");
}
#endregion
#region Protected methods and properties
///
/// The regular expression used to parse links.
///
private static Regex regex =
new Regex("((http://|www\\.)([A-Z0-9.-]{1,})\\.[0-9A-Z?&=-_\\./]{2,})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private Post _Post;
///
/// Gets or sets the post from which the comments are parsed.
///
public Post Post
{
get { return _Post; }
set { _Post = value; }
}
///
/// Examins the comment body for any links and turns them
/// automatically into one that can be clicked.
///
/// All links added to comments will have the rel attribute set
/// to nofollow to prevent negative pagerank.
///
///
protected string ResolveLinks(string body)
{
foreach (Match match in regex.Matches(body))
{
if (!match.Value.Contains("://"))
body = body.Replace(match.Value, regex.Replace(body, "$1"));
else
body = body.Replace(match.Value, regex.Replace(body, "$1"));
}
return body.Replace(Environment.NewLine, "
");
}
///
/// Displays a delete link to visitors that is authenticated
/// using the default membership provider.
///
/// The id of the comment.
protected string AdminLink(string id)
{
if (Page.User.Identity.IsAuthenticated)
{
StringBuilder sb = new StringBuilder();
foreach (Comment comment in Post.Comments)
{
if (comment.Id.ToString() == id)
sb.AppendFormat(" | {0}", comment.Email);
}
string confirmDelete = "Are you sure you want to delete the comment?";
sb.AppendFormat(" | {2}",
id.ToString(), confirmDelete, "Delete");
return sb.ToString();
}
return string.Empty;
}
///
/// Displays the Gravatar image that matches the specified email.
///
protected string Gravatar(string email, string name, int size)
{
if (email.Contains("://"))
return
string.Format(
"
", name,
email);
//http://www.artviper.net/screenshots/screener.php?&url={0}&h={1}&w={1}
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(email));
StringBuilder hash = new StringBuilder();
for (int i = 0; i < result.Length; i++)
hash.Append(result[i].ToString("x2"));
StringBuilder image = new StringBuilder();
image.Append("
");
return image.ToString();
}
#endregion
}