Archive for August 18th, 2010


3 cách viết code trong Flex

Giống như Flash có cách viết code trên frame, trên đối tượng (AS2), hoặc dùng linkage với file bên ngoài.

Flex có những cách code tương tự như sau :

1. Code trực tiếp trên file mxml với thẻ scritp:

Code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="helloWorld();">
	<mx:Script>
		<![CDATA[
			public function helloWorld(): void {
				labelHello.text = "Hello World";
			}
		]]>
	</mx:Script>
	<mx:Label id="labelHello"  color="#FFFFFF" width="150"/>
</mx:Application>

2. Code trên file as rồi include vào :

File myscript.as (tạo = New ActionScript File)

Code:
// ActionScript file
public function helloWorld(): void {
	labelHello.text = "Hello World";
}

File mxml:

Code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="helloWorld();">
	<mx:Script>
		<![CDATA[
			include "myscript.as";
		]]>
	</mx:Script>
	<mx:Label id="labelHello"  color="#FFFFFF" width="150"/>
</mx:Application>

3. Dùng class (code behind): đây là cách tốt nhất. Code 1 nơi, layout 1 nơi, rõ ràng, dễ đọc.

MyVBox class (tạo = New AS Class) :

Code:
package
{
	import mx.controls.Label;
	import mx.containers.VBox;
	import mx.events.FlexEvent;

	public class MyVBox extends VBox
	{
		public var labelHello: Label;

		public function MyVBox()
		{
			super();
			this.addEventListener(FlexEvent.CREATION_COMPLETE, helloWorld);
		}

		public function helloWorld(event: FlexEvent): void {
			labelHello.text = "Hello World";
		}

	}
}

File MyVBoxComp.mxml:

Code:
<?xml version="1.0" encoding="utf-8"?>
<MyVBox xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
	<mx:Label id="labelHello"  color="#FFFFFF" width="150"/>
</MyVBox >

File TestApplication.mxml:

Code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*">
	<local:MyVBoxComp />
</mx:Application>

Tùy từng trường hợp mà chúng ta đặt code cho thích hợp. Nếu code đơn giản thì xài cách 1 hoặc 2, còn ko xài cách 3 để pro hơn 1 chút.

Copyright: http://vnfx.com/vb/showthread.php?t=3973

GIỚI THIỆU VỀ KỸ THUẬT LẬP TRÌNH HOOK

Có bao giờ các bạn đặt ra câu hỏi là tại sao chúng ta có thể gõ tiếng Việt được trong Microsoft Word và các phần mềm soạn thảo văn bản khác hay không? Rõ ràng là chúng ta không thể can thiệp vào mã của Microsoft Word để sửa thành tiếng Việt khi chúng ta muốn soạn thảo văn bản tiếng Việt. Vậy thì tại sao các phần mềm như VietKey, VNI-TanKy lại có thể làm được điều này? Câu trả lời là sử dụng các Hook. Trong bài viết này, chúng ta sẽ cùng tìm hiểu xem Hook là gì mà có thể làm được điều thần kỳ như vậy!Truớc khi chúng ta tìm hiểu về Hook , chúng ta nhắc lại một chút về quá trình xử lý thông điệp của hệ điều hành WindowsQuá trình xử lý thông điệp của Windows diễn ra như sau : Đầu tiên từ các hành động của nguời dùng như là : click chuột, nhấn phím, .. thì hệ điều hành sẽ chuyển các hành động tương ứng thành các thông điệp (message). Rồi sau đó Windows đẩy các message này vào hàng đợi của hệ thống (system queue) và từ system queue các message đuợc chuyển cho các hàng đợi của ứng dụng (application queue). Từ lúc này các ứng dụng sẽ lấy các message này trong hàng đợi ứng dụng của mình để xử lý (thông qua các vòng lặp chờ thông điệp – message loop).1. Hook là gì ?Hook là cơ chế mà nhờ đó một hàm có thể chặn các sự kiện (message, mouse actions, keystrokes ) trước khi chúng được gửi đến hàng đợi của ứng dụng. Các hàm này có thể thực hiện một số thao tác trên sự kiện, và trong một vài trường hợp có thể định nghĩa lại hoặc hủy bỏ sự kiện mà nó chặn được. Một điểm quan trọng cần lưu ý là các hàm này được gọi bởi chính Windows chứ không phải bởi ứng dụng của chúng ta.Windows hỗ trợ nhiều loại hook khác nhau, mỗi loại nhắm đến việc chặn bắt một loại thông điệp cụ thể nào đó. Ví dụ, một ứng dụng có thể sử dụng WH_KEYBOARD để giám sát sự di chuyển của thông điệp bàn phím trong hệ thống. Nhờ loại hook này mà một chương trình có thể can thiệp vào và tạo ra khả năng gõ tiếng Việt khi soạn thảo văn bản. Một loại hook khác là WH_MOUSE cho phép theo dõi các thông điệp liên quan đến hoạt động của con chuột.Hình trên mô tả quá trình xử lý thông điệp của Windows khi có sử dụng các Hook .Thì như trên hình vẽ chúng ta có thể thấy rõ ràng rằng ,một khi chúng ta sử dụng các Hook thì các Hook này sẽ được đặt nằm giữa System Queue và Application Queue .2. Cơ chế hoạt động của HookHệ thống duy trì một chuỗi hook (hook chain) cho mỗi loại hook. Mỗi chuỗi này là một danh sách liên kết các con trỏ đặt biệt, con trỏ này chính là các hàm callback của ứng dụng có sẵn, nó còn được gọi là hàm hook (hàm lọc, filter function)Khi có một thông điệp được sinh ra thuộc một loại hook nào đó, nó sẽ được hệ thống đẩy đi vào hàm hook đầu tiên trong chuỗi, lần lượt từng hàm một (qua tất cả các hook trong chuỗi). Công việc của hàm hook có thể phức tạp hay đơn giản tùy thuộc vào từng loại hook. Hàm hook cho một số loại chỉ có thể giám sát, số khác có thể sửa đổi thông điệp hoặc dừng lại việc xử lý thông điệp trên chuỗi hook trước khi chúng đến các hook tiếp theo hoặc đến cửa sổ đích.3. Ứng dụng của Hook- Cho phép tạo ra các chương trình hỗ trợ gõ tiếng Việt như : Vietkey- Cho phép tạo ra các chuơng trình Test tự động phần mềm (bằng cách phát sinh các sự kiện phím, chuột giống như người dùng đang nhập vào).- Cho phép thay đổi giao diện các ứng dụng đang chạy.- Cho phép xem phần trợ giúp của các ứng dụng bằng việc nhấn một phím nào đó, ví dụ như nhấn F1 chẳng hạn- Và nhiều ứng dụng khác nữa tùy vào trí tưởng tượng của các bạn !…4 . Cài đặt HookGiao diện lập trình ứng dụng (API) của Windows cung cấp 3 hàm để thao tác với hook :• SetWindowsHookEx• UnhookWindowsHookEx• CallNextHookExa) Cài đặt một Filter Function vào chuỗi các Filter Function của một hookTác vụ này được thực hiện thông qua hàm SetWindowsHookEx, khai báo của hàm này như sau :HHOOK SetWindowsHookEx( int idHook, HOOKPROC lpfn,HINSTANCE hMod, DWORD dwThreadId);Ý nghĩa của từng tham số :idHook: Xác định loại hook mà ta muốn cài đặt, tham số này có thể là một trong các giá trị sau :• WH_CALLWNDPROC : đặt một thủ tục hook quản lý các thông điệp trước lúc hệ thống gởi chúng tới cửa sổ đích.• WH_CALLWNDPROCRET : đặt một thủ tục hook quản lý các thông điệp sau khi chúng được xử lý bởi thủ tục cửa sổ đích.• WH_CBT : đặt một thủ tục hook nhận những thông báo có ích tới ứng dụng huấn luyện trên cơ sở tính toán (CBT).• WH_DEBUG : đặt một thủ tục hook có ích cho việc debug những thủ tục hook khác.• WH_FOREGROUNDIDLE : đặt một thủ tục hook sẽ được gọi khi thread foreground của ứng dụng sẽ trở thành không dùng đến. Hook này có ích cho hoạt động những nhiệm vụ (task) độ ưu tiên thấp trong thời gian không được dùng đến.• WH_GETMESSAGE : đặt một thủ tục hook quản lý các thông điệp được post tới hàng đợi thông điệp.•WH_JOURNALPLAYBACK : đặt một thủ tục hook post những thông điệp được ghi trước đó bởi thủ tục hook WH_JOURNALRECORD.•WH_JOURNALRECORD : đặt một thủ tục hook ghi những thông điệp đầu vào được post tới hàng thông điệp hệ thống. Hook này có ích cho việc ghi các macro.• WH_KEYBOARD : đặt một thủ tục hook quản lý các thông điệp keystroke.• WH_MOUSE : đặt một thủ tục hook quản lý các thông điệp chuột.• WH_MSGFILTER: đặt một thủ tục hook quản lý các thông điệp được kết sinh như là một kết quả cuả sự kiện đầu vào ở trong dialog box, message box, menu hay scroll bar.• WH_SYSMSGFILTER : đặt một ứng dụng các thông điệp được kết sinh như là kết quả của một sự kiện đầu vào ở trong dialog box, message box, menu hay scroll bar. Thủ tục hook quản lý những thông điệp này cho tất cả các ứng dụng trong hệ thống.Mỗi giá trị trên xác định một loại hook mà ta muốn cài đặt, mỗi loại hook có một ý nghĩa và tình huống sử dụng khác nhau.lpfn : Địa chỉ của Filter Function mà ta muốn gắn với hook.hMod : Handle của module chứa Filter Function. Nếu ta cài đặt một hook cục bộ (nghĩa là sự thực thi của Filter Function chỉ ảnh hưởng đối với tiến trình cài đặt hook), tham số này phải là NULL. Còn nếu chúng ta muốn có một hook với phạm vi toàn hệ thống (tức là mọi tiến trình đang hiện hữu đều chịu ảnh hưởng bởi Filter Function của chúng ta), tham số này sẽ là Handle của DLL chứa Filter Function.dwThreadID : Định danh của thread ứng với hook đang được cài đặt . Nếu tham số này là một số khác 0, Filter Function được gắn với hook chỉ được gọi trong ngữ cảnh của một thread xác định. Còn nếu dwThreadID = 0, Filter Function sẽ có phạm vi toàn hệ thống, và dĩ nhiên, nó sẽ được gọi trong ngữ cảnh của bất kỳ thread nào đang tồn tại trên HĐH. Có thể sử dụng hàm GetCurrentThreadId để lấy được handle của thread muốn cài đặt hook.Một hook có thể được sử dụng ở mức hệ thống, ở mức cục bộ, hoặc ở cả hai mức vừa nêu. Bảng sau mô tả các loại hook cùng tầm ảnh hưởng của nó :WH_CALLWNDPROCThread , GlobalWH_CALLWNDPROCRETThread , GlobalWH_CBTThread , GlobalWH_DEBUGThread , GlobalWH_FOREGROUNDIDLEThread , GlobalWH_GETMESSAGEThread , GlobalWH_JOURNALPLAYBACKGlobalWH_JOURNALRECORDGlobalWH_KEYBOARDThread , GlobalWH_MOUSEThread , GlobalWH_MSGFILTERThread , GlobalWH_SYSMSGFILTERGlobalVới một loại hook xác định, hook cục bộ sẽ được gọi trước, sau đó là hook toàn cục.B ) Gỡ bỏ một Filter Function ra khỏi chuỗi các Filter Function của một hookWindows cung cấp hàm UnhookWindowsHookEx giúp chúng ta thực hiện việc này. Khai báo của nó như sau :BOOL UnhookWindowsHookEx( HHOOK hhk);Tham số : hhook chỉ ra hàm hook được dỡ bỏ . Đây là giá trị được trả vể bởi hàm SetWindowsHookEx khi hàm Hook được cài đặt.Chú ý : Hàm UnhookWindowsHookEx phải được sử dụng trong sự kết hợp với hàm SetWindowsHookEx.c) Chi tiết về Filter FunctionFilter Function là một hàm được gắn với loại hook mà chúng ta muốn cài đặt. Hàm này được gọi bởi hệ điều hành Windows chứ không được gọi bởi ứng dụng, đây cũng là lý do mà người ta thường gọi nó là “Callback Function”. Tuy nhiên , để thống nhất về mặt thuật ngữ, từ nay về sau chúng ta vẫn gọi nó là Filter Function.Tất cả các Filter Function đều có dạng sau :LRESULT CALLBACK FilterFunc(int nCode, WPARAM wParam, LPARAM lParam);Ở đây “FilterFunc” chỉ là tên hàm tượng trưng, khi cài đặt, Filter Function sẽ có tên bất kỳ theo ý của người lập trình .Ý nghĩa của từng tham số truyền cho hàm :nCode : tham số này thường được gọi là “hook code”, Filter Function sử dụng giá trị này để quyết định cách thức xử lý đối với sự kiện. Giá trị của hook code tùy thuộc vào từng loại hook cụ thể, và mỗi loại hook sẽ có tập hợp những giá trị hook code đặc trưng của riêng mình. Có một quy luật mà dường như các Filter Function của mọi loại hook cần tuân thủ : Khi Windows truyền cho hàm giá trị hook code âm, Filter Function không được xử lý sự kiện mà phải gọi hàm CallNextHookEx với chính những tham số mà hệ điều hành truyền cho nó. Sau đó, nó phải trả về giá trị được trả về bởi hàm CallNextHookEx.wParam, lParam: Đây là những thông tin cần thiết cho Filter Function trong quá trình xử lý sự kiện. Các giá trị này sẽ có ý nghĩa khác nhau tuỳ thuộc vào từng loại hook. Ví dụ , Filter Function gắn với hook WH_KEYBOARD sẽ nhận mã phím ảo (Virtual-Key Code) từ wParam, đồng thời có được từ lParam thông tin mô tả trạng thái của bàn phím khi sự kiện gõ phím xảy ra.d) Gọi Filter Function kế tiếp trong chuỗi các Filter FunctionKhi một hook được cài đặt, Windows gọi hàm đầu tiên trong chuỗi các Filter Function, và kể từ thời điểm này, trách nhiệm Windows không còn nữa. Filter Function hiện hành phải đảm bảo với hệ thống là có được lời gọi đến hàm kế tiếp trong chuỗi các Filter Function. Bởi lẽ, có thể có một ứng dụng khác cũng cài đặt cùng loại hook để thi hành một số tác vụ nào đó, và nếu như ta không cho Filter Function của ứng dụng này tham gia xử lý sự kiện, sẽ có vấn đề rắc rối xảy ra. Vấn đề sẽ càng trở nên nghiêm trọng nếu ứng dụng này là một chương trình thuộc hệ thống, và rõ ràng sẽ không có gì đảm bảo cho sự an toàn của hệ thống chúng ta. Để giải quyết vấn đề trên, hãy sử dụng hàm CallNextHookEx, khai báo của nó như sau :LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam );hhk : là handle của hook hiện hành, giá trị này có thể lấy được từ hàm SetWindowsHookEx khi cài đặt hook.nCode : chỉ định hook code để gởi đến hook kế tiếp. Hàm xử lý hook dùng giá trị này để chỉ định xử lý thông điệp được gởi từ hook như thế nào .wParam: chỉ định 16 bits thông tin mở rộng của thông điệp.lParam: chỉ định 32 bits thông tin mở rộng của thông điệp.Giá trị trả về : giá trị trả về là kết quả của quá trình xử lý và tùy thuộc vào thông số nCodeTrong một số tình huống, Filter Function hiện hành có thể không muốn chuyển sự kiện cho Filter Function khác trong cùng một chuỗi. Lúc này, nếu loại hook chúng ta đang cài đặt cho phép huỷ bỏ sự kiện, và Filter Function của chúng ta cũng có cùng quyết định là hủy bỏ, nó sẽ không phải gọi hàm CallNextHookEx.5. Chương trình minh họaĐể hiểu rõ hơn về Hook ,các bạn có thể xem một ví dụ đơn giản về sử dụng Hook. Trong ví dụ này chúng ta sẽ cài đặt một Hook ,cho phép đọc thông tin về menu bar chuẩn của bất kỳ chương trình ứng dụng nào và lưu các thông tin này thành một tập tin resource (để sau đó ta có thể dễ dàng sử dụng trong chương trình của mình!)Trong ví dụ này chúng ta sẽ sử dụng Hook WH_GETMESSAGE để chặn bắt các thông điệp gửi đến hàng đợi thông điệp . Và khi chương trình của chúng ta bắt được thông điệp WM_NCLBUTTONDOWN (thông điệp này đuợc phát sinh khi chúng ta click chuột lện thanh tiêu đề của cửa sổ) , chương trình sẽ cho mở hộp thoại Save As để cho nguời dùng chọn đường dẫn và đặt tên cho file resource sẽ được tạo ra .Và lúc này chuơng trình sẽ lưu toàn bộ nội dung của menubar xuống thành file resource mà chúng ta đã đặt tên.* Trong ví dụ này vì ta muốn lấy thông tin về menu bar của tất cả ứng dụng trên Windows nên ta phải sử dụng một tập tin .DLL để lập một Hook loại toàn cục (còn các hook loại cục bộ chỉ cho phép chặn các thông điệp trong nội bộ ứng dụng có cài đặt Hook mà thôi).

Tổng Quan Về Kỹ Thuật Subclass

Hệ điều hành Windows điều khiển các ứng dụng bằng cách gửi các Message đến các Window của các ứng dụng. Những Message này thông báo đến các Window, cho chúng biết khi nào có cú nhắp chuột…và tất cả các thông tin cần thiết khác để Window ứng xử chính xác. Theo cách này, một ứng dụng Windows tối thiểu phải chứa một hàm để xử lí các Message này (hàm WindowProc). Hàm này được khai báo với hệ thống khi Window được tạo để Windows có thể biết sẽ gửi Message đó cho ai, và không bao giờ nhầm lẫn.Ở đây chúng tôi xin lưu ý để các bạn không bị nhầm lẫn. Thông thường chúng ta quan niệm một Window là một cửa sổ chương trình. Nhưng theo cái nhìn của HĐH Windows thì một Window có thể là một Form, có thể là một TextBox và cũng có thể là một Button… Vì thế nên từ Window mà chúng tôi dùng ở đây là chỉ tất cả các Control chứ không phải là một Form như chúng ta đã thường nghĩ.Trở lại vấn đề, trong lập trình Windows, Hook(hay còn gọi là Subclass) là kĩ thuật mà trong đó chúng ta sẽ chặn những sự kiện (các message, các cú nhấn chuột, các cú gõ phím) trước khi chúng đến được ứng dụng. Hàm này có thể làm việc trên các sự kiện, hoặc trong một số trường hợp có thể thay đổi hoặc vô hiệu chúng. Hàm chuyên nhận các sự kiện gọi là filter functions (chúng tôi tạm dịch là hàm xử lý Message) và được phân loại tùy theo sự kiện mà nó nhận xử lý.Kĩ thuật Hook cung cấp một khả năng lập trình rất mạnh, vượt ra ngoài những gì mà môi trường lập trình cung cấp cho chúng ta. Sử dụng kĩ thuật Hook chúng ta có thể xử lí, thay đổi tất cả các Message cho tất cả các control và Dialog Box hoặc Menu của ứng dụng và của hệ thống. Ta cũng có thể chặn bất kì một Message nào khi hàm SendMessage được gọi. Nói chung với kỹ thuật này chúng ta có thể biết được những gì đang xảy ra và thực sự làm chủ chương trình.Cách SubClass1. Tạo một Project mới với tên mặc định là Form1.2. Thêm vào hai nút bấm (Command Button) với tên là Command1 và Command2.3. Thêm đoạn Code sau vào một Module :D eclare Function CallWindowProc Lib “user32″ Alias _”CallWindowProcA” (ByVal lpPrevWndFunc As Long, _ByVal hwnd As Long, ByVal Msg As Long, _ByVal wParam As Long, ByVal lParam As Long) As LongDeclare Function SetWindowLong Lib “user32″ Alias _”SetWindowLongA” (ByVal hwnd As Long, _ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPublic Const GWL_WNDPROC = -4Public Const WM_LBUTTONDOWN = &H201Public IsHooked As BooleanGlobal lpPrevWndProc As LongGlobal gHW As LongPublic Sub Hook()If IsHooked ThenMsgBox “Dung hook hai lan mà khong unhook ” & _”neu khong ban se khong the hook.”ElselpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _AddressOf WindowProc)IsHooked = TrueEnd IfEnd SubPublic Sub Unhook()Dim temp As Longtemp = SetWindowLong(gHW, GWL_WNDPROC,lpPrevWndProc)IsHooked = FalseEnd SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As _Long, ByVal wParam As Long, ByVal lParam As Long) As LongIf uMsg = WM_LBUTTONDOWN ThenMsgBox “Hook Test”ElseWindowProc = CallWindowProc(lpPrevWndProc, hw, _uMsg, wParam, lParam)End IfEnd Function3. Thêm vào Form đoạn code sau:Private Sub Form_Load()gHW = Me.hwndCommand1.Caption = “Hook”Command2.Caption = “Unhook”End SubPrivate Sub Command1_Click()HookEnd SubPrivate Sub Command2_Click()UnhookEnd SubPrivate Sub Form_QueryUnload(Cancel As Integer, UnloadMode _As Integer)If IsHooked ThenCancel = 1MsgBox “Unhook truoc khi dong, neu khong VB se Crash, va moi thu ban lam se mat.”End IfEnd Sub4. Chạy ứng dụng, nhấn vào nút Hook. Sau đó bấm chuột trái lên Form, một Message box sẽ xuất hiện. Nếu không có lỗi gì thì bạn đã thành công rồi đấy.Phân tích:Bạn đừng xem thường ví dụ vừa rồi. Nó có vẻ hơi tầm thường (xét về tác dụng) nhưng lại chứa đựng trong đó rất nhiều thứ. Sau đây tôi sẽ phân tích tỉ mỉ từng bước cho các bạn.Đầu tiên có một điều cần nhớ là phải bấm vào nút Unhook trước khi đóng ứng dụng, đây là điều quan trọng vì nếu không VB sẽ đỗ vỡ, và nếu bạn quên chưa lưu thì mọi công lao của bạn sẽ đi xuống biển. Vì thế hãy cẩn thận lưu trước khi chạy thử vì không phải lúc nào bạn cũng làm đúng đâu. Một điều hay nữa là hàm của bạn sẽ xử lí trước tất cả các sự kiện của VB. Ví dụ như nếu bây giờ bạn thêm vào sự kiện Form_MouseClick() một công việc gì đó thì nó sẽ không có tác dụng (trừ phi bạn nhấp chuột trái). Bạn có thể tự thử lấy.Để có thể Hook được một Windows bạn cần phải biết một thứ rất quan trọng đó là Handle của Window cần Hook. Đây là một số nguyên đặc trưng cho mỗi Window, bạn không thể tạo ra nó nhưng có thể truy cập nó bằng thuộc tính hWnd (Ví dụ: Form1.hWnd, Text1.hWnd…). Bây giờ chúng ta trở lại với ví dụ trên. Công việc đầu tiên của kĩ thuật Hook là phải báo với Window hàm xử lý Message của bạn nằm ở đâu trong bộ nhớ để Windows sẽ truyền tham số vào đó khi cần thiết. Chúng ta sử dụng hàm SetWindowLong để làm việc này.lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)Hàm SetWindowLong có nhiều chức năng khác, trong trường hợp này nó sẽ thay đổi hàm xử lí Message bằng hàm WindowProc do ta định nghĩa. Sau đó nó sẽ lưu lại điạc chỉ trong bộ nhớ của hàm xử lý Message cũ vào biến lpPrevWndProc chúng ta sẽ cần dùng lại nó sau này.Sau khi đã khai báo xong với Windows chúng ta hoàn có thể tiến hành kĩ thuật Hook. Bây giờ chúng ta hãy xem lại cái quan trọng nhất của chương trình – hàm xử lí Message :Function WindowProc(ByVal hw As Long, ByVal uMsg As _Long, ByVal wParam As Long, ByVal lParam As Long) As LongIf uMsg = WM_LBUTTONDOWN ThenMsgBox “Hook Test”ElseWindowProc = CallWindowProc(lpPrevWndProc, hw, _uMsg, wParam, lParam)End IfEnd FunctionKhi hàm này được chạy, nó sẽ có 4 đối số, 4 đối số này sẽ được Windows truyền cho hàm mỗi khi có một sự kiện, đây là ý nghĩa của các đối số :*hw chính là Handle của Window nhận Message (trong ví dụ này chính là Handle của Form).*uMsg là Message mà Windows gửi đến cho hàm (bạn sẽ chặn những Message này).*Còn wParam và lParam là các thông tin đi kèm theo Message, các thông tin này đôi khi cũng rất quan trọng nhưng trong trường hợp này ta chưa cần đến chúng. Chúng ta sẽ gặp lại chúng trong các ví dụ sau.Trong đó đối số quan trọng nhất là uMsg. Nó là những Message do HĐH Windows gửi đến, và chính là những gì mà chúng ta sẽ chặn lại. Trong ví dụ trên chúng ta đã chặn Message WM_LBUTTONDOWN lại để xử lí. Các Message được gửi đến bằng những con số, chúng được lưu trong các hằng, có thể tìm thấy các hằng này trong thư viện MSDN hoặc API Text-Viewer. Nếu không có Message mà ta muốn chặn thì ta phải trả quyền hoạt động lại cho hàm xử lí Message cũ, đây là điều rất quan trọng và bạn không được phép quên, nếu không chương trình của bạn sẽ chẳng đáp ứng gì đâu. Để trả lại các Message không cần thiết cho hàm xử lí cũ ta sử dụng hàm CallWindowProc, hàm này sẽ gửi trả lại những đối số do Windows gửi đến lại cho hàm xử lý Message cũ, lpPrevWndProc là địa chỉ của hàm xử lý Message cũ trong bộ nhớ mà chúng ta đã lưu lại từ trước :WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)Bạn đã thấy vì sao chúng tai phải lưu lại địa chỉ trong bộ nhớ của hàm xử lý Message cũ rồi chứ (lpPrevWndProc). Đấy là những công việc mang tính thủ tục mà ta cần phải làm khi áp dụng kĩ thuật Subclass.Note: Trong ví dụ trên bạn phải bấm vào nút Hook để thực sự bắt đầu Hook, và nhớ Unhook trước khi kết thúc chương trình. Nếu bạn đang vò đầu bức tai không hiểu tại sao nó không chạy thì đây là lời giải đáp cho bạn.

Cách viết Module trên Drupal

MODULE TRONG DRUPAL?Module là một nhóm những chức năng nhất định, gồm những thuộc tính cơ bản:+ Name: tên chính thức của module, ảnh hưởng trực tiếp đến những hàm kết nối với hệ thống.+ Display name: tên gợi nhớ, được trình bày ở trang điều hành module.+ Description: giới thiệu ngắn gọn về các chức năng của module, được trình bày ở trang điều hành module.+ Version: mã số phiên bản của module.+ Dependencies: tên của module mà module đang thiết kế yêu cầu tới (trong trường hợp sử dụng hàm từ module khác), nếu có nhiều module thì các module này cách nhau bởi dấu phẩy. Module không thể được kích hoạt nếu các module được yêu cầu không tồn tại hoặc chưa được kích hoạt.+ Package: phân nhóm chức năng chứa đựng module.Một điểm hay của Drupal là cho phép người phát triển module có thể sử dụng lại những hàm đã được viết ở các module khác để xây dựng module cho mình. Module có thể tự động ngưng hoạt động tạm thời để giảm tải cho máy chủ khi có quá nhiều truy cập bằng cách bật module throttle (quản lý cơ chế tự động điều chế sự tắt nghẽn hệ thống) và chọn sử dụng chức năng điều tiết lưu lượng. Chức năng tự động điều tiết có thể được bật thông qua trang cấu hình throttle sau khi đã bật module throttle.Mỗi module phải xử lý được các sự kiện hoặc định nghĩa các sự kiện riêng của nó. Mỗi thao tác cần được phân quyền rõ ràng. Việc phân quyền này thuộc về người điều hành. Mỗi thao tác cần có một internal path (hay drupal path) nhất định.Thông tin được khai báo rõ ràng qua tập tin .info, điều đó sẽ làm cho người điều hành dễ quản lý. Không cần quan tâm nhiều đến quyền hạn truy cập. Module được tách ra một thư mục cụ thể để quản lý một cách dễ dàng.Phát triển module không cần thay đổi phần nhân của mã nguồn, khi nhân có lỗi bảo mật, việc cập nhật trở nên dễ dàng. Việc gán các quyền truy cập với các vai trò thuộc về người điều hành, người điều hành không bị ràng buộc bởi quyền truy cập nào. Mỗi module có thể định nghĩa cho riêng nó những quyền hạn truy cập khác nhauHOOK TRONG DRUPAL?Hook được xem như là các sự kiện (event) bên trong bộ nhân Drupal. Hook được gọi là các hàm callbacks, đây là cách phổ biến nhất để tương tác với nhân Drupal. Module sử dụng hook để tương tác với hệ thống. Mỗi hook có tham số và giá trị trả về nhất định. Một hook là một hàm PHP được đặt tên theo dạng: codepro_menu(), trong đó codepro là tên của module còn menu là tên của hook. Mỗi hook sẽ có những thông số đầu vào khác nhau và trả về các kết quả khác nhau.Tùy theo chức năng và mức độ phức tạp của module mà người thiết kế có thể sử dụng các hook thích hợp.VIẾT 1 MODULE CHO DRUPAL NHƯ THẾ NÀO?Cấu trúc của một module có thể gồm nhiều tập tin khác nhau, nhưng phải có ít nhất một tập tin tên_module.info và một tập tin tên_module.module, tên này không được trùng với các module đã tồn tại trong hệ thống.Tạo file *.info:Cấu trúc của một tập tin *.info có dạng:- Name = tên của module, bắt buộc phải có.- Description = mô tả các chức năng của module, bắt buộc phải có.- Version = phiên bản của module.- Package = nhóm các chức năng của module, nếu không khai báo package thì module được đưa vào nhóm “other”.- Dependencies = các module phụ thuộc, cách nhau bằng khoảng trống. Nếu module được yêu cầu chưa được bật trên hệ thống thì module này không thể bật được.Tạo file *.module:+ Bắt đầu với thẻ < ?php.+ Chúng ta có thể ghi chú thích cho nhiều dòng sau dấu ‘/*’ và kết thúc ghi chú dùng dấu ‘*/’, chú thích cho một dòng dùng dấu ‘//’.+ Viết mã: cài đặt các hook mà chúng ta cần xử lý (drupal có khá nhiều hook), ở đây mình lấy ví dụ đơn giản là cài đặt 1 internal path để khi request tới thì nó sẽ in ra một câu chào.Code: Chọn hết t(‘Title of TTP menu’), ‘path’ => ‘ttpmenu’, ‘callback’ => ‘ttpmenu_hello’, ‘access’ => TRUE ); } return $items; } function ttpmenu_hello() { return t(‘Hello CodePro!’); }VẬY INTERNAL PATH TRONG DRUPAL LÀ GÌ?+ Khi một web-browser tạo một request đến Drupal, nó đưa cho Drupal 1 URL, từ thông tin này Drupal “suy nghĩ” để chạy code và giải quyết request. Điều này được gọi là “dispatching”.+ Để làm điều này, drupal thực hiện như sau: yêu cầu các module cung cấp 1 mảng menu các item, đó là đường dẫn và các thông tin về đường dẫn.+ Trong ví dụ trên, hàm hook _menu thật sự sẽ được gọi 2 lần : một lần khi biến $may_cache được set là TRUE và một lần khi biến $may_cache được set là FALSE. Menu mà chúng ta tạo ra trong trường hợp là menu tĩnh. Nó không bào giờ thay đổi vì nó luôn là cachable. Toàn bộ cây menu chỉ được tạo 1 lần cho user, Drupal sẽ lưu cây này trong cache dưới dạng mảng trong bảng cache_menu, nếu bạn muốn tạo một menu động, ta sẽ xử lý nó trong trường hợp biến $may_cache = FALSE.+ NTERNAL PATH chính là những path được định nghĩa trong hook menu và nó gắn với 1 hàm callback, khi chúng ta request tới path này thì nó sẽ được chuyển tới cho hàm callback xử lý.

Client Side Load Balancing for Web 2.0 Applications

A web server handles HTTP (Hypertext Transfer Protocol) requests sent to it by web browsers. When you type in a URL —http://www.digital-web.com, for example—your computer sends out a request to look up the servers needed to handle requests and send responses back quickly. The technique for determining how to route requests to the cluster of web servers efficiently is called load balancing.

Load Balancing Web Applications

It is easier to make the client code and resources highly available and scalable than to do so for the servers—serving non-dynamic content requires fewer server resources.

Load balancing increases the reliability of a web site by routing requests to other servers in the cluster when one of the servers is too busy or fails. There are many techniques for achieving load balancing, but generally they should meet the following requirements:

  1. Distribute loads among a cluster of application servers.
  2. Handle failover of an application server gracefully.
  3. Ensure the cluster of servers appears as a single server to the end user.

A popular yet simple approach to balancing web requests is called round-robin DNS. This approach involves creating multiple DNS entries in the DNS record for the domain. For example, let’s say we want to balance the load on www.myloadbalancedwebsite.com, and we have two web servers with IP addresses of 64.13.192.120 and 64.13.192.121, respectively. To create a round-robin DNS to distribute requests, we simply create the following DNS entry:

www.myloadbalancedwebsite.com    64.13.192.120
www.myloadbalancedwebsite.com    64.13.192.121

As the end user’s web browser sends a request for the DNS record for www.myloadbalancedwebsite.com, the entry that is returned first will alternate. Since your browser uses the first entry returned, the requests are distributed evenly among our two servers. Unfortunately, the key drawback to round-robin DNS is that it fails the second requirement mentioned above—if one of the two servers fail, the DNS server will continue to send requests to it, and half of your end users will experience downtime.

Another popular load balancing technique involves handling requests with a single server or router dedicated to load balancing. Dedicated hardware equipment and software-based solutions such as F5 BIG-IP and Linux Virtual Server Project are examples of this type of solution. The dedicated load balancer takes requests and distributes them among a cluster of web servers. The load balancer detects if a server has failed, and routes requests to other servers. Also, to ensure that there is no single point of failure, a backup dedicated load balancer is available to take over in case the primary one fails.

The downsides to this approach are:

  1. There is a limit to the number of requests the load balancer itself can handle. However, this problem can be resolved with the combination of round-robin DNS and dedicated load balancers.
  2. There is an extra cost related to operating a dedicated load balancer, which can run into tens of thousands of dollars. The backup load balancer generally does nothing other than wait for the primary to fail.

Client Side Load Balancing

There is an approach to load balancing modern web applications that does not require any load-balancing hardware, and handles failure of servers more gracefully than round-robin DNS. Before delving into the details, let us consider a desktop application that needs to connect to servers on the internet to retrieve data. If our theoretical desktop application generates more requests to the remote server than it can handle using a single server, we will need a load balancing solution. Could we use the round-robin DNS and/or dedicated load balancer approach describe above? Of course, but there are other approaches that are more robust and less costly.

Instead of letting the client know of only one server domain from which to retrieve data, we can provide many servers—s1.myloadbalancedsite.com, s2.myloadbalancedsite.com, and so on. The desktop client randomly selects a server and attempts to retrieve data. If the server is not available, or does not respond in a preset time period, the client can select another server until the data is retrieved. Unlike web applications—which store the client code (JavaScript code or Flash SWF) on the same server that provides data and resource—the desktop client is independent of the server and able to load balance servers from the client side to achieve scalability for the application.

Sample of load balancing and scalability

So, can we apply the same technique to web applications? Before we can answer this question, we need to establish what makes up a web application.

Web applications have inherently blurred the boundary between the client component and the server component of a typical application. Web applications written in PHP may often have the server code entwined with the client code. Even if an MVC (model-view-controller) pattern framework is applied, and good practice is followed by separating code that generates the presentation layer (HTML) from code used for backend logic, it is still the server that is generating and serving the presentation. In addition, resources such as images are served by the server as well—but with new web technologies, the boundaries have shifted. Many applications today only make AJAX or Flash remoting calls—in fact, there is a lot of similarity in the ways a standard desktop application and web applications make remote calls.

For the purposes of client-side load balancing, there are three main components to a modern web application:

  1. Client-side code: JavaScript and/or SWF (for flash clients)
  2. Resources: images, CSS (Cascading Style Sheets), audio, video, and HTML documents
  3. Server-side code: backend logic that generates data requested by the client

It is easier to make the client code and resources highly available and scalable than to do so for the servers—serving non-dynamic content requires fewer server resources. In addition, it is possible to put the client code on a highly reliable distribution service such as Amazon Web Services’s S3 service. Once we have client code and resources served from a highly reliable location, let us take a look at how we can load balance server clusters.

Just like the desktop client above, we can embed our list of application servers into the client code. The web client contains a file called “servers.xml”, which has a list of available servers. The client tries to communicate (whether via AJAX or Flash) with every server in the list until it finds one that responds. Our client-side process is therefore:

  1. Load the file www.myloadbalancedwebsite.com/servers.xml, which is stored with the client code and other resources, and contains the list of available servers, e.g.:
    <servers>
      <server>s1.myloadbalancedwebsite.com</server>
      <server>s2.myloadbalancedwebsite.com</server>
      <server>s3.myloadbalancedwebsite.com</server>
      <server>s4.myloadbalancedwebsite.com</server>
    </servers>
  2. The client code randomly selects servers to call until one responds. All subsequent calls use that server.
  3. The client has a preset timeout for each call. If the call takes greater than the preset time, the client randomly selects another server until it finds one that responds, and uses that server for all subsequent calls.

Making Cross-Domain Calls

If you’ve been working with AJAX for any length of time, you’re probably thinking, “This won’t work, because of cross-domain browser security,” so let’s address that.

For security reasons, web browsers and Flash clients will block calls to a different domain—for example, if the client wants to talk to the server s1.myloadbalancedwebsite.com, the client code must be loaded from the same domain, s1.myloadbalancedwebsite.com. Requests from clients loaded from any other domain will be blocked. In order for the load-balancing scheme described above to work, the client code at www.myloadbalancedwebsite.com needs to be able to call services running on other sub-domains (such as s1.myloadbalancedwebsite.com).

For Flash clients, we can simply set the “crossdomain.xml” file to allow requests from *.myloadbalancedwebsite.com:

<cross-domain-policy>
  <allow-access-from domain="*.myloadbalancedwebsite.com"/>
</cross-domain-policy>

For AJAX-based client code, the restriction depends on the transport we use to make server calls. If we use theDynamic script Tag method to transport calls, there is no security issue, because we can make server calls without cross-domain security constraint issues. (However, it is generally a good idea to check the referrer header to make sure it is definitely your client that is making the server requests, for the sake of your site’s security.)

What if the application uses XMLHttpRequest? XHR strictly forbids client calls from a different domain to the server. Luckily, a workaround exists if the client and server have the same parent domain—as in our example, www.myloadbalancedwebsite.com and s1.myloadbalancedsite.com. We can make all AJAX calls to the server using an iframe loaded from the server; since browsers allow communication between scripts in an iframe, it is possible to access data received from the server calls made in the iframe if the scripts are loaded from the same parent domain. Problem solved.

Advantages of Client-Side Load Balancing

Now that we can make cross-domain calls, let us see how well our load-balancing technique meets the requirements outlined at the start of the article.

  1. Distribute loads among a cluster of application servers. Since the client randomly selects the server it connects to, the loads should be distributed evenly among the servers.
  2. Handle failover of an application server gracefully. The client has the ability to failover to another server when the chosen server does not respond within a preset period of time. The application server connection seamlessly fails over to another server.
  3. Ensure the cluster of servers appears to the end user as a single server. In the example, the user simply points a browser to http://www.myloadbalancedwebsite.com/. The actual server used is transparent to the user.

So what are the advantages of using client-side load balancing over server-side load balancing? The obvious advantage is that a special load-balancing device is unnecessary—there is no need to configure load-balancing hardware, or to make sure that the backup functions the same as the primary load balancer. If a server is unavailable, simply remove it from the “servers.xml” file.

Another advantage is that servers do not have to be housed in the same location; since the client is selecting servers instead of having a fixed load balancer redirecting traffic, the locations of the servers are unrestricted. Servers can be in multiple datacenters in case one datacenter is not accessible. If the application requires a database on the local network, the other datacenter can still be used as a backup in case your primary one is unavailable. Changing to another datacenter is as simple as making an update to the “servers.xml” file, instead of waiting for DNS changes to propagate.

Voxlite, a Client-Side Load Balanced Web Application

Voxlite, a web-2.0 application that lets users send video messages to one another with just a browser and a webcam, is an application that uses client-side load balancing to achieve high availability and scalability. In addition, Voxlite uses the Simple Storage Service (S3) and Elastic Computing Cloud (EC2) services fromAmazon Web Services.

From very early on, the S3 service presented an attractive option for storing and serving the video messages, and EC2 was naturally designed to work with the S3 service. It provides an easy and cost-effective way for Voxlite to scale to support more users. EC2 instances can be allocated at any time by simply starting a virtual machine image—each EC2 instance costs ten cents per hour, or seventy-two dollars per month. But what makes EC2 even more attractive is the computing resource is elastic; EC2 instances can be de-allocated when they are not being used. For example, if Voxlite gets more traffic during the day than in the evening, it is possible to only allocate more servers during the day, and thus, greatly increase the cost-effectiveness of the hosting solution. Unfortunately, one major drawback with EC2 is that it is not possible to architect a server-side load balancing solution that doesn’t have a single point of failure. Many web applications hosted on EC2 use a single EC2 instance with dynamic DNS to load-balance requests to a particular domain. If the instance that provides the load balancing fails, the whole system can become unavailable until the dynamic DNS maps the domain to another EC2 instance.

Using the client-side load balancing technique described above, it is possible to have a load-balanced solution with EC2 servers that has no single point of failure. To build a cluster of EC2 instances supporting client-side load balancing, Voxlite’s client code and other web resources is stored on, and served from, S3. An EC2 image with the server code is created so that whenever an EC2 instance starts, it is properly configured and ready to handle client requests. Voxlite then uses a clever technique to make the client aware of the available servers.

Earlier, I described the use of a “servers.xml” file to let the client know the list of available servers—but, with the S3 service available, there is a better way. When accessing an S3 bucket (a bucket is a term used by S3 for storing a group of files; the idea is similar to file folders) without any keys, the S3 service will simply list all the keys matching the given prefix—so, in each of Voxlite’s EC2 instances, a cron job is created that runs periodically and registers the server as a cluster member by writing an empty file with the key servers/{AWS IP address} to a publicly readable S3 bucket.

For example, if I go to the URL http://s3.amazonaws.com/voxlite/?prefix=servers, I get the following response:

<ListBucketResult>
  <Name>voxlite</Name>
  <Prefix>servers</Prefix>
  <Marker/>
  <MaxKeys>1000</MaxKeys>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>servers/216.255.255.1</Key>
    <LastModified>2007-07-18T02:01:25.000Z</LastModified>
    <ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
    <Size>0</Size>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
  <Contents>
    <Key>servers/216.255.255.2</Key>
    <LastModified>2007-07-20T16:32:22.000Z</LastModified>
    <ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
    <Size>0</Size>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
</ListBucketResult>

In this example, there are two EC2 instances in the cluster, with IP addresses of 216.255.255.1 and 216.255.255.2 respectively.

The logic for the cron job is:

  1. Load and parse http://s3.amazonaws.com/voxlite/?prefix=servers.
  2. If the current running instance is not listed, write an empty file to the bucket with the key servers/{IP address of EC2 instances}.
  3. Verify if other servers listed in the bucket are running properly by testing the connection using the internal AWS IP address. If a connection cannot be established, remove the server key from the bucket.

Once this cron job is a part of the EC2 image, each running instance is automatically registered as an available server in the cluster. The client code (AJAX or Flash) parses the list of keys in the bucket and extracts the external AWS host name, allowing it to then randomly select a server to connect to, as described above when using the “servers.xml” file. If an EC2 instance shuts down or happens to crash, the other instances in the cluster would automatically remove its key from the bucket—the bucket would be left with only available instances. In addition, the client can select another EC2 instance in the bucket if a request does not get a response in the preset time. If the web site is getting more traffic, simply start more EC2 instances. If the load decreases, simply shut down the extra instances. By using client-side load balancing with S3 and EC2, it is easy to build an elastic, scalable and robust web application.

Source : http://www.digital-web.com/articles/client_side_load_balancing/

Usually users upload their file to a server through a web form as shown below:file-uploadThe HTML form looks something like this:view plaincopy to clipboardprint? 1. 2. 3.

5. 6.
7.
8.
9.

10. 11.



Here uploader.php is a simple script that uploads the file to the temporary cache of PHP & then moves it to a pre-determined directory under the ROOT of website.view plaincopy to clipboardprint? 1. // Where the file is going to be placed 2. $target_path = ‘uploaded_files/’; 3. 4. /* Add the original filename to our target path. 5. Result is “uploaded_files/filename.extension” */ 6. $target_path = $target_path . basename( $_FILES['file']['name']); 7. 8. if(move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) { 9. echo “The file “. basename( $_FILES['file']['name']). 10. ” has been uploaded”; 11. } else{ 12. echo “There was an error uploading the file, please try again!”; 13. } // Where the file is going to be placed$target_path = ‘uploaded_files/’;/* Add the original filename to our target path.Result is “uploaded_files/filename.extension” */$target_path = $target_path . basename( $_FILES['file']['name']); if(move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) { echo “The file “. basename( $_FILES['file']['name']). ” has been uploaded”;} else{ echo “There was an error uploading the file, please try again!”;}This implementation suffers from a major security hole. “Uploader.php” allows users toUpload arbitrary files to the directory under the web root. A malicious user canUpload a PHP file, such as a PHP shell and execute arbitrary commands on the server with the privilege of the web server process. A PHP shell is a PHP script that allows a user to run arbitrary shell commands on the server.A simple PHP shell is shown below:view plaincopy to clipboardprint? 1. < ?php 2. system($_GET['command']); 3. ?> < ?php system($_GET['command']);?>Anybody can execute shell commands on the server by surfing to:view plaincopy to clipboardprint? 1. $ curl http://server/uploads/shell.php?command=any_unix_command $ curl http://server/uploads/shell.php?command=any_unix_commandA crude measure:A PHP snippet that checks for the MIME type in the uploaded request:view plaincopy to clipboardprint? 1. if($_FILES['userfile']['type'] != “image/gif”) { 2. echo “Sorry, we only allow uploading GIF images”; 3. exit; 4. } if($_FILES['userfile']['type'] != “image/gif”) { echo “Sorry, we only allow uploading GIF images”; exit;}This does not helps as a simple manipulation or request header can allow attacker to upload the shell PHP script by setting the Content-type header to, say images/gif if the allowed type is gif only.What can be done instead is that use PHP functions to check that the file type is indeed of desired type, for example: ‘getimagesize()’ function of PHP takes a file name as an argument and returns the size and type of the image.Even this doesn’t help as it’s possible to manipulate images to include PHP code in them with help of any image editor like GIMP. Keeping the extension as .PHP the file can be uploaded, it will also pass the ‘getimagesize()’ test as it is a valid image with comments & can also be executed by server as it has PHP code into it.File name extension verificationWe can make a black list of file extensions and check the file name specified by the user to make sure that it does not have any of the known-bad extensions. Or we can also maintain a white list of type of files that can be uploaded.Particular care has to be taken with regards to writable web directories if you are running PHP on Microsoft IIS. As opposed to Apache, Microsoft IIS supports “PUT” HTTP requests, which allow users to upload files directly, without using an upload PHP page. PUT requests can be used to upload a file to the web server if the file system permissions allow IIS (which is running as IUSR_MACHINENAME) to write to the directory and if IIS permissions for the directory allow writing. IIS permissions are set from the Internet Services Manager as shown in the screenshot below.iis file upload settingTo allow uploads using a PHP script you need to change file system permissions to make the directory writable. It is very important to make sure that IIS permissions do not allow writing. Otherwise users will be able to upload arbitrary files to the server using PUT requests, bypassing any checks you might have implemented in your PHP upload script.Other issuesThere are still a number of things to consider when implementing a file upload function.1. Denial of service. Users might be able to upload a lot of large files and consume all available disk space. This can be tackled to an extent with the HTML form itself by usingview plaincopy to clipboardprint? 1.
This would limit the file size that can be uploaded to size=’2000000′.2. Local File Inclusion Attack: In this situation a web app written in multiple languages usually includes a file from local file system on server, for example in PHP:view plaincopy to clipboardprint? 1. include(“language/$lang.php”); include(“language/$lang.php”);The attacker can make this kind of code to include any file on the file system with the “.php” extension. Though this has a limitation but if the attacker has uploaded a file & knows its location then it can be included here.Solution to this problem is to have reference implementation, i.e. to prevent attacker from knowing the file name on the system. This can be done by randomly generating file names and keeping track of them in a database.

Directory listing in htaccess

Directory listing in htaccess. Allow, Deny, Disable, Enable Directory Listing in .htaccessWhen a web browser is pointed to a directory on your web site which does not have an index.html file (or any other index file) in it, the files in that directory can be listed on a web page.Let us see few snippets that can be added in htaccess file to allow or avoid directory listing in apache server.Enable / Disable directory ListingTo allow a web server to produce a directory listing, whenever you point a directory without index file. Add following line in your .htaccess file.view plaincopy to clipboardprint? 1. Options +Indexes 2. # or # 3. IndexIgnore * Options +Indexes# or #IndexIgnore *allow-directory-listing-htaccessTo disable or prevent the directory access add following line in your .htaccess file. If user points the browsers to a directory which does not have index file then in this case 403 error will beview plaincopy to clipboardprint? 1. Options -Indexes Options -Indexes Following is the error page that gets displayed when we try to access any directory without index file.403-directory-listing-error-htaccessChange Listing styleYou may want to display other details while showing the directory listing. This includes file icons, file size, modification date and more. This can be done by adding fancy style to your htaccess file. Add following snippet in .htaccess file.view plaincopy to clipboardprint? 1. IndexOptions +FancyIndexing IndexOptions +FancyIndexingfancy-directory-listing-htaccessTo remove the fancy directory listing or to display normal directory listing, use -FancyIndex.view plaincopy to clipboardprint? 1. IndexOptions -FancyIndexing IndexOptions -FancyIndexingIgnore files with specific extensionIt may happen that you may need to ignore certain files to get displayed in directory listing. This can be achieved using IndexIgnore directive in .htaccess file.Following snippet will not display .zip and .txt file in directory listing.view plaincopy to clipboardprint? 1. IndexIgnore *.zip *.txt IndexIgnore *.zip *.txtModify Index FileIt is possible to change the default index file from index.html (index.php, index.jsp …) to any other file. Following line will change the index file to Home.html.view plaincopy to clipboardprint? 1. DirectoryIndex Home.html

Top 10 SQL Performance Tips

Specific Query Performance Tips (see also database design tips for tips on indexes):

  1. Use EXPLAIN to profile the query execution plan
  2. Use Slow Query Log (always have it on!)
  3. Don’t use DISTINCT when you have or could use GROUP BY
  4. Insert performance
    1. Batch INSERT and REPLACE
    2. Use LOAD DATA instead of INSERT
  5. LIMIT m,n may not be as fast as it sounds. Learn how to improve it (if possible): http://www.facebook.com/note.php?note_id=206034210932
  6. Don’t use ORDER BY RAND() if you have > ~2K records
  7. Use SQL_NO_CACHE when you are SELECTing frequently updated data or large sets of data
  8. Avoid wildcards at the start of LIKE queries
  9. Avoid correlated subqueries and in select and where clause (try to avoid in)
  10. No calculated comparisons — isolate indexed columns
  11. ORDER BY and LIMIT work best with equalities and covered indexes
  12. Separate text/blobs from metadata, don’t put text/blobs in results if you don’t need them
  13. Derived tables (subqueries in the FROM clause) can be useful for retrieving BLOBs without sorting them. (Self-join can speed up a query if 1st part finds the IDs and uses then to fetch the rest)
  14. ALTER TABLE…ORDER BY can take data sorted chronologically and re-order it by a different field — this can make queries on that field run faster (maybe this goes in indexing?)
  15. Know when to split a complex query and join smaller ones
  16. Delete small amounts at a time if you can
  17. Make similar queries consistent so cache is used
  18. Have good SQL query standards
  19. Don’t use deprecated features
  20. Turning OR on multiple index fields (<5.0) into UNION may speed things up (with LIMIT), after 5.0 the index_merge should pick stuff up.
  21. Don’t use COUNT * on Innodb tables for every search, do it a few times and/or summary tables, or if you need it for the total # of rows, use SQL_CALC_FOUND_ROWS and SELECT FOUND_ROWS()
  22. Use INSERT … ON DUPLICATE KEY update (INSERT IGNORE) to avoid having to SELECT
  23. use groupwise maximum instead of subqueries
  24. Avoid using IN(…) when selecting on indexed fields, It will kill the performance of SELECT query.

Scaling Performance Tips:

  1. Use benchmarking
  2. isolate workloads don’t let administrative work interfere with customer performance. (ie backups)
  3. Debugging sucks, testing rocks!
  4. As your data grows, indexing may change (cardinality and selectivity change). Structuring may want to change. Make your schema as modular as your code. Make your code able to scale. Plan and embrace change, and get developers to do the same.

Network Performance Tips:

  1. Minimize traffic by fetching only what you need.
    1. Paging/chunked data retrieval to limit
    2. Don’t use SELECT *
    3. Be wary of lots of small quick queries if a longer query can be more efficient
  2. Use multi_query if appropriate to reduce round-trips
  3. Use stored procedures to avoid bandwidth wastage

OS Performance Tips:

  1. Use proper data partitions
    1. For Cluster. Start thinking about Cluster *before* you need them
  2. Keep the database host as clean as possible. Do you really need a windowing system on that server?
  3. Utilize the strengths of the OS
  4. pare down cron scripts
  5. create a test environment
  6. source control schema and config files
  7. for LVM innodb backups, restore to a different instance of MySQL so Innodb can roll forward
  8. partition appropriately
  9. partition your database when you have real data — do not assume you know your dataset until you have real data

MySQL Server Overall Tips:

  1. innodb_flush_commit=0 can help slave lag
  2. Optimize for data types, use consistent data types. Use PROCEDURE ANALYSE() to help determine the smallest data type for your needs.
  3. use optimistic locking, not pessimistic locking. try to use shared lock, not exclusive lock. share mode vs. FOR UPDATE
  4. if you can, compress text/blobs
  5. compress static data
  6. don’t back up static data as often
  7. enable and increase the query and buffer caches if appropriate
  8. config params – http://docs.cellblue.nl/2007/03/17/easy-mysql-performance-tweaks/ is a good reference
  9. Config variables & tips:
    1. use one of the supplied config files
    2. key_buffer, unix cache (leave some RAM free), per-connection variables, innodb memory variables
    3. be aware of global vs. per-connection variables
    4. check SHOW STATUS and SHOW VARIABLES (GLOBAL|SESSION in 5.0 and up)
    5. be aware of swapping esp. with Linux, “swappiness” (bypass OS filecache for innodb data files, innodb_flush_method=O_DIRECT if possible (this is also OS specific))
    6. defragment tables, rebuild indexes, do table maintenance
    7. If you use innodb_flush_txn_commit=1, use a battery-backed hardware cache write controller
    8. more RAM is good so faster disk speed
    9. use 64-bit architectures
  10. –skip-name-resolve
  11. increase myisam_sort_buffer_size to optimize large inserts (this is a per-connection variable)
  12. look up memory tuning parameter for on-insert caching
  13. increase temp table size in a data warehousing environment (default is 32Mb) so it doesn’t write to disk (also constrained by max_heap_table_size, default 16Mb)
  14. Run in SQL_MODE=STRICT to help identify warnings
  15. /tmp dir on battery-backed write cache
  16. consider battery-backed RAM for innodb logfiles
  17. use –safe-updates for client
  18. Redundant data is redundant

Storage Engine Performance Tips:

  1. InnoDB ALWAYS keeps the primary key as part of each index, so do not make the primary key very large
  2. Utilize different storage engines on master/slave ie, if you need fulltext indexing on a table.
  3. BLACKHOLE engine and replication is much faster than FEDERATED tables for things like logs.
  4. Know your storage engines and what performs best for your needs, know that different ones exist.
    1. ie, use MERGE tables ARCHIVE tables for logs
    2. Archive old data — don’t be a pack-rat! 2 common engines for this are ARCHIVE tables and MERGE tables
  5. use row-level instead of table-level locking for OLTP workloads
  6. try out a few schemas and storage engines in your test environment before picking one.

Database Design Performance Tips:

  1. Design sane query schemas. don’t be afraid of table joins, often they are faster than denormalization
  2. Don’t use boolean flags
  3. Use Indexes
  4. Don’t Index Everything
  5. Do not duplicate indexes
  6. Do not use large columns in indexes if the ratio of SELECTs:INSERTs is low.
  7. be careful of redundant columns in an index or across indexes
  8. Use a clever key and ORDER BY instead of MAX
  9. Normalize first, and denormalize where appropriate.
  10. Databases are not spreadsheets, even though Access really really looks like one. Then again, Access isn’t a real database
  11. use INET_ATON and INET_NTOA for IP addresses, not char or varchar
  12. make it a habit to REVERSE() email addresses, so you can easily search domains (this will help avoid wildcards at the start of LIKE queries if you want to find everyone whose e-mail is in a certain domain)
  13. A NULL data type can take more room to store than NOT NULL
  14. Choose appropriate character sets & collations — UTF16 will store each character in 2 bytes, whether it needs it or not, latin1 is faster than UTF8.
  15. Use Triggers wisely
  16. use min_rows and max_rows to specify approximate data size so space can be pre-allocated and reference points can be calculated.
  17. Use HASH indexing for indexing across columns with similar data prefixes
  18. Use myisam_pack_keys for int data
  19. be able to change your schema without ruining functionality of your code
  20. segregate tables/databases that benefit from different configuration variables

Other:

  1. Hire a MySQL ™ Certified DBA
  2. Know that there are many consulting companies out there that can help, as well as MySQL’s Professional Services.
  3. Read and post to MySQL Planet at http://www.planetmysql.org
  4. Attend the yearly MySQL Conference and Expo or other conferences with MySQL tracks (link to the conference here)
  5. Support your local User Group (link to forge page w/user groups here)

Source : http://forge.mysql.com/wiki/Top10SQLPerformanceTips

Easy MySQL Performance Tweaks

This article is meant to be an easy and relatively safe way to enhance mysql performance. It is not meant to be a complete guide to tuning MySQL. Fully optimizing MySQL takes both time and effort since every application has different requirements. The Debian MySQL packages ship with very conservative memory usage settings and the same is probably true for other Linux distributions and the Windows binaries. If you loosen these settings up a little, MySQL will perform much faster under ordinary circumstances.

The items are ordered on impact, high to low. Feedback and hints will be greatly appreciated.

Key Buffer
The key buffer holds the indexes of tables in memory and a bigger key buffer results in faster row lookups. Adjust according to your own needs. Bigger is better, but prevent swapping at all costs. A good rule of thumb seems to be to use 1/4 of system memory.

key_buffer = 128M

Query Cache
This is where the magic happens. Well, not magic really, just plain old caching. Keeping the result of queries in memory until they are invalidated by additional writes enhances performance by magnitudes. The query_cache_size, as the name suggests, is the total size of memory available to query caching. The value query_cache_limit is the maximum number of kilobytes one query may be in order to be cached. Setting this value too high might prevent a lot of smaller queries to be cached. Setting it too low will result in bigger queries to never be cached, and the smaller queries not being able to completely fill the cache size, which would be a waste of resources. Adjust according to your own needs and memory available:

query_cache_size = 128MB
query_cache_limit = 4MB

Table Cache
An important variable if your application accesses many tables. It is the number of tables a thread can keep open at the same time. A value of 512 should do no harm.

table_cache = 512

Sort Buffers
sort_buffer_size (the variable previously known as sort_buffer), used for grouping and sorting and is a per-thread buffer. If the buffer can not hold the data to be sorted, a sort is performed on disk. Watch out for making this too large as the buffer is allocated for every thread that needs sorting and with many sorts it can easily consume all your memory.

sort_buffer_size = 32M
myisam_sort_buffer_size = 32M

The InnoDB Engine
Most people do not use the InnoDB engine in MySQL and use MyISAM instead. Since MySQL reserves memory for this engine, you are better off without it. If you need InnoDB, you can find more on its settings in the official MySQL docs.

Add `skip-innodb’ to my.cnf to disable the engine.

Binary Logging
MySQL has a few powerful features. Replicating data changes to a second server is one of them. MySQL keeps a log file of data changes which is used for this purpose. If you do not use replication or use the file as incremental backup, you can disable it. This will save you expensive disk write actions for every change to your data. For applications that have a lot of frequently updated data, this can be quite a performance boost. According to the official docs, this will generally result in just a 1% boost but it’s an easy gain if you do not need the log. Read more about the binary log here. Comment the following line:

log-bin = /var/log/mysql/mysql-bin.log

Temporary Tables
Temporary tables are used for sorting and grouping. The buffer is created on demand so watch out for setting this too high here as well. If the buffer cannot accomodate the data, a temp file is used on disk instead.

tmp_table_size = 64MB

Delayed Writing
This setting can greatly improve writing or updating data to a table. Instead of directly committing data to the disk, MySQL queues writes and returns write queries immediately. Be very very careful with this, because this also means that in case of a power failure or crash, you lose data. You can use this for logging if you don’t mind losing a couple of rows in case of a crash.

delay_key_write = 1

Connection Timeout
This is a little tweak that determines the closing of sleeping connections. The default is one hour and is often too long for practical purposes. I often set this at one minute instead (60).

wait_timeout = 60

The above settings are just to make mysql a little faster in general. You can get much better speed improvements by optimizing the database itself. Setting the correct indexes on tables can be a life-saver.

After 3 months of tweaking here is how I optimized to pull off these numbers with only a single dual Xeon 3.2ghz server with 4GB of memory. This is a very simplified guide and I am very far from being an expert – so this only reflects my personal success with this configuration. At the bottom of the article is a script I use to test performance.

Mysql provides a configuration file located in /etc/my.cnf. From here you can set all of the memory, table, and connection limits as well as a host of other options. Before we get started I suggest you get aquainted with the my.cnf file as well as the tuning parameters within it.

Here is the my.cnf I use:

Trích dẫn:
[mysqld]
back_log = 75
skip-innodb
max_connections = 500
key_buffer = 384M
myisam_sort_buffer_size = 64M
join_buffer_size = 1M
read_buffer_size = 1M
sort_buffer_size = 2M
table_cache = 1800
thread_cache_size = 384
wait_timeout = 7200
connect_timeout = 10
tmp_table_size = 64M
max_heap_table_size = 64M
max_allowed_packet = 64M
max_connect_errors = 1000
read_rnd_buffer_size = 524288
bulk_insert_buffer_size = 8M
query_cache_limit = 4M
query_cache_size =128M
query_cache_type = 1
query_prealloc_size = 65536
query_alloc_block_size = 131072
default-storage-engine = MyISAM

[mysqld_safe]
nice = -5
open_files_limit = 8192

[mysqldump]
quick
max_allowed_packet = 16M

[myisamchk]
key_buffer = 64M
sort_buffer = 64M
read_buffer = 16M
write_buffer = 16M

Let’s just look at the important bits.

max_connections = 500 – I use a tool (see below) to check how many current connections I have, and under very heavy load (2000 simultaneous users) I rarely hit 400 concurrent connections to the database. This is because most connections only last for a few milliseconds.

key_buffer = 384M – When tuning a MySQL server, key_buffer_size is very important. This number works well for me and with the mysqlreport script I rarely use 50% of the available memory.

table_cache = 1800 – After key_buffer the next most important variable is your table cache. Again this is set for vBulletin so you may be able to significantly reduce this value depending on the number of tables in your database.

wait_timeout = 7200 – This variable determines the timeout in seconds before mysql will dump a connection. If set to low you will likely receive mySQL server has gone away errors in your log, which in vBulletin’s case is quite common.

max_allowed_packet = 16M – Again if set to low (the default is 8M) users will likely experience errors. 16M has always worked fine for my production environments.

You can grab a mySQL performance script from the guys at hackmysql.com.
http://hackmysql.com/mysqlreport
I use it to tell me how the database is performing under load. You can run this from any shell when you are loaded with traffic. Nothing fancy but should give you an idea.

If you run into problems mtop is a great tool for monitoring a live mySQL server. In particular mtop: http://mtop.sourceforge.net/
will show you the queries which are taking the most amount of time to complete. Thanks to konforce on digg for pointing that out.

Don’t forget mySQL’s own lengthy and dull performance tuning whitepaper.

How to find slow mysql queries

It has happened to all of us running a website or application using mysql as its back-end database. Performance is suddenly very sluggish and you have no idea what is causing it. Now there may be other factors that are causing the issue (overloaded CPU, harddrive running out of space, or a lack of bandwidth), but it could also be a query that is not optimized and/or is taking much longer than it should to return.

How do you know which queries are taking the longest to execute? Mysql has built-in functionality for checking this through the slow query log.

To enable (do one of the following):

1) add this to /etc/my.cnf

log-slow-queries=/tmp/slow_queries.log
long_query_time=10

2) call mysqld with –log-slow-queries[=/tmp/slow_queries.log]

long_query_time is the maximum amount of seconds a query can take before it will be logged to the slow query log.

other related options:

–log-slow-admin-statements

Log slow administrative statements such as OPTIMIZE TABLE, ANALYZE TABLE, and ALTER TABLE to the slow query log.

–log-queries-not-using-indexes

If you are using this option with –log-slow-queries, queries that do not use indexes are logged to the slow query log.

mysql info How to find slow mysql queries

If slow query logging has been enabled successfully, you will see “ON” in the VALUE field for “log_slow_queries” (shown above).

Note: Queries handled by the query cache are not added to the slow query log, nor are queries that would not benefit from the presence of an index because the table has zero rows or one row.

You may also run into the case where a query is slow at one time (such as when you are logging it) but not another (if you execute it manually):

  • A table may be locked, causing the query to wait. the lock_time indicates how long the query waited for locks to be released
  • none of the data or indexes have been cached in memory. This is common when MySQL first starts or your tables have not been optimizied
  • a background process was running, making disk I/O considerably slower
  • The server may have been overloaded with other unrelated queries at the same time, and there wasn’t enough CPU power to do the job efficiently

Log analysis

MySQL also comes with mysqldumpslow, a perl script that can summarize the slow query log and provide a better idea of how often each slow query executes.

Source : http://www.rawseo.com/news/2009/03/25/how-to-find-slow-mysql-queries/

Powered by WordPress | Theme: by 85ideas. Editor by Khoanguyen