2011年5月12日 星期四

XMLHttpRequest 的應用:灌垃圾資料給釣魚網站

今天有一個許久未聯絡的同學忽然間丟 MSN 水球給我,第一時間的直覺就是詐騙,要買遊戲儲值卡的。果不其然,聊不到兩句就開始問我有沒有空,可不可以幫他買卡等等,我用幾個爛藉口推掉之後,他留下一個超連結就離線了。

點擊超連結,果然出現一個很像 Windows Live 登入的網頁,做得十分粗糙,連 Title 都沒有改,還是 “Untitled Document”,唉~~要騙人帳號也搞像一點嘛!於是我就拿出了我之前寫的小程式,一個 html 檔案,填入了一些資料,開始向那個釣魚網站灌垃圾資料。

這隻程式很簡單,就是使用 XMLHttpRequest 對釣魚網站 POST 假資料,假資料當然是使用亂數產生,主要的部份是這樣子的:

// 產生一個 XMLHttpRequest 物件
function initRequest()
{
    var A = null;
    try
    {
        A = new ActiveXObject("Msxml2.XMLHTTP")
    } 
    catch(e) 
    {
        try
        {
            A = new ActiveXObject("Microsoft.XMLHTTP")
        } 
        catch(oc) 
        {
            A = null
        }
    }
    if (!A && typeof XMLHttpRequest != "undefined")
    {
        A = new XMLHttpRequest()
    }
    if (!A && window.createRequest) 
    {
        try 
        {
            A = window.createRequest();
        } 
        catch (e) 
        {
            A = null;
        }
    } 
    return A
}
// 取亂數帳號密碼,塞入釣魚網頁
function DoBurst()
{
    try
    {
        // 宣告變數
        username = "";
        password = "";
        // 取得輸入資料
        actionUrl = document.getElementById("actionUrl").value;
        usernameId = document.getElementById("usernameId").value;
        passwordId = document.getElementById("passwordId").value; 
        
        // 取亂數拼湊假的帳號跟密碼
        c = Math.floor(Math.random() * 8) + 5;
        for (n=0; n < c; n++)
        {
            username += charSet.charAt(Math.floor(Math.random() * charSet.length));
        }
        username += document.getElementById("usernameSuffix").value;
        
        c = Math.floor(Math.random() * 8) + 5;
        for (n=0; n < c; n++)
        {
            password += charSet.charAt(Math.floor(Math.random() * charSet.length));
        } 

        // submit
        url = actionUrl + "?" + usernameId + "=" + username + "&" + passwordId + "=" + password;

        if (typeof XmlHttp == "undefined")
        {
            XmlHttp = initRequest();
        }

        XmlHttp.open("POST", url, true);
        XmlHttp.onreadystatechange = ShowResult;
        XmlHttp.send("");

        // 計數器累加,並更新畫面
        i++;
        document.getElementById("sendTimes").innerText = i;
    }
    catch(e)
    {
        // 可做錯誤處理
    }
}

然後使用 interval 定時重複執行,就這樣簡單!

2011年3月9日 星期三

Ultra VNC 的最佳選項

1. 要搭配 Video Hook Driver
2. 「Check the Cideo Hook Driver」按鈕要連線時按才有意義image

2011年1月30日 星期日

Ubuntu Server 10.10 安裝 ASP.Net 網站伺服器的步驟

一、安裝 mono 以及 xsp

sudo apt-get install mono-gmcs
sudo apt-get install mono-xsp2
sudo apt-get install mono-apache-server2
sudo apt-get install libapache2-mod-mono
sudo a2enmod mod_mono

二、修改 /etc/apache2/mods-enabled/mod_mono.conf
成為以下這樣:
===== 從這裡開始 =====
AddType application/x-asp-net .aspx .ashx .asmx .ascx .asax .config .axd

DirectoryIndex index.aspx
DirectoryIndex Default.aspx
DirectoryIndex default.aspx

MonoAutoApplication enabled
MonoServerPath "/usr/bin/mod-mono-server2"

Include /etc/mono-server2/mono-server2-hosts.conf
===== 到這裡結束 =====

三、重新啟動 apache2
sudo /etc/init.d/apache2 restart

若要讓 Visual Studio 跟 MonoDevelop 共用網站專案的話
要使用「ASP.Net 應用程式」開發,不可以使用「ASP.Net 網站」開發
這樣平常就可以使用 Visual Studio 開發,要部署到 Ubuntu Server 時,再用 MonoDevelop 編譯一次就好

2010年11月7日 星期日

ASP.Net GridView 的自訂資料繫結

在論壇上,常常看到有網友提出這樣的問題:如果資料值是 Y/N,要顯示 是/否 在 GridView 上,要如何做?
這個問題有幾種解法

第一種:使用 GridView.RowDataBound 事件,搭配 TemplateField

這種方法是大部分的書上會介紹的方法

RowDataBound 事件,會傳入一個型別為 GridViewRowEventArgs 的參數 e
e.Row 指的是 GridView 剛剛做完資料繫結的列
e.Row.DataItem 指的是用來做這個列的資料繫結的資料來源,型別是 object
如果以 DataTable 或是 DataSet 做資料來源,e.Row.DataItem 實際上是一個 DataRowView
所以,如果以 DataTable 或是 DataSet 做資料來源,(e.Row.DataItem as DataRowView).Row["欄位名稱"] 可以取得欄位的資料值

接下來,就是「數格子」,要知道你的 TemplateField 是第幾欄,還要知道要做自訂資料繫結的控制項是 ItemTemplate 的第幾個控制項


(e.Row.Cells[欄索引].Controls[控制項索引] as 控制項型別).Text =
  (e.Row.DataItem as DataRowView).Row["欄位名稱"].ToString()

或是要知道自訂資料繫結的控制項的 ID

(e.Row.Cells[欄索引].FindControl("控制項ID") as 控制項型別).Text =
  (e.Row.DataItem as DataRowView).Row["欄位名稱"].ToString()

這種方法的缺點是
  1. 如果在這個TemplateField 之前,加入或是刪掉了其他欄,或是修改了 TemplateField 的 ItemTemplate,事件處理都得修改
  2. 如果不是以 DataTable 或是 DataSet 做資料來源,e.Row.DataItem 事實上是什麼型別?

不確定因素太多,既麻煩又複雜!強烈不建議使用這個方法

第二種:使用單純自訂資料繫結,搭配 TemplateField
這種方法直接在 TemplateField 的 ItemTemplate 中放置一個 Label,並設置 Text 屬性的資料繫結為

Text='<%# Eval("欄位名稱").ToString() == "Y" ? "是" : (Eval("欄位名稱").ToString() == "N" ? "否" : "") %>'
Text='<%# Eval("欄位名稱", "{0}") == "Y" ? "是" : (Eval("欄位名稱", "{0}") == "N" ? "否" : "") %>'

簡單明瞭,只是判斷是寫在 .aspx 裡面,而且當資料值是 DbNull 的時候會發生錯誤,如果還要加上判斷是否為 DbNull 的語法就更複雜了
因此,此方法建議使用於簡單判斷以及資料欄位不允許 null 的狀況
PS: Eval("欄位名稱") 與 Eval("欄位名稱", "{0}") 的不同點在於前者回傳的是 Object,後者回傳的是 String

第三種:使用自訂資料繫結方法,搭配 TemplateField
跟第二種方法類似,只是將 Label 的 Text 屬性的資料繫結改為呼叫一個自訂方法 (必須為 public 或 protected 方法)

Text='<%# YesOrNo(Eval("欄位名稱")) %>'

並撰寫後端程式碼如下:
protected string YesOrNo(object o)
{
  string s = o == DbNull.Value ? "" : Convert.ToString(o);
  return s == "Y" ? "是" : (s == "N" ? "否" : "");
}
這樣的好處是

  1. 不用數格子
  2. 沒有複雜的資料繫結語法
  3. 無論從何種資料來源做資料繫結,都可以適用
  4. 可檢查資料是否為 DbNull
提供給大家做參考

2010年11月3日 星期三

Delphi 5 使 DBGrid 支援滑鼠滾輪的程式碼

Delphi 5 的 TDBGrid 無法支援滑鼠滾輪移動資掉指標,而且當有 PickList 的 Column 或是 Lookup Field 下拉時
滾動滑鼠滾輪會有很奇怪的行為。
要解決這個問題,可以繼承 TDBGrid 寫一個新的 DBGrid 類別,並覆寫兩個方法:

interface
type
  TNewDBGrid = class(TDBGrid)
  protected
    function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
    function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;    
  end;

implementation
  function TNewDBGrid.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean;
  begin
    Result := False;
    if Assigned(OnMouseWheelDown) then
      OnMouseWheelDown(Self, Shift, MousePos, Result);
    if (not Result) and (DataLink <> nil) and (DataLink.Active)
       and (DataLink.DataSet <> nil) and (DataLink.DataSet.Active) then
    begin
      DataLink.DataSet.MoveBy(1);
      Result := True;
    end;
  end;

  function TNewDBGrid.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean;
  begin
    Result := False;
    if Assigned(OnMouseWheelDown) then
      OnMouseWheelDown(Self, Shift, MousePos, Result);
    if (not Result) and (DataLink <> nil) and (DataLink.Active)
       and (DataLink.DataSet <> nil) and (DataLink.DataSet.Active) then
    begin
      DataLink.DataSet.MoveBy(-1);
      Result := True;
    end;
  end;

2010年9月8日 星期三

多螢幕環境下,指定螢幕顯示畫面 (C#)

private void ChangeScreen(Form aForm, int screenId)  
{   
  // 先將 Form 設定為 Normal   
  aForm.WindowState = FormWindowState.Normal;   
  
  // 改 Location   
  aForm.StartPosition = FormStartPosition.Manual;   
  if (screenId < Screen.AllScreens.Length)   
  {   
    aForm.Location = Screen.AllScreens[screenId].WorkingArea.Location;   
  }   
  
  // 最後設定成 Maximized   
  aForm.WindowState = FormWindowState.Maximized;   
}

2010年9月2日 星期四

多螢幕環境下,指定螢幕顯示畫面 (Delphi 5)

這個 Procedure 是從 Delphi 2009 的 Forms.pas 中挖出來的,在多螢幕環境之下可以將 Form 顯示在指定的螢幕上,對於要開發多螢幕應用程式的人有一些用處。
procedure MakeFullyVisible(AForm: TForm; AMonitor: TMonitor);   
var   
  ALeft: Integer;   
  ATop: Integer;   
begin   
  if AMonitor = nil then   
    AMonitor := AForm.Monitor;   
  ALeft := AForm.Left;   
  ATop := AForm.Top;   
  if AForm.Left + AForm.Width > AMonitor.Left + AMonitor.Width then   
    ALeft := AMonitor.Left + AMonitor.Width - AForm.Width;   
  if AForm.Left < AMonitor.Left then   
    ALeft := AMonitor.Left;   
  if AForm.Top + AForm.Height > AMonitor.Top + AMonitor.Height then   
    ATop := AMonitor.Top + AMonitor.Height - AForm.Height;   
  if AForm.Top < AMonitor.Top then   
    ATop := AMonitor.Top;   
  AForm.SetBounds(ALeft, ATop, AForm.Width, AForm.Height);   
end;
呼叫方法是:
MakeFullyVisible(Form1, Screen.Monitors[0]);    // 將 Form1 顯示在第一個螢幕   
MakeFullyVisible(Form2, Screen.Monitors[1]);    // 將 Form2 顯示在第二個螢幕