話說前陣子處理了 BlogEngine.NET 升級到 1.4.5.0,另外也寫了 SecurePost.cs 這個 extension, 其時都碰過這個鳥問題,只是一直沒去理它而以。接下來為了要改 PostViewCounter.cs (BE extension, too), 又碰到... 於是就認真的研究了一下...。
過程是這樣,為了建立 BlogEngine 的開發環境,首先我從官方網站下載了 source code, 解開後編譯都沒問題,OK。
接下來 WEB 的部份我把網站上的 source code 搬過來 (不包含 ~/App_Data,太大了),編譯也 OK。
不過我要改 Counter 的 Code 啊,沒有一些 SAMPLE DATA 很難測試,只好把資料檔也搬過來.. 結果 Visual Studio 2008 就冷冷的回了這訊息給我:
(0): Build (web): The CodeDom provider type "Microsoft.VJSharp.VJSharpCodeProvider, VJSharpCodeProvider, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" could not be located.
我沒有漏貼前面的訊息... 的確是沒有檔名,也沒有行號(0)。我最不能忍受的就是沒頭沒尾的 ERROR MESSAGE 了。除了告訴你 "掛掉了" 之外,無頭無腦的對於追查問題實在沒什麼幫助。只好靠自己了...。雖然這是個 compile error message,不過我要 RUN 的畢竟是個 web site, 不編譯也是可以跑,除了那個惱人的錯誤訊息之外,要執行倒是沒問題。只不過編譯失敗,我就不能設中斷點,直接 F5 執行測試。雖然可以另外手動 Attach Process 的方式來除錯,不過每次都要這樣搞實在是很煩..
仔細想了想,沒錯,我是沒裝 Visual J#。不過我的確沒要用 Visual J# 啊,如果真的用到 J# 的話,出這訊息是應該的。訊息沒有原始檔? 也沒有錯誤行號? 那問題應該是 Global 的範圍,第一個想到的就是 web.config 是不是定義了 CodeDom 或是指定了相關的 CodeProvider ? 無奈查了一遍沒看到,VS2008 的 PROJECT 設定也沒看到引用任何 J# 相關的 LIB...
已經到了死馬當活馬醫的地步... 開始亂找一通碰碰運氣。搜尋了一下有沒有 *.java 的檔? OUCH,還真的有... 在 ~/App_Data/files 下找到我古董檔案,研究所時代寫的 Java Applet .... 順手試一下,刪掉後還真的就過了? 這個無頭無腦的問題,就在不知不覺中找到 solution, case closed!
怒... 這樣也算? 找到 .java 的程式碼,去找 VJ# 來編譯還說的過去,不過找 "source code" 找到 ~/App_Data 實在是太超過了一點... 好歹也列個要編譯那個檔案,然後找不到對應的 CodeProvider,這樣要排除問題也簡單一點...
結論是: 各位別太鐵齒,看來 ~/App_Data 下的檔案也是不能亂塞的...
因為家裡大人開出條件,除非新的 BLOG 系統 (就是我在用的 BlogEngine 啦) 有特定文章要輸入密碼才能看的功能,否則她就不想換系統了 (原來是用 CommunityServer 2007)。要弄密碼其實很簡單,不過過去試過 IIS 加上整合式驗證... 弄到最後該看的人看不到,也沒擋到該擋的人而作罷...。
仔細想了想大人的需求,要的就是簡單的控制機制。不需要先建立帳號,也不需要登入,就是特定幾篇文章要輸入暗號才能看到內容,就這樣而以。無耐 BlogEngine 還算很年輕,替它寫的 Extension 也還不多,官方網站提供了幾個 Extension 列表,找到最接近的是這個: Password Protected Post... 不過它是以登入 BE 為使用者認證的方式,再依照 ROLE 跟 CATEGORY 的配對為授權方式,來控制那些讀者能看到那些文章...。就是不想要替每個人建帳號啊,看來只好自己寫了... Orz。
以往都是想要作什麼很簡單,難是難在把它作出來..。現在都反過來了,工具越來越強,系統也越來越完整,難的反而是思考要怎麼作,程式碼沒幾行就搞定了。之前的文章介紹過 BlogEngine 的 Extension 機制,這次就實際來試看看。我要寫的東西很簡單,就一組密碼就好,要有夠簡單的方式讓大人能夠指定那幾篇文章是要保護的,而所有的人 (已登入的除外) 只能看到提示輸入密碼的訊息,密碼打對了才會顯示文章內容。至於密碼要不要加密? 會不會被竊聽? 不重要啦,只要保護不要遜到按右鍵簡示原始碼,密碼跟內容都看光光了就好。
順手寫了幾行 CODE,先驗證一下最基本的動作做不做的到 (POC: Prove Of Concept)。第一步是先把顯示內容的動作攔下來,換成制示的輸入密碼訊息... 這個簡單,沒幾行就搞定了:
直接從 CodePlex 抓下來的 Source Code, 解壓縮完就可以寫了。加上這段 CODE 並不難,整個 Extension 只有這樣而以:
1: [Extension("SecurePost", "1.0", "<a href=\"http://columns.chicken-house.net\">chicken</a>")]
2: public class SecurePost
3: {
4: static SecurePost()
5: {
6: Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
7: }
8:
9: private static void Post_Serving(object sender, ServingEventArgs e)
10: {
11: Post post = sender as Post;
12: StringBuilder bodySB = new StringBuilder();
13: {
14: // 略。透過 bodySB 輸出 HTML
15: }
16: e.Body = bodySB.ToString();
17: }
18: }
看起來 CODE 還不少,不過算一算真正在作事的都是在湊那堆 HTML ... 關鍵只有一開始去攔 Post.Serving 事件,接到自己的事件處理器 Post_Serving( ) 上,之後所有會輸出 Post 內容的地方,都會觸發這個事件。然後只要在事件處理器內去調整 Post 內容就可以了。
好,好的開始是成功的一半,已經完成 1/3 了 (什麼???) 第一部份的 CODE 產生的 HTML,會引導使用者輸入密碼,按下 [GO] 之後,就會連到 POST 的網址了。不過除了原本網址之外 (post.AbsoluteLink) 後面還要加上 "?pwd=xxxxxx" 帶上使用者輸入的密碼。前面講過我只要最基本的防護,其它進階的安全問題就不理它了。我只要掌握兩個原則:
另外補一件事,我也不要讓全部的文章都用這種機制保護。只要有特別標示的 POST 要密碼就好。看到 BlogEngine 內建的 BreakPost 這個擴充程式,我就仿照它的作法,內文找到特定字串就啟用。我定的規則是整篇 POST 內容開頭一定要是 "[password]" 才會啟用密碼保護機制。
既然這樣,第二步也很簡單。如果密碼對,一切照原狀顯示內容。密碼不對的話就一樣攔下來...。程式碼.... 只是在第一步的程式碼多了... 兩行...
1: private static void Post_Serving(object sender, ServingEventArgs e)
2: {
3: Post post = sender as Post;
4: if (HttpContext.Current.Request["pwd"] == Password) return;
5: if (!e.Body.StartsWith("[password]", StringComparison.CurrentCultureIgnoreCase)) return;
6: StringBuilder bodySB = new StringBuilder();
7: {
8: // 略。透過 bodySB 輸出 HTML
9: }
10: e.Body = bodySB.ToString();
11: }
啥米? 就是第一部份的 CODE 加上第四及第五行就搞定了? 程式不挑的話,現在已經寫完了... 哈哈! 上面的輸入密碼畫面,輸入正確密碼後就可以看到文章內容了。我特地連網址列一起複製下來,在網址列上會看到密碼明碼。照道理應該是要先 HASH 啦,不過 CLIENT SIDE 跟 SERVER SIDE 都要有同樣的 HASH 機制才行,想用 MD5 / SHA256 之類的來算,無耐 CLIENT 要弄這些也是很煩,就決定不理它了...。明碼就明碼吧,執行後的畫面像這樣:
剩下的部份就沒什麼了,想想加上去好了。就是透過 BlogEngine 的 Extension Manager,讓使用者可以簡單的調整參數。要讓使用者自定的參數只有三個:
這些東西自己做的話,就還得想要開檔案或寫資料庫,有點小囉唆,不過已經有 Extension Manager 了,只要在原本的 static constructor 再加幾行就搞定:
1: static SecurePost()
2: {
3: Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
4: ExtensionSettings settings = new ExtensionSettings("SecurePost");
5: settings.AddParameter(
6: "SecurePostMessage",
7: "顯示訊息:");
8: settings.AddParameter(
9: "PasswordHint",
10: "密碼提示:");
11: settings.AddParameter(
12: "PasswordValue",
13: "指定密碼:");
14: settings.AddValues(new string[] {
15: "本篇文章已受密碼保護,請依照題示輸入密碼。",
16: "一二三四",
17: "1234"});
18: settings.IsScalar = true;
19: settings.Help = "用密碼保護文章的內容。";
20: ExtensionManager.ImportSettings(settings);
21: _settings = ExtensionManager.GetSettings("SecurePost");
22: }
我已經很努力的多撐幾行了... 不過也只有這廿行,寫完了...。整個 .cs 檔案直接丟到 ~/App_Code/Extension 就算安裝完成。用管理者身份登入 BE 後,在 Extension 那頁可以看到:
不錯,SecurePost 已經出現在 Extension Manager 裡了。因為有加上 settings 的程式碼,所以右邊有 [編輯] 的字樣出現。點下去之後會到這個畫面:
嗯,看起來真專業,沒想到從頭到尾所有的 CODE 還不到一百行...。幾十行 CODE 寫出來的 Extension 就可以唬人了.. :D,試看看還真的會動耶 (廢話)。早知道寫起來那麼快,當初就不花那麼多時間去找人家寫好的了...。最後附上整段完整的程式碼,有需要的人就拿去用吧! 用法很簡單,全部複製下來 (可以按 [COPY CODE] 就好),存檔,把檔案放在 ~/App_Code/Extension/SecurePost.cs 下,然後用管理者身份進入 BlogEngine Extension Manager 改一改就好了!
大功告成! 這個 Extension 如果對你有用的話就拿去用吧,要散佈也歡迎,不過只有個小要求,請不要把程式碼存到別的地方供人下載,請直接提供我這篇文章的網址就好。覺的好用就留個話給我,要幫我推一下文或讚助就更好了 :D,謝謝收看!
--
1: using System;
2: using System.Web;
3: using System.Web.UI;
4: using BlogEngine.Core.Web.Controls;
5: using BlogEngine.Core;
6: using System.Text;
7:
8:
9:
10:
11: [Extension("SecurePost", "1.0", "<a href=\"http://columns.chicken-house.net\">chicken</a>")]
12: public class SecurePost
13: {
14: private static string SecurePostMessage { get { return _settings.GetSingleValue("SecurePostMessage"); } }
15: private static string Password { get { return _settings.GetSingleValue("PasswordValue"); } }
16: private static string PasswordHint { get { return _settings.GetSingleValue("PasswordHint"); } }
17:
18: private static ExtensionSettings _settings = null;
19:
20: static SecurePost()
21: {
22: Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
23:
24: ExtensionSettings settings = new ExtensionSettings("SecurePost");
25:
26: settings.AddParameter(
27: "SecurePostMessage",
28: "顯示訊息:");
29: settings.AddParameter(
30: "PasswordHint",
31: "密碼提示:");
32: settings.AddParameter(
33: "PasswordValue",
34: "指定密碼:");
35:
36: settings.AddValues(new string[] {
37: "本篇文章已受密碼保護,請依照題示輸入密碼。",
38: "一二三四",
39: "1234"});
40:
41: //settings.ShowAdd = false;
42: //settings.ShowDelete = false;
43: //settings.ShowEdit = true;
44: settings.IsScalar = true;
45: settings.Help = "用密碼保護文章的內容。";
46:
47: ExtensionManager.ImportSettings(settings);
48:
49: _settings = ExtensionManager.GetSettings("SecurePost");
50:
51: }
52:
53: private static void Post_Serving(object sender, ServingEventArgs e)
54: {
55: Post post = sender as Post;
56:
57:
58: if (HttpContext.Current.User.Identity.IsAuthenticated == true) return;
59: if (HttpContext.Current.Request["pwd"] == Password) return;
60: if (!e.Body.StartsWith("[password]", StringComparison.CurrentCultureIgnoreCase)) return;
61:
62:
63: StringBuilder bodySB = new StringBuilder();
64: {
65: bodySB.AppendFormat(
66: "<b>{0}</b><p/>",
67: HtmlEncode(SecurePostMessage));
68:
69: if (e.Location == ServingLocation.Feed)
70: {
71: }
72: else
73: {
74: bodySB.Append("<div>");
75: bodySB.AppendFormat(
76: @"請輸入密碼(提示: <b>{0}</b>): <input id=""postpwd"" type=""password""/><button onclick=""document.location.href='{1}'+'?pwd='+escape(this.parentNode.all.postpwd.value);"">GO</button>",
77: PasswordHint,
78: post.AbsoluteLink);
79: bodySB.Append("</div>");
80: }
81: }
82: e.Body = bodySB.ToString();
83: }
84:
85: private static string HtmlEncode(string text)
86: {
87: return HttpContext.Current.Server.HtmlEncode(text);
88: }
89: }
感謝編輯賞光,第三篇順利刊出 :D
執行緒這種東西,實在不是什麼主流的文章,不過雜誌社願意刊到第三篇,真是感謝... 前兩篇分別介紹了同步機制跟旗標,這次用執行緒集區作總結,提供了綜合的應用,也對效能的影響作整理,讓讀者具體的瞭解使用前後的效能差異。
這次文章內提到了 ThreadPool 的應用,不過因為內容及篇幅的關係,沒有挖到 ThreadPool 本身怎麼設計。對這部份有興趣的讀者可以參考我寫的這三篇:
ThreadPool 實作 #3. AutoResetEvent / ManualResetEvent
雖然好像沒有人因為看到雜誌才連到這裡來,不過還是要囉唆一下,看到文章有任何意見都可以在這裡留言給我。文章內提到的 SAMPLE CODE 可以在這裡下載! 這次的範例程式是 Console application,不提供直接在網頁上執行,下載回去試試吧!
雖然我很少貼這些五四三的 (明明 543 這 tags 點下去有一堆..) ,不過無意間在癮科技逛到這段實在是太酷了... 流言終結者這節目的 Adam & Jamie用漆彈示範來比喻 CPU / GPU 繪圖的差別... 不管它的比喻精不精確或妥不妥當啦,那一瞬間噴出蒙那麗莎實在是太酷了... :D
在開始講 "為什麼" 之前,先講一下該如何正確的引用我的文章。
只要把這個 link 加到書籤, 就大功告成了!
javascript:document.body.style.zoom="150%";void(0);
之後看到任何網頁, 覺的看不過癮想放大看, 再點一下這個 Bookmark 就好了.
覺的固定 150% 不好用, 那可以把 link 改成這樣:javascript:document.body.style.zoom=prompt('縮放比例 (%):','100%');void(0);
--------------------------------------------------------------------------------------------------------------------------------
引用說明結束。以下為本文內容,純發洩用。
為什麼突然要貼這篇? 該說是 "一回生二回熟" 嘛? 沒錯,每次一時興起,到 GOOGLE 找一下我自己的資訊,總是會發現有人沒經過我同意轉貼我的文章...。轉貼對我實質上的影響並不大,畢竟我寫東西是興趣,不是拿還養家糊口的,所以被轉貼除了心理不大爽之外,其它都還好。不過這樣會大大的降低我寫東西的意願。
舉例來說,最不滿的就是像上次在對岸的入口網站碰到的案例,原文照貼,沒註明出處,留 comment 提醒還被砍掉!? 回報站方也是一副不理不睬的樣子... 這種沒什麼好說的了,直接用我的方式表達我的不滿。
碰過另一個例子,也是很令人厭惡,就是到處轉貼文章,不管有沒有註明出處。落落長的一整篇文章就被 COPY / PASTE 過去,最後加個小小的 "出處" 就算免責了? 如果他的網頁還放了廣告,那就等於是不當的取得利益。講的難聽一點,這跟盜版沒兩樣,不都是用別人的作品去賺取利益? 最後是通知 BLOGGER,站方停權結束這件事。
看過 Jedi 的文章,我很認同他在這篇 [引用不能祇是引用] 文章裡的看法。很多人好像以為只要加了 trackback 就是盡到道義上的責任了? Trackback 太方便了,之前用的 CS 甚至方便到連 trackback 的 URL 都不需要點,一切全都無腦化自動的進行。方便到好像原本該尊重作者的動作都不用作了,直接貼了就好。所以我的網站刻意不放 trackback,因為我不喜歡這樣的結果。
我自己認為尊重作者的引用方式,要有兩個前題。一個是清楚的讓你的讀者知道,這段引用的內容出自那個人的那一篇文章。另外就是轉貼的部份。如果你不能只提供 LINK,而需要轉貼它人的內容到你的文章內,請把握好 "片段" 的原則。轉貼幾句話是合理的,轉貼一整篇就是白目了。這跟書本只影印一部份 (好像是 1/3 以內?) 是合法的,整本影印就侵害到原作者版權了。網路上的內容,複製更容易了,也讓人更容易忽略掉這些問題。
所謂 "不教而殺謂之虐",就藉著這個機會說明一下,怎樣作我才不會認為我的權益被侵害。我很歡迎同好轉貼我的文章,不過我既然是我自己的文章,我會保有這幾項權益:
這篇不是合約,也不是在訂什麼法律條文...。我只是想表達出我對於 "轉貼" 及 "引用" 的看法而以。其實任何方式的引用我都歡迎,只要不違背上面四點原則為前題就好。只是一直碰到類似的事件,我不想成為處理盜文事件的老手啊啊啊...。希望打了這篇,可以讓那些沒有惡意的轉貼行為,不會被我誤認為又是盜文事件。