Tuesday, August 19, 2008

全國墊紙 救甘興?

在「赤壁」這部片中,還有一個人物也很特別,
是由日本人中村獅童所飾演的「甘興」,
不過根據史書記載,吳國有甘寧這個猛將,但卻查不到甘興這個人…

後來網友展現了可怕的情報能力,才讓我們知道甘興到底是何許人物,而且還是
我們早就熟悉的人物,故事是這樣的…資料來源--網路路透社消息)

甘興是孫權旁邊一個侍衛,平時盡忠職守,也深得周瑜的喜愛,有一天,甘興在
孫權的桌子上割東西時,因為沒有墊東西,所以刀子力透紙背,割壞了孫權的愛
桌,孫權非常的生氣,正當要將甘興拖出去斬了的時候…

周瑜特別為甘興求情,他向孫權深明大義,叫孫權不可為了區區一張桌子而殺害
一位忠臣,孫權最後接受了周瑜的求情,但還是憤恨難平。



周瑜為了讓孫權消消火氣,便向全國宣告,日後在桌子上割東西,都要先墊紙保
護桌子,才不會造成像孫權愛桌被割的憾事,而這個佈告獲得全國的響應,也使
得孫權最後心情平緩,原諒了甘興…

這就是…

「全國墊紙 救甘興」
(全國電子...就感心~~~ =.=|| ) 快被冷死了啦...

對別人好 就是快樂

來源 :對別人好 就是快樂

對別人好.就是快樂

要看完ㄛ..

有意思的文章!

對別人好.就是快樂


某天,小張要去相親,因為沒有看過對方,擔心她長得太醜,
於是交代朋友,十分鐘後 call他的手機,這樣他就可以藉機遁逃。
到了約會地點之後,小張發現女方驚為天人,
於是心想,等一下手機響不要回就好了。
沒想到,美女的手機這時候響了起來,美女聽了兩秒後,對小張說:
『對不起,朋友有急事找我,我要先走了……』
 
有一個男人在派對上對男主人說:
『今天的美女真多,要是待會兒我泡上一個,
你可不可以把樓上的房間借我一用。』
主人說: 『那你老婆怎麼辦?』
這人說: 『放心,她不會想念我的,我只失縱一下而已。』
主人說:
『我不是說這個,我是說十五分鐘前,她才向我借了樓上的房間。』
 
有一個老光棍,他並沒有什麼嗜好,
只是喜歡在睡覺前喝一點葡萄酒自娛。
然而,他發現這幾天有人偷了他的酒。
他便懷疑偷酒的是他的佣人,於是就把酒倒出來,
再裝入他的小便。但裝小便的酒,仍然每天減少。
他很不高興的把佣人叫來,責備一番。
『不,我並沒有偷喝!』
佣人說:
『我是想做味道更香更可口的菜給您吃,
所以我每天燒菜時,都加了一點在裡面。』


從這三則短文中各位有沒有發現什麼共通之處呢?
沒錯,你怎麼對別人,別人就怎麼對你;
你給別人什麼,別人就回報你什麼。
說得更白一點就是,你給別人的,其實是給自己的。
就像我在前面說過的,不管你丟出去什麼,
或是…想了、說了、做了什麼,最後都會回到你身上,不是嗎?
你給別人的,其實是給自己…
自食惡果的事說都說不完,讓我們再聽下面的故事:

在一家簡陋的酒館裡,正在喝大杯啤酒的李先生,突然覺得內急,
他匆匆忙忙站了起來,又想到上廁所時,酒可能被別人偷喝,
猶豫一會後,他找到一張紙,寫上: 《我吐口水在這裡!》,
把它放在杯子下面,然後才放心的去上廁所。
過了幾分鐘後,李先生回來時,他看到另一張紙寫道:
《我也吐了一口在這裡!》。
哈!哈!哈!  

 
我聽說從前有個人,他很不喜歡喝咖啡,
但是他太太並不知道,他從來沒告訴過她。
她非常喜歡喝咖啡,所以,每天早上都會順便為他…
準備一個熱水瓶的咖啡,跟他的便當擺在一起。
他一直都帶著那個便當和熱水瓶去工作,但是因為他很節儉,
所以每天晚上都會把那個熱水瓶帶回家,裡面的咖啡完全沒有被動到。
他知道太太很喜歡喝咖啡,為了要省錢,所以當她沒看到的時候,
他會將沒有喝的咖啡倒回咖啡壺裡。
晚上的時候他會用喝咖啡使他睡不著的理由把它推掉。
就這樣他每天都重複這麼做。

有一天,她的太太認識了另一個男人,
他們計劃好要毒害他,以獲取巨額的保險金,
於是她每天早上都放少量的砒霜在他的熱水瓶裡,
日復一日,直到最後她毒死了她自己。
你給別人的,其實是給自己的。
你說是不是呢?
你所給予的,都會回到你身上…
如果,你對人冷淡,別人也會回以冷漠;
如果,你經常批評別人,你也會接收到許多的批評;
如果,你總是擺一張臭臉,沒錯,別人也不會給你好臉色。
所有你所給予的,都會回到你身上。
套句詩人奧登( W.H.Auden)的話:
『人受惡意之作弄,必作惡以回報。』
如果你陷害別人,哪天你也會遭人陷害。

 
同樣的道理……
當你帶給別人歡樂,你就會得到歡樂;
帶給別人祝福,你就會得到別人的祝福;
如果你經常讚美別人,不久你也會聽到有人在讚美你,
《你給別人的,其實是給自己的!》。
你讓他人經歷什麼,有一天你也將自己經歷;
你怎麼對待你的父母,將來你的孩子也會怎麼對待你。
我想許多人一定聽過,
格林童話中有一則關於一位老人和兒子住在一起的故事。


老人的耳力已經不行了,眼睛也看不見,
顫抖的雙手經常把飯菜洒得滿地,碗也常打破,
兒子夫婦倆感到非常厭煩,給老爸爸一付木製碗筷,
把他趕到廚房幽暗的角落,不准和大家一起用餐。
有一天,兒子看到自己的兒子用刀片消木頭,
他好奇的問孩子要做什麼。
結果孩子回答: 『我在替你準備將來要用的木碗、木筷。』
從此以後,年老的父親又回到餐桌上吃飯,家人也都非常孝順他。

 
農夫的哲理
地球是圓的,整個世界都在繞著圈子,
不論你傷害誰,就長遠來看,你都是傷害到你自己,
或許你現在並沒有覺知,但它一定會繞回來。

所以,如果你佔了別人什麼便宜,
先別得意,很快你就會為此付出代價;
反過來,若是別人對你做了什麼,你也無需氣憤,
不必去報復,任何他們所做的,他們都將自食惡果。

《凡你對別人所做的,就是對自己所做的。》
這是歷來最偉大的教誨。

不管你對別人做了什麼,
那個真正接收的人,並不是別人,而是你自己;
同理,當你給予他人,當你為別人付出,
那個真正獲利的也不是別人,而是你自己。
有一個農夫的玉米品種,每年都榮獲最佳產品獎,
而他也總是將自己的冠軍種籽,毫不吝惜地分贈給其他農友。
有人問他為什麼這麼大方?
他說:
『我對別人好,其實是為自己好。
風吹著花粉四處飛散,如果鄰家播種的是次等的種籽,
在傳粉的過程中,自然會影響我的玉米品質。
因此,我很樂意其他農友都播種同一優良品種。』

他的話看似簡單卻深富哲理,凡你對別人所做的,就是對自己所做的。
所以,凡事你希望自己得到的,你必須先讓別人得到


保證有效的秘方
就像那個農夫一樣,
如果你想要得到冠軍的品種,就要給別人冠軍的種籽。
你若想被愛,就要先去愛人;

你期望被人關心,就要先去關心別人;
你想要別人對你好,就要先對別人好。

這是一個保證有效的秘方,可以適用在任何情況。
如果你希望交到真心的朋友,你就必須先對朋友真心,
然後你會發現朋友也開始對你真心;如果你希望快樂,
那就去帶給別人快樂,不久你就會發現自己愈來愈快樂。

明白了嗎?

我們所能為自己做的最好的事情,就是去為他人多做點好事。

 
《己所欲,施於人。》
凡你想給予自己的經驗,就給予別人;
想別人怎麼對你,就怎麼對待別人。
感恩過去… 把握當下… 創造未來…

Thursday, August 14, 2008

如何擴充 VMware 虛擬磁碟及作業系統容量

企業為了節省成本及空間,在內部系統的規劃上漸漸的都以虛擬機器(VM)取代
在一部裝滿 8G RAM 的 PC 上,可以規劃出 5-6 VM 使用,的確可以替企業省不少成本

在 VM 的領域上,又以 VMWare 最為有名。而其下的 VMWare Server 因是免費的,許多企業便運用 VMWare Server 的免費及便利性,規劃內部系統的建置及測試。

尤其是在測試方面,因可以規劃成獨立的空間作測試,將來在備份及還原時只要一個檔便可解決不用作 Ghost 或是重新安裝的繁雜動作

在建立一個 VM 時,VMWare 預設的空間是 8GB,所以一般建立時都會直接用此預設值但在特殊情況下 (如模擬正式環境的機器),8GB 的空間就顯得不足

在此情況下,有兩種作法
1. 再加上一個虛擬硬碟,但此方法無法避免原來的虛擬硬碟爆掉
2. 將原來的虛擬硬碟容量加大

在此就介紹如何加大原來的虛擬硬碟及作業系統的容量 (以 Windows 2003 server 為例 )

step 1. 複製原來的虛擬硬碟成為第二顆硬碟,並掛到原來的 VM 中。複製的檔名如下
c:\Virtual Machines\Windows Server 2003 Standard Edition\Windows Server 2003 Standard Edition_1.vmdk
PS : 檔名不能有中文名稱,因為 VMWare 不支援

step 2. 利用 VMWare 提供的工具先將第二顆虛擬硬碟加大
以下為原來 VM 的 size 為 8GB






執行以下指令後 (以我的環境為例)
C:\Program Files\VMware\VMware Server>vmware-vdiskmanager.exe -x 16Gb "c:\Virtual Machines\Windows Server 2003 Standard Edition\Windows Server 2003 Standard Edition_1.vmdk"

可以透過 DOS box 看見虛擬硬碟容量逐漸加大中







執行完後,可以發現虛擬硬碟容量已經變大了








要如此做的原因是因為若要將硬碟上的作業系統容量作擴充但還要保留原來的內容,則必須將此硬碟掛為 D 磁碟,因為 C 磁碟是開機磁碟,作業系統會鎖住無法作立即擴充

step 3. 將 VM 開機並將原來的 D 碟 8GB 容量擴充為 16GB 容量
因為掛上 VM 後,D碟 (我的虛擬硬碟為 F) 的邏輯磁碟只有 8 GB,若要擴充為 16GB,則可以藉由 Windows 2003 內建的工具 Diskpart 完成。原來邏輯的只有 8GB





進入 VM 後,透過 dos command 指令將 D 碟擴充為 16GB



















step 4.
接下來就需要一點小技巧。為了將原來的 C 碟系統擴充為 16GB,又因為 D 碟是複製 C 碟又可以開機,那要如何做呢? 沒錯,將 VM 關機後,移除原來的虛擬磁碟,再將 _1.vmdk 改為原來虛擬磁碟的檔名,然後再將 VM 重新開機後,可以看到,C 碟可開機且容量變為 16GB








要把虛擬硬碟容量改為多少,端看實際運用。一般而言,8GB 應該足夠,若需加大便可以用此技巧加大虛擬硬碟容量並無需再重新安裝 Windows 2003

Sunday, June 22, 2008

網頁 Usability

網頁應用程式 Usability 筆記

原則一:思考服務的對象

首先要先了解你的用戶是哪一種類型:若按用戶功力可分為 end user 和 power user。若按網頁使用頻率來分,可分為例行性作業和一次性作業。用例子說明好了,比方說大家熟悉的購物網站,包含產品瀏覽、購物車、下單等等功能。首先,這類網站的使用者功力大多屬於 end user,因此介面上越簡單越好 (即使你有很好的創意,也要小心發揮,因為 end user 可能會看不懂你新穎的介面)。若從使用頻率來看,產品瀏覽屬於例行性作業,下單則屬於一次性作業 (因為久久才下單一次)。因此產品瀏覽的網頁不能拖泥帶水,步驟要越少越好,不然用戶逛了老半天找不到想買的東西就跑掉了。另一方面,下單的網頁到是不怕步驟多,就怕使用者不會用,或是抗拒使用 (要付錢的地方總是會小心翼翼的)。所以一般下單都會設計成 wizard 的方式,一步一步導引使用者完成下單。

那如果是購物網站的後台呢?後台的使用者屬於 power user (可能一開始就是,或是之後會被訓練)。他每天的工作就是產品上架,處理訂單...等等例行性的作業。這樣的網頁以快速為最優先考量:可以運用 減少 popup、不用 wizard、多功能客製化元件、一頁內放多一點資訊、增設 hotkey... 等等技巧。總之讓用戶可以在最少的點擊、最少的思考完成他的工作就是了。

購物網站是大家熟悉的例子,大家都見多了。但是如果換個 domain 就要多花心思去了解了。比方說我的工作是服務醫院醫學相關的研究,涉及到的人員有護士、醫生、研究員、實驗室、計畫負責人...等等。服務內容則有病人收樣管理、實驗管理、秏材進銷存、問卷調查...等等。遇到這類不熟悉的 domain 時,記得談需求時要多尋問:分辨他在這個功能上屬於 end user 還是 power user?他多久用一次這個功能?每天用還是一個月用一次?先替這些用戶簡單歸個類,大方向捉對了,未來做出的網站用戶用的就順手。
原則二:第一頁要放用戶最想做,最常做的事

這個原則乍聽之下很自然、也很直覺... 但我們 team 的大多數成員 (包含我自己) 就是沒有辦法做到這一點。我們的專案多屬內部使用,而開發部門並沒有設立專人設計網頁,所以從網頁設計到後端資料全都工程師自己來。工程師拿到案子,頭腦就開始直覺思考後端流程怎麼設計,然後由後端往前端推,網頁的流程就會和後端呈現一比一的關係。比方說要做一個管理稽核案的功能,有新增修改查詢等等功能。依典型的工程師思維,第一頁就做了個查詢案子的表單和新增案子的連結,下了查詢條件後再列出相關案子的網頁。這種 "第一頁" 也不能說工程師沒按需求來做... 只是剛進去時除了表單,就是一片空白,什麼都沒有。使用者一進來就得去想、得去回憶要下什麼查詢條件,才能找到他要的東西。這樣還真有點難用...

要提升 usability,就是去思考用戶最想做或是最常做的事,比方說,第一頁除了查詢表單之外,還列出他最近處理過的10個案子;或者,用戶比較關心那些稽核不過的案子,那一開始就先列出這些有問題的案子;或者,可以提供查詢條件 history 的功能,讓用戶可以調出最近下的查詢條件... 等等。決定要做那方面的事,要透過談需求時了解。而且,要注意很少有使用者會自覺得想到這一塊,必需由開發者主動尋問和了解使用者的作業才行。
原則三:重要的內容放在 1024x768 內

這個原則很基本,許多人都了解 (還不知道的人要打屁屁!)。問題是出在難遵守.... 開發人員通常都用很大的營幕、開高解析度、然後字型用的小小的,希望一次看多點資訊,方便開發。這樣的習慣長期下來,一不小心就會發生設計的網頁常常需要 scroll (甚至是左右 scroll)。除非你的網頁是設計給 power user,而且是配備比較好的營幕。不然開發時建議固定開個 1024x748 的 browser 來檢視網頁的呈現,比較符合一般使用者的畫面大小。(安裝 firefox 的 web developer plugin,然後大小設 1024x748 (不是 768,因為要扣掉 toobar和 menu 的高度)) 瀏覽器的大小有了,接下來就是將重要的內容、用戶最關心的事情,盡量放在網頁上半段,一般來說,左上角是人瀏覽的起點,從那裡開始最好。目的就是讓用戶最少的力氣找到他要的東西,而不是 scroll 老半天才看的到。
原則四:改變資料狀態用按鈕,瀏覽資料用連結

當你做的功能是 改變資料狀態時,網頁上要用按鈕來呈現。如果是資料間瀏覽,則用連結來呈現。什麼是改變資料狀態?比方說刪除資料、送出表單、移動位置、切換...等等功能。這些功能用按鈕比較洽當,因為按鈕有 "動作" 的感覺 (按下後再彈上)、有視覺上的 feedback。當然在 ajax 的風潮之下,按鈕漸漸越用越少了,不少地方開始用連結來替代。不過重點還是一樣,要有視覺上的 feedback,例如加些 animation, yellow fade out之類的都可以。

另一方面,瀏覽資料則一定是用連結,千萬不要用按鈕替代。這聽起來很白吃吧?但就是有新手會犯這種錯 (三年前我自個兒也常犯...)
原則五:慎防預覽頁面

當設計多步驟網頁時,例如結帳的功能,中間多半會夾一個預覽的頁面。預覽的網頁原本是好意,讓使用者可以再完成前,再確認、考慮一番。但偏偏很多用戶會把他當做 "已完成" 的網頁,造成常會有客戶來電,抱怨明明已經完成了,卻沒成交。為避免這類常犯的錯誤,建議預覽的畫面正上方要加上大剌剌的 "完成按鈕" (可用顏色/大小/字型來醒目) 提醒使用者,要按了才會生效。如果版面許可,可以再加上 process train (另一說法是 process funnel) 就是常見的按順序導引:(1) -> (2) -> (3) -> done,這樣就更穩了。現在 Ajax 技術發達,也可以考慮用 "即時預覽" 取代掉舊的換頁預覽,這樣既方便又不會出錯。
最後,我們來看一個客製元件提升 usability 的實際例子

需求:用戶需替病人的樣本做稽核 (有無漏收或誤收),一個稽核案約含 100 個病人。每個病人的稽核狀態分別為 未稽核、已稽核、稽核不過。

用戶 profile:用戶為稽核員,是內部的使用者,可以被訓練。因此屬 power user

使用頻率:約每週使用,一次約稽核數十人,屬例行性作業。

按上面的需求,如果用傳統的 html 元件設計,我們會得到:

上圖用表格的方式呈現 100 個病人資料。而最右邊稽核的狀態則採下拉式選單表示 (當然這裡也能用 Radio Button,但是三個選項會太寬,版面擠不下)。在下拉式選單中挑選欲變更的狀態時,背後會用 ajax 的方式直接更新後端的資料。一般來說寫到這樣已經算很方便了,最少用戶不用為了切換狀態而 submit 一個個的 html form。

雖然不錯,但是還有兩個缺點:第一,每次切換下拉式選單都需要兩次的 click。第二,當 100 個 病人直直排下來,狀態用文字表示時,要分辨出 未稽核、已稽核 等狀態其實還蠻花的。

由於稽核員屬 power user,因此我們不一定要使用簡單的 html 基本元件,我們可以客製元件:

上圖稽核的狀態改用兩個圖示表示,兩個都是灰的表示尚未稽核,綠色表示已稽核,紅色則表示稽核不過。這樣一來,即使 table 上排滿滿了 100 個病人,也可以很快看出哪些病人還沒稽核,哪些是稽核有問題的。要切換狀態,只要在欲切換的圖示上點擊一次就行了 (有點類似常見的評比星星),而背後也是直接用 ajax 更新後端的資料。

當然,這樣的元件用戶第一次看到會傻眼... 無從下手,不過只要稍微 demo 一下,之後作業就很順暢囉。

至於要製作這樣的客製元件... 呃... 要看各位用什麼技術寫了... 用 Wicket 的話,一個幾十行的 .java 就搞定了,也不用寫什麼 javascript 或是 xml。其他的技術就得慢慢磨了吧... 採用容易寫客製元件的 framework 真的好處很多,寫元件不僅快又簡單,也讓你有更多的時間和精力花在構思更好的 usability 上。

來源
http://www.javaworld.com.tw/roller/ingramchen/entry/2007_11_18_WebAppUsabilityNotes

Saturday, December 22, 2007

ldap connect AD

開始:
1. 建立 IIS SSL
2. 將 CA Certificate 加入至 jre keystore 裡
3. JNDI 連 AD

1. 建立 IIS SSL:
Install Windows 2003 Server:

Install AD:
Start -> Run -> dcpromote
domain name : joeyta-DOT-local
NT domain name : joeytaserver
即 Fully Qualified Domain Name (FQDN) 為 joeytaserver.joeyta-DOT-local

先安裝 IIS , 再安裝 CA.

Install IIS:
Start -> Programs -> Administrative Tools -> Configure Your Server Wizard
->> Next -> Next -> Application server (IIS, ASP.NET) -> Next

進入 http://joeyserver.joeyta.local/postinfo.html 表示安裝成功.

Install CA:
Start -> Settings -> Control Panel -> Add or Remove Programs
->> Add/Remove Windows Components
選擇 Certificate Services -> Next
選擇 Enterprise root CA -> Next
Common name for this CA: testca -> Next

進入 http://joeyserver.joeyta.local/CertSrv 表示安裝成功.


Generating a Certificate Signing Request:
Start -> Programs -> Administrative Tools -> Internet Information Services (IIS) Manager
->> Internet Information Services -> (local computer) -> Web Sites
-> > 右鍵點選 Default Web Site -> Properties
選擇 "Directory Security" -> Server Certificate
->> Create a new certificate -> Prepare the request now, but send it later
一直按 Next , 需要注意的是 Common name 必須為 joeyserver.joeyta.local, 這是給使用者連 ssl 的 website.
最後產生 certificate request file , 預設為 c:\certreq.txt


Request a certificate on CA:
進入 http://joeyserver.joeyta.local/CertSrv
按 Request a certificate -> advanced certificate request
-> Submit a certificate request by using a base-64-encoded CMC or PKCS#10 file, or submit a renewal request by using a base-64-encoded PKCS#7 file
使用 notepad 打開 c:\certreq.txt , copy c:\certreq.txt 內容貼至 Saved Request:
Certificate Template 選擇 Web Server, 按 Submit
然後點選 Download certificate , 將 certnew.cer 儲存至 c:\certnew.cer


Installing a Certificate:
Start -> Programs -> Administrative Tools -> Internet Information Services (IIS) Manager
->> Internet Information Services -> (local computer) -> Web Sites
-> > 右鍵點選 Default Web Site -> Properties
選擇 "Directory Security" -> Server Certificate
->> Process the pending request and install the certificate -> Next
Path and file name: c:\certnew.cer -> Next
SSL port this web site should use: 443 -> Next -> Next -> Finish


2. 將 CA Certificate 加入至 jre keystore 裡:
進入 http://joeyserver.joeyta.local/CertSrv
點選 Download a CA certificate, certificate chain, or CRL
點選 Download CA certificate , 然後下載並改名為 c:\testca_cert.cer

然後執行 command:
c:\temp>keytool -import -alias testca_cert -file "/testca_cert.cer" -keystore "/jdk1.5.0_09/jre/lib/security/cacerts" -storepass "changeit"

出現 Trusted this certificate? 按 "y" 即新增成功.


3. JNDI 連 AD:

/***************************** LDAPFastBind.java *****************/
package test.ldap;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;

class FastBindConnectionControl implements Control {
public byte[] getEncodedValue() {
return null;
}

public String getID() {
return "1.2.840.113556.1.4.1781";
}

public boolean isCritical() {
return true;
}
}

public class LDAPFastBind {
public Hashtable env = null;

public LdapContext ctx = null;

public Control[] connCtls = null;

public LDAPFastBind(String ldapurl) {
env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, ldapurl);

env.put(Context.SECURITY_PROTOCOL,"ssl");

String keystore = "/jdk1.5.0_09/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore",keystore);

connCtls = new Control[] { new FastBindConnectionControl() };

// first time we initialize the context, no credentials are supplied
// therefore it is an anonymous bind.

try {
ctx = new InitialLdapContext(env, connCtls);

} catch (NamingException e) {
System.out.println("Naming exception " + e);
}
}

public boolean Authenticate(String username, String password) {
try {
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, username);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
System.out.println(username + " is authenticated");
return true;
}

catch (AuthenticationException e) {
System.out.println(username + " is not authenticated");
System.out.println(e);
return false;
} catch (NamingException e) {
System.out.println(username + " is not authenticated");
System.out.println(e);
return false;
}
}

public void finito() {
try {
ctx.close();
System.out.println("Context is closed");
} catch (NamingException e) {
System.out.println("Context close failure " + e);
}
}

public void printUserAccountControl() {
try {

// Create the search controls
SearchControls searchCtls = new SearchControls();

// Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

// specify the LDAP search filter
//String searchFilter = "(&(objectClass=user)(CN=test))";
//String searchFilter = "(&(objectClass=group))";
String searchFilter = "(&(objectClass=user)(CN=peter lee))";

// Specify the Base for the search
String searchBase = "DC=joeyta,DC=local";

// initialize counter to total the group members
int totalResults = 0;

// Specify the attributes to return
String returnedAtts[] = { "givenName", "mail" };
searchCtls.setReturningAttributes(returnedAtts);

// Search for objects using the filter
NamingEnumeration answer = ctx.search(searchBase, searchFilter,
searchCtls);

// Loop through the search results
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();

System.out.println(">>>" + sr.getName());

// Print out the groups

Attributes attrs = sr.getAttributes();
if (attrs != null) {

try {
for (NamingEnumeration ae = attrs.getAll(); ae
.hasMore();) {
Attribute attr = (Attribute) ae.next();
System.out.println("Attribute: " + attr.getID());
for (NamingEnumeration e = attr.getAll(); e
.hasMore(); totalResults++) {

System.out.println(" " + totalResults + ". "
+ e.next());
}

}

} catch (NamingException e) {
System.err.println("Problem listing membership: " + e);
}

}
}

System.out.println("Total attrs: " + totalResults);

}

catch (NamingException e) {
System.err.println("Problem searching directory: " + e);
}

}

public boolean adminChangePassword(String sUserName, String sNewPassword){
try {

//set password is a ldap modfy operation
ModificationItem[] mods = new ModificationItem[1];

//Replace the "unicdodePwd" attribute with a new value
//Password must be both Unicode and a quoted string
String newQuotedPassword = "\"" + sNewPassword + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));

// Perform the update
ctx.modifyAttributes(sUserName, mods);

System.out.println("Reset Password for: " + sUserName);

return true;
}
catch (NamingException e) {
System.out.println("Problem resetting password: " + e);
}
catch (UnsupportedEncodingException e) {
System.out.println("Problem encoding password: " + e);
}
return false;
}

public boolean userChangePassword(String sUserName, String sOldPassword, String sNewPassword){
try {
//StartTlsResponse tls = (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
//tls.negotiate();

//change password is a single ldap modify operation
//that deletes the old password and adds the new password
ModificationItem[] mods = new ModificationItem[2];

//Firstly delete the "unicdodePwd" attribute, using the old password
//Then add the new password,Passwords must be both Unicode and a quoted string
String oldQuotedPassword = "\"" + sOldPassword + "\"";
byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE");
String newQuotedPassword = "\"" + sNewPassword + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", oldUnicodePassword));
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));

// Perform the update
ctx.modifyAttributes(sUserName, mods);

System.out.println("Changed Password for: " + sUserName);
//tls.close();
return true;

}
catch (NamingException e) {
System.err.println("Problem changing password: " + e);
}
catch (UnsupportedEncodingException e) {
System.err.println("Problem encoding password: " + e);
} catch ( Exception e){
System.err.println("Problem: " + e);
}
return false;
}

public boolean createNewUser(String sGroupName, String sUserName){
try {
// Create attributes to be associated with the new user
Attributes attrs = new BasicAttributes(true);

//These are the mandatory attributes for a user object
//Note that Win2K3 will automagically create a random
//samAccountName if it is not present. (Win2K does not)
attrs.put("objectClass","user");
attrs.put("sAMAccountName","AlanT");
attrs.put("cn","Alan Tang");

//These are some optional (but useful) attributes
attrs.put("givenName","Alan");
attrs.put("sn","Tang");
attrs.put("displayName","Alan Tang");
attrs.put("description","Engineer");
attrs.put("userPrincipalName","alan-AT-joeyta.local");
attrs.put("mail","alang-AT-mail.joeyta-DOT-local");
attrs.put("telephoneNumber","123 456 789");

//some useful constants from lmaccess.h
int UF_ACCOUNTDISABLE = 0x0002;
int UF_PASSWD_NOTREQD = 0x0020;
int UF_PASSWD_CANT_CHANGE = 0x0040;
int UF_NORMAL_ACCOUNT = 0x0200;
int UF_DONT_EXPIRE_PASSWD = 0x10000;
int UF_PASSWORD_EXPIRED = 0x800000;

//Note that you need to create the user object before you can
//set the password. Therefore as the user is created with no
//password, user AccountControl must be set to the following
//otherwise the Win2K3 password filter will return error 53
//unwilling to perform.

attrs.put("userAccountControl",Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD + UF_PASSWORD_EXPIRED+ UF_ACCOUNTDISABLE));

// Create the context
Context result = ctx.createSubcontext(sUserName, attrs);
System.out.println("Created disabled account for: " + sUserName);

//now that we've created the user object, we can set the
//password and change the userAccountControl
//and because password can only be set using SSL/TLS
//lets use StartTLS

//StartTlsResponse tls = (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
//tls.negotiate();

//set password is a ldap modfy operation
//and we'll update the userAccountControl
//enabling the acount and force the user to update ther password
//the first time they login
ModificationItem[] mods = new ModificationItem[2];

//Replace the "unicdodePwd" attribute with a new value
//Password must be both Unicode and a quoted string
String newQuotedPassword = "\"P-AT-ssw0rd\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));
mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userAccountControl",Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWORD_EXPIRED)));

// Perform the update
ctx.modifyAttributes(sUserName, mods);
System.out.println("Set password & updated userccountControl");


//now add the user to a group.

try {
ModificationItem member[] = new ModificationItem[1];
member[0]= new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("member", sUserName));

ctx.modifyAttributes(sGroupName,member);
System.out.println("Added user to group: " + sGroupName);

}
catch (NamingException e) {
System.err.println("Problem adding user to group: " + e);
}
//Could have put tls.close() prior to the group modification
//but it seems to screw up the connection or context ?
//tls.close();

System.out.println("Successfully created User: " + sUserName);
return true;

}
catch (NamingException e) {
System.err.println("Problem creating object: " + e);
}

catch (IOException e) {
System.err.println("Problem creating object: " + e);
}
return false;
}

public boolean addUserToGroup(LdapContext ctx, String userDN, String groupDN) {
try{
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("member", userDN));
ctx.modifyAttributes(groupDN, mods);
System.out.println("Added user " + userDN + " to group " + groupDN);
return true;
} catch (NamingException ne){
System.err.println("Problem add user to group: " + ne);
}
return false;
}

public boolean removeUserFromGroup(LdapContext ctx, String userDN, String groupDN) {
try{
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("member", userDN));
ctx.modifyAttributes(groupDN, mods);
System.out.println("Remove user " + userDN + " from group " + groupDN);
return true;
} catch (NamingException ne){
System.err.println("Problem remove user from group: " + ne);
}
return false;
}

}
/***************************** LDAPFastBind.java *****************/





/***************************** LDAPClient.java *****************/
package test.ldap;

class LDAPClient {
public static void main(String[] args) {
// Could also use ldaps over port 636 to protect the communication to
// the
// Active Directory domain controller. Would also need to add
// env.put(Context.SECURITY_PROTOCOL,"ssl") to the "server" code
//String ldapurl = "ldap://joeyserver.joeyta.local:389";
String ldapurl = "ldap://joeyserver.joeyta.local:636";

LDAPFastBind ctx = new LDAPFastBind(ldapurl);

String sAdminUserName = "CN=Administrator,CN=Users,DC=joeyta,DC=local";
String sAdminPassword = "I@mRoot";

// String sUserName = "CN=peter lee,CN=Users,DC=joeyta,DC=local";
String sUserName = "joeyta\\peter";
// String sUserName = "peter@joeyta.local";

String sOldPassword = "P@ssw0rd";
String sNewPassword = "P@$w0rd";

String sNewUserName = "CN=Alan Tang,CN=Users,DC=joyeta,DC=local";
String sNewGroupName = "CN=test,CN=Users,DC=joeyta,DC=local";

boolean IsAuthenticated = ctx.Authenticate(sAdminUserName, sAdminPassword);
// boolean IsAuthenticated = ctx.Authenticate(sUserName, sOldPassword);

ctx.printUserAccountControl();

ctx.createNewUser(sNewGroupName, sNewUserName);

//boolean IsAdminSuccessChangePWD = ctx.adminChangePassword(sUserName,sNewPassword);
//boolean IsUserSuccessChangePWD = ctx.userChangePassword(sUserName,sOldPassword,sNewPassword);

ctx.finito();

}
}
/***************************** LDAPClient.java *****************/

Saturday, December 15, 2007

Ubuntu 好用軟體

edonkey - aMule

sudo apt-get install aMule

不用說了吧,反正就是那回事,中文,日文都 ok 的啦

IM - Gaim(Pidgin)

萬用 Instant Messager,Ubuntu內建,新版改名叫 Pidgin,變得漂亮多了

BBS - PCManX

sudo apt-get install pcmanx-gtk2

好用的 BBS client,記得要換字型比較好看

Packet Sniffer - Ethereal

sudo apt-get install ethereal

看封包內容的軟體,功能強大,不過我只拿來 debug http 的 resquest/response

BT - Deluge

sudo apt-get install deluge-torrent

就是 BT,gnome 是有內建,但是那個太陽春了,換這個 python 寫的吧

看漫畫 - Comix

sudo apt-get install comix

這個超讚,用電腦看漫畫必備!可以設定左右兩頁合併成一頁,也支援右頁翻到左頁 (漫畫都是右到左)。當然你要拿來瀏覽一般圖片也行,速度很快。

向量繪圖 - Inkscape

sudo apt-get install inkscape

雖然我不會美工,但有時候還是得改一些 icon,或是做一些簡單的 logo。inkscape 用起來挺直覺的,連我這個繪圖白吃都玩的起~

安裝外部軟體 - Automatix

sudo apt-get install automatix2

Skype, Adobe Reader, Windows codec, 讀寫 NTFS 等等涉及版權的軟體安裝起來都超麻煩的,這時 Automatix 就派上用場了,點幾下那些難纏的軟體通通裝好設定完全。爽~

錄音 - Audacity

sudo apt-get install audacity

多軌錄音軟體,介面很醜... 不過夠我錄音樂用了。

看影片 - vlc

sudo apt-get install vlc

你什麼 codec 都可以不裝,就是不能漏掉這個 vlc,連 wmv9 都可以看,真是天賜啊

字典 - 星際譯王

sudo apt-get install stardict

沒有這個字典活不下去

virtual machine - VirtualBox

sudo apt-get install virtualbox

我已經放棄 vmware 了,vmware player 太陽春,vmware workstation 要錢,vmware server 安裝太麻煩。每次 kernel 升級 vmware 就要重新 compile... etc 真是煩死了。一氣之下轉換到 virtualbox,從此過著幸福快樂的日子。還死守在 vmware 的同胞們快點換吧~

screen action - brightside

sudo apt-get install brightside

裝了這個就可以設定滑鼠碰觸畫面角落,開啟特定程式或是顯示桌面,我用慣 mac 的滑鼠顯示桌面了,所以裝這個來模擬。

Palm - J-Pilot

sudo apt-get install jpilot

如果你跟我一樣還在用那個不上道的 palm (treo650),這個可以解決 sync 的問題,Big5 中文也通喔!(如果弄得到 iphone 我就把 treo 給丟了)

nVidia - envy

sudo apt-get install envy

nVidia 的用戶,一定得安裝 envy。這個軟體可以解決所有有關 nVidia 的問題,XWindow 裝不起來嗎?beryl 特效弄不出來嗎?想裝 nVidia 官方的 driver 嗎?裝 envy 就對了。我的 LCD 是 LED 背光,因此顏色是偏藍的,這時就得靠 nVidia 官方的 nvidia-setting 這個工具來微調了。用 envy 安裝官方 driver 後,輕輕鬆鬆搞定!

Google Desktop

http://desktop.google.com/linux

google 最新推出的 linux 版桌面搜尋,安裝後 ctrl 兩下就能搜尋囉,還蠻好用地,算是補足 linux 一直欠缺的功能。啥?你說之前已經有 beagle 了?拜託,那是用 mono 寫得耶,好不容易轉到 linux 了,幹嘛還被 ms 套牢?

中文字型 OpenDesktop Font

http://www.opendesktop.org.tw/modules/news/article.php?storyid=106

經由 OpenDesktop 團隊的努力,我們有全世界最漂亮、最清楚的中文字型囉。Mac上字型透過獨家的 render 技術產生的字型很棒,但就算 render 技術再強,永遠也比不上一個個精雕細啄的點陣字啊!

其他太基本的 gcin, java, eclipse, gimp, remote desktop 等等就不提了