Blog转换至WordPress
已从Blogengine完整转到wp程序
顺便把apple的也给转了.
日志与评论均已转换,分类就没有转了。
链接方面也没有转,准备手工加一下。
所有的日志链接已做301跳转,
ps,wp后台发布日志真叫慢啊。。
面朝大海,春暖花开
已从Blogengine完整转到wp程序
顺便把apple的也给转了.
日志与评论均已转换,分类就没有转了。
链接方面也没有转,准备手工加一下。
所有的日志链接已做301跳转,
ps,wp后台发布日志真叫慢啊。。
该插件将评论者的IP转为地区,数据取自于http://www.ip138.com
在这里表示感谢!
该扩展要在CommentAdded事件上进行处理,首先添加一个字段UserArea用来保存地区。
放心,这里的是异步处理的,不会造成页面的明显延迟。
代码如下:
/// <summary>
///Ip2Area 的摘要说明
/// </summary>
///
[Extension("IP转为地区", "1.0", "JasonYi")]
public class Ip2Area
{
public Ip2Area()
{
Post.CommentAdded += new EventHandler<EventArgs>(Post_CommentAdded);
}
void Post_CommentAdded(object sender, EventArgs e)
{
Comment p = sender as Comment;
if(p!=null)
new HttpAsyncGetIPArea(p,"http://www.ip138.com/ips.asp").Execute();
}
}
public class HttpAsyncGetIPArea
{
private Comment _comment;
private string _url;
public HttpAsyncGetIPArea(Comment c,string url)
{
_comment = c;
_url = url;
}
public Comment comment
{
get { return _comment; }
}
private HttpWebRequest Request;
public void Execute()
{
Request = (HttpWebRequest)WebRequest.Create(_url);
Request.Method = "POST";
Request.ContentType = "application/x-www-form-urlencoded";
Byte[] data = System.Text.Encoding.ASCII.GetBytes("action=2&ip=" + _comment.IP);
Request.ContentLength = data.Length;
using (Stream stream = Request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
Request.BeginGetResponse(ProcessRespose, this);
}
private void ProcessRespose(IAsyncResult async)
{
HttpAsyncGetIPArea item = (HttpAsyncGetIPArea)async.AsyncState;
try
{
using (HttpWebResponse response = (HttpWebResponse)item.Request.EndGetResponse(async))
{
string RStr = string.Empty;
using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default))
{
RStr = sr.ReadToEnd();
}
Regex reg = new Regex(@"本站主数据:([^<li>]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
MatchCollection mc = reg.Matches(RStr);
string area = string.Empty;
if (mc.Count > 0)
{
area = mc[0].Value.Replace("本站主数据:", string.Empty);
}
if (!string.IsNullOrEmpty(area))
{
string sql = "UPDATE be_PostComment SET UserArea=@Area WHERE PostCommentID=@Id";
SqlParameter[] para = { new SqlParameter("@Area", area), new SqlParameter("@Id", comment.Id) };
SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionString, System.Data.CommandType.Text, sql, para);
comment.UserArea = area;
}
}
}
catch (Exception ex)
{
//throw new System.Net.WebException("Get HttpResponse Error");
}
finally
{
Request.Abort();
}
}
}
这里的对日志加密是指输入正确密码以后才能正常访问。
示例:
http://www.yibin001.com/Archives/6035.aspx
密码:123456
针对于BlogEngine来说,可以用它丰富的插件机制来实现。
首先明确,完成这个插件需要做哪些工作:
1、数据表结构的变化。要增加密码项,“密码”字段当然是少不了了。
2、表结构的变化势必会引起Post实体类属性的变化。
3、Post.Serving时触发事件,该事件负责针对性的改变e.Body
4、认证的实现。
这里我用的是SqlServer数据库,打开be_Posts表,执行以下语句
ALTER TABLE dbo.be_Posts ADD AccessPassword VARCHAR(100) NOT NULL DEFAULT '' GO
对应地在BlogEngine.Core.Post中增加属性AccessPassword
private string _AccessPassword = string.Empty;
public string AccessPassword
{
get { return _AccessPassword; }
set {
if (_AccessPassword != value) MarkChanged("AccessPassword");
_AccessPassword = value;
}
}
这里的AccessPassword不为空表明该日志需要密码才能访问。当然,这里还得修改相应的数据访问层代码,来初始化AccessPassword字段。这里略去。
下一步编写插件,针对Post.Serving事件编写,全部代码:
[Extension("加密日志","1.0","yibin")]
public class ZPostAccessExtension : System.Web.SessionState.IRequiresSessionState
{
string cookiekey = string.Empty;
public ZPostAccessExtension()
{
Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
}
void Post_Serving(object sender, ServingEventArgs e)
{
Post p = sender as Post;
if (HttpContext.Current.User.IsInRole("administrators") || HttpContext.Current.User.Identity.Name == p.Author)
return;
cookiekey = "POSTACCESS_" + p.Id;
//这里很关键,用Session来判断当前用户没有权限访问,如果指定的session存在,则直接退出,否则更改e.Body值。
if (HttpContext.Current.Session[cookiekey] != null)
{
return;
}
if (!string.IsNullOrEmpty(p.AccessPassword))
{
if (e.Location == ServingLocation.PostList)
{
e.Body = "加密日志,您无权查看";
}
else
{
e.Body = string.Format(@"<p class=""AccessPassword"">加密日志,请输入密码查阅</p><input type=""password"" name=""AccessPassword_{0}"" id=""AccessPassword_{0}"" class=""AccessPassword"" /><input type=""button"" value=""确定"" title=""确定"" onclick=""Check();""/>", p.PostIdentity);
e.Body = e.Body.Replace("<", "<").Replace(">", ">"); //这里要对已经HtmlEncode后的字符进行还原,否则显示不正确。
}
}
}
}
接下来就是实现认证这一步,我采用的是实现ICallbackEventHandler接口来进行无刷新操作。
先看很简单的js代码
<script type="text/javascript">
var accessMessage = document.getElementById('AccessMessage');
function Check()
{
accessMessage.style.display='block';
var pwd = '';
var panel = document.getElementById('AccessPassword_<%=Post.PostIdentity %>'); //DOM找到密码输入框
if(panel) {
pwd = panel.value;
}
if(pwd==''){
accessMessage.innerHTML='密码不能为空';
panel.focus();
return false;
}
accessMessage.innerHTML='正在验证......';
<%= Page.ClientScript.GetCallbackEventReference(this,"pwd","checkCallback","")%>;
}
function checkCallback(rValue) {
if(rValue=='error')
{
accessMessage.style.display='block';
accessMessage.innerHTML='密码认证失败';
setTimeout(function(){accessMessage.style.display='none';},2000);
}
else{
accessMessage.style.display='block';
accessMessage.innerHTML='验证成功';
setTimeout(function(){document.getElementById('entrybody_<%=Post.PostIdentity %>').innerHTML = rValue;},500);
setTimeout(function(){accessMessage.style.display='none';},3000);
}
}
function ServerError(error) {
alert(error);
}
</script>
.cs文件中的关于ICallbackEventHandler接口的实现
#region ICallbackEventHandler 成员
protected string _callback = string.Empty;
string ICallbackEventHandler.GetCallbackResult()
{
return _callback;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
if (Post.AccessPassword == eventArgument.Trim())
{
string SessionKey = "POSTACCESS_" + Post.Id;
HttpContext.Current.Session.Add(SessionKey, true); //注意这里,当密码验证成功后写session
string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/PostView.ascx";
PostViewBase postView = (PostViewBase)LoadControl(path);
postView.Post = Post;
postView.Location = ServingLocation.SinglePost;
_callback = postView.Body; //此处仍然会执行Post.Serving 事件,但因为前面已经写入了Session,所以触发Post.Serving 事件时将直接返回日志内容。
//因为我想每次访问日志都需要输密码,所以,当正确返回日志内容后,清除掉该Session
HttpContext.Current.Session.Remove(SessionKey);
}
else
{
_callback = "error";
}
}
#endregion
OK,整个过程就是如此,很是简单吧。
同样的原理,可以实现类似于论坛的“回复后可见”同样的功能,如果想长时间维持日志的正常查看权,可将Session换成Cookie。
另外,BlogEngine默认在web.config中将enableSessionState设为了false,请一定要设为true,否则无法使用Session!
我就是没有认真看web.config,在Session的获取上大费周折。