Klinik Mr. Delphi

Telah dimuat di majalah Mikrodata.

Daftar Isi
Keamanan Aplikasi
Membuat Map Network Drive
Mengetahui UNC Suatu File
Mewarnai DBGrid
Menduplikatkan Form Saat Runtime
Apakah Hash itu ??
Membuat GUID Saat Runtime
Mengetahui Uptime Windows
Baris Kosong dalam TMemo
Scroll ke Akhir TMemo/TRichEdit
Memaksa TDateTimePicker untuk Drop-down Otomatis
Version Control dalam Delphi


Keamanan Aplikasi
Tanya:
Saya sedang bingung nih.. Saya ditugaskan atasan saya untuk membuat aplikasi yang mempunyai batasan keamanan yang lebih baik, yaitu dengan cara membatasi workstation yang bisa menjalankan aplikasi ini dan juga membatasi user untuk menggunakan workstation tertentu. Namun, ada beberapa user (diantaranya technical support) yang bisa login ke semua workstation yang telah diberi kewenangan. Bagaimana cara membuatnya ?? Tolong dibantu yah, thanks lho..

Jawab:
Ok, yang penting jangan bingung dulu, mari kita teliti lebih seksama lagi. Dalam kasus Anda berarti ada dua macam pembatasan, secara aplikasi dan secara masing-masing user. Pembatasan bisa diberikan dengan nama komputer, alamat IP, MAC Address, dll. Dalam contoh berikut, kita gunakan alamat IP dan nama komputer, tergantung yang telah didefinisikan, bisa salah satu, bisa kedua-duanya. Namun perlu diingat bahwa workstation harus dikonfigurasikan agar user tidak berhak untuk merubah alamat IP maupun nama komputer, juga diasumsikan tidak menggunakan DHCP.

Dalam aplikasi ini, kita membutuhkan tiga tabel, yaitu:

  • Tabel UserList, berisi UserID dan UserPass
  • Tabel AppSec, berisi IP dan PcName
  • Tabel UserSec, berisi UserID, IP, dan PcName

    Inti logika dari pemrograman ini adalah:

    1. Periksa apakah kombinasi UserID dan Password sesuai dengan tabel UserList
    2. Bila iya, periksa apakah dalam tabel AppSec ada record untuk salah satu alamat IP atau nama komputer, atau kombinasi keduanya
    3. Bila iya, periksa apakah dalam tabel UserSec ada record UserID digabung dengan alamat IP, atau digabung dengan nama komputer, atau digabung dengan keduanya
    4. Bila iya, maka user diperbolehkan meneruskan proses

    Lalu pemrogramannya adalah sebagai berikut:

    procedure TfrmAppSec.btnLoginClick(Sender: TObject);
    var
      cUserID, cUserPass, cIP, cPcName: String;
    begin
      cUserID   := Trim( edtUserID.Text );
      cUserPass := Trim( edtPassword.Text );
      if chkUser( cUserID, cUserPass ) then begin
        cIP     := getComputerIP();
        cPcName := getComputerName();
        if chkAppSec( cIP, cPcName ) and chkAppUser( cUserID, cIP, cPcName ) then begin
          ShowMessage( 'Login Ok!' );
          // Lanjutkan proses
        end else
          ShowMessage( 'User tidak diperkenankan login di workstation ini!' );
      end else
        ShowMessage( 'Kombinasi UserID dan Password salah!' );
    end;
    
    
    function TfrmAppSec.ChkUser( cUserID, cPassword: String ): Boolean;
    begin
      Result := tblUser.Locate( 'UserID;UserPass', VarArrayOf( [ cUserID, cPassword ] ), [] );
    end;
    
    
    function TfrmAppSec.chkAppSec( cIP, cPcName: String ): Boolean;
    begin
      Result := ( tblAppSec.Locate( 'IP;PcName', VarArrayOf( [ cIP, cPcName ] ), [] ) ) or
        ( tblAppSec.Locate( 'IP', cIP, [] ) ) or
        ( tblAppSec.Locate( 'PcName', cPcName, [] ) );
    end;
    
    
    function TfrmAppSec.chkAppUser( cUserID, cIP, cPcName: String ): Boolean;
    begin
      Result := ( tblUserSec.Locate( 'UserID;IP;PcName', VarArrayOf( [ cUserID, cIP, cPcName ] ), [] ) ) or
        ( tblUserSec.Locate( 'UserID;IP', VarArrayOf( [ cUserID, cIP ] ), [] ) ) or
        ( tblUserSec.Locate( 'UserID;PcName', VarArrayOf( [ cUserID, cPcName ] ), [] ) );
    end;
    
    
    function TfrmAppSec.GetComputerName: String;
    var
      wsaData: TWSAData;
      cHostName: String;
    begin
      WSAStartup( 257, wsaData );
      cHostName := GetHostByName( NIL )^.h_name;
      WSACleanup;
      Result := cHostName;
    end;
    
    
    function TfrmAppSec.GetComputerIP: String;
    var
      wsaData: TWSAData;
      cIP: String;
    begin
      WSAStartup( 257, wsaData );
      cIP := iNet_ntoa( PInAddr( GetHostByName( NIL )^.h_addr_list^ )^ );
      WSACleanup;
      Result := cIP;
    end;
    
    end.
    

    Go Top


    Membuat Map Network Drive
    Tanya:
    Aplikasi saya masih mengakses data berupa file DBF, namun saya ingin membuatnya lebih aman dengan cara membuat share network untuk folder tersebut, dan aplikasi sayalah yang bertanggungjawab untuk melakukan mapping network drive ke share tadi. Bilamana aplikasi sudah selesai, maka aplikasi ini secara otomatis menghapus mapping network drive tersebut, sehingga user tidak akan pernah tahu ada share network yang berisi data DBF yang penting tersebut. Bisakah hal ini dilakukan ?? Bila bisa, tolong dong cara pemrogramannya dijabarkan dengan detil. Terima kasih atas sarannya.

    Jawab:
    Kita dapat menggunakan fungsi WNetAddConnection2 untuk membuat koneksi ke shared folder dan fungsi WNetCancelConnection2 untuk memutuskan koneksi.

    Berikut ini ada contoh yang telah disederhanakan, Anda cukup membuat suatu form dan 2 button seperti berikut:

    procedure TfrmNetworkMap.btnConnectClick(Sender: TObject);
    begin
      if NetUse( Trim( edtDrive.Text ), Trim( edtUNC.Text ), Trim( edtPassword.Text ) ) then
        modeConnect( False )
      else
        ShowMessage( 'Error: Tidak bisa melakukan map network drive !' );
    end;
    
    
    procedure TfrmNetworkMap.btnDisconnectClick(Sender: TObject);
    begin
      if NetDel( Trim( edtDrive.Text ) ) then
        modeConnect( True )
      else
        ShowMessage( 'Error: Tidak bisa menghapus map network drive !' );
    end;
    
    
    function TfrmNetworkMap.NetUse( cDrive, cUNC, cPassword: String): Boolean;
    var
      nr: TNetResource;
    begin
      if cDrive = '' then
        nr.lpLocalName := nil
      else
        nr.lpLocalName := PChar( cDrive );
      nr.dwType        := RESOURCETYPE_DISK;
      nr.lpRemoteName  := PChar( cUNC );
      nr.lpProvider    := nil;
      Result           := WNetAddConnection2( nr, PChar( cPassword ), nil, 0 ) = NO_ERROR;
    end;
    
    
    function TfrmNetworkMap.NetDel( cDrive: String ): Boolean;
    begin
      Result := WNetCancelConnection2( PChar( cDrive ), 0, False ) = NO_ERROR;
    end;
    
    end.
    

    Go Top


    Mengetahui UNC Suatu File
    Tanya:
    Bagaimana caranya untuk mengetahui UNC dari suatu file yang tersimpan di network drive, misalnya F:\User\Hian\mrdelphi.doc ??

    Jawab:
    Anda dapat menggunakan fungsi ExpandUNCFileName, yang akan menghasilkan pengalamatan UNC yang lengkap, misalnya \\192.168.0.1\IT\User\Hian\mrdelphi.doc, silakan lihat pada contoh berikut:

    procedure TfrmUncPath.btnFindOutClick(Sender: TObject);
    begin
      edtUnc.Text := ExpandUNCFileName( edtFileName.Text );
    end;
    

    Go Top


    Mewarnai DBGrid
    Tanya:
    Dalam DBGrid, saya ingin memudahkan user dalam membedakan data secara visual, yaitu dengan cara memberikan warna yang berbeda berdasarkan kondisi tertentu. Event apakah yang harus saya gunakan dan bagaimana cara mengubah warna maupun font ??

    Jawab:
    Anda dapat menggunakan event DrawColumnCell, dimana Anda definisikan warna maupun font dengan mengubah property Canvas dari DBGrid seperti pada contoh berikut ini:

    procedure TfrmColorDbGrid.grdColorDrawColumnCell(Sender: TObject;
      const Rect: TRect; DataCol: Integer; Column: TColumn;
      State: TGridDrawState);
    var
      nArea: LongInt;
    begin
      // Check the field value and assign a color
      nArea := tblColor.FieldByName( 'AREA' ).AsInteger;
      if nArea < 1000000 then
        grdColor.Canvas.Brush.Color := clBlue
      else if nArea < 2000000 then
        grdColor.Canvas.Brush.Color := clAqua
      else if nArea < 3000000 then
        grdColor.Canvas.Brush.Color := clRed
      else begin
        grdColor.Canvas.Brush.Color := clTeal;
        grdColor.Canvas.Font.Style  := [ fsBold ];
      end;
      grdColor.DefaultDrawColumnCell( Rect, DataCol, Column, State );
    end;
    

    Go Top


    Menduplikatkan Form Saat Runtime
    Tanya:
    Apakah saya bisa menduplikatkan suatu form saat runtime ??

    Jawab:
    Bisa, kita lakukan dengan memanfaatkan fasilitas streaming dalam Delphi. Silakan lihat code seperti ini:

    procedure TfrmMain.btnDupeFormClick(Sender: TObject);
    var
      ms: TMemoryStream;
      frmDuplicate: TfrmMain;
    begin
      ms := TMemoryStream.Create;
      try
        ms.WriteComponent( frmMain );
        frmDuplicate := TfrmMain.CreateNew( Application );
        ms.Position := 0;
        ms.ReadComponent( frmDuplicate );
        // Lokasi dirubah agar terlihat di layar
        frmDuplicate.Top  := 0;
        frmDuplicate.Left := 0;
        frmDuplicate.Show;
      finally
        ms.Free;
      end;
    end;
    

    Go Top


    Apakah Hash itu ??
    Tanya:
    Sehubungan dengan security, saya sering mendengar istilah "hash". Pertanyaan saya, apa sih sebenarnya hash itu ?? Dan bagaimana menerapkannya dalam Delphi ??

    Jawab:
    Hash merupakan penghitungan suatu string menjadi suatu nilai yang lebih pendek yang bisa mewakili string tersebut. Hash banyak dipakai pada algoritma enkripsi maupun index.

    Hash sudah diterapkan di Delphi dan dapat kita baca pada source code VCL secara langsung di file dbtables.pas, seperti yang saya cuplik berikut ini:

    function GetHashCode(Str: PChar): Integer;
    var
      Off, Len, Skip, I: Integer;
    begin
      Result := 0;
      Off := 1;
      Len := StrLen(Str);
      if Len < 16 then
        for I := (Len - 1) downto 0 do
        begin
          Result := (Result * 37) + Ord(Str[Off]);
          Inc(Off);
        end
      else
      begin
        { Only sample some characters }
        Skip := Len div 8;
        I := Len - 1;
        while I >= 0 do
        begin
          Result := (Result * 39) + Ord(Str[Off]);
          Dec(I, Skip);
          Inc(Off, Skip);
        end;
      end;
    end;
    

    Bila Anda masih penasaran dan ingin mencari komponen Hash siap pakai, silakan mencoba salah satu contoh yaitu HashLib! v1.02 oleh Alex Demchenko (alex@ritlabs.com) yang bisa di-download langsung di http://www.torry.net/vcl/security/crypting/adhashlib.zip atau bisa ditemui pada CD Mikrodata edisi ini.

    Go Top


    Membuat GUID Saat Runtime
    Tanya:
    Saya sedang membuat suatu aplikasi yang harus menghasilkan suatu ID yang unik untuk masing-masing object dalam aplikasi ini. Bagaimana caranya ?? Saya pernah mendengar tentang GUID, dapatkah GUID ini digunakan untuk memecahkan permasalahan saya ini ?? Terima kasih.

    Jawab:
    Ya, dalam hal ini, Anda dapat menggunakan GUID. GUID adalah kependekan dari Globally Unique Identifier, yang berarti suatu identitas yang dijamin unik secara global. Adapun cara untuk membuat GUID saat runtime adalah:

    // Tambahkan ComObj, ActiveX pada uses
    
    function TfrmCreateGUID.CreateGUID: String;
    var
      ID: TGUID;
    begin
      Result := '';
      if CoCreateGuid( ID ) = S_OK then
        Result := GUIDToString( ID );
    end;
    
    procedure TfrmCreateGUID.btnCreateGUIDClick(Sender: TObject);
    begin
      edtGUID.Text := CreateGUID;
    end;
    

    Go Top


    Mengetahui Uptime Windows
    Tanya:
    Saya ingin mengetahui sudah berapa lama Windows berjalan sejak dinyalakan (uptime Windows). Bagaimanakah cara pemrogramannya dalam Delphi ??

    Jawab:
    Anda bisa menggunakan fungsi GetTickCount, namun ingat, GetTickCount akan menghasilkan suatu angka dalam satuan milidetik yang menyatakan berapa tick telah berjalan sejak Windows dinyalakan, sehingga Anda harus membaginya dengan 1000 untuk mendapatkan hasil dalam satuan detik. Lihat contoh pemrograman berikut ini:

    function TfrmMain.Uptime: String;
    const
      nTicksPerDay: Integer = 1000 * 60 * 60 * 24;
      nTicksPerHour: Integer = 1000 * 60 * 60;
      nTicksPerMinute: Integer = 1000 * 60;
      nTicksPerSecond: Integer = 1000;
    var
      lwUptime: LongWord;
      nDay, nHour, nMin, nSec: Integer;
    begin
      lwUptime := GetTickCount;
    
      nDay := lwUptime div nTicksPerDay;
      Dec( lwUptime, nDay * nTicksPerDay );
    
      nHour := lwUptime div nTicksPerHour;
      Dec( lwUptime, nHour * nTicksPerHour );
    
      nMin := lwUptime div nTicksPerMinute;
      Dec( lwUptime, nMin * nTicksPerMinute );
    
      nSec := lwUptime div nTicksPerSecond;
      
      Result := IntToStr( nDay ) + ' hari ' +
        IntToStr( nHour ) + ' jam ' +
        IntToStr( nMin ) + ' menit ' +
        IntToStr( nSec ) + ' detik ';
    end;
    
    
    procedure TfrmMain.tmrWinUptimeTimer(Sender: TObject);
    begin
      edtWinUptime.Text := Uptime;
    end;
    

    Go Top


    Baris Kosong dalam TMemo
    Tanya:
    Saya mengalami hal yang aneh dengan TMemo, dimana saya menempatkan suatu TMemo dengan area yang cukup untuk menampilkan 5 baris teks, lalu saya melakukan penambahan isi teks TMemo secara pemrograman, selalu terlihat bahwa TMemo menambahkan satu baris kosong, sehingga saat saya menambahkan baris teks yang ke-5, maka isi TMemo akan scroll otomatis. Bagaimanakah caranya agar TMemo tidak menambahkan baris kosong secara otomatis ??

    Jawab:
    Method Add akan menambahkan baris kosong. Agar tidak menambah baris kosong, dapat kita siasati dengan seakan-akan melakukan proses penggantian teks dengan property SelStart dan SelText.

    Memo1.SelStart := Memo1.GetTextLen;
    Memo1.SelText  := 'Memo';
    

    Go Top


    Scroll ke Akhir TMemo/TRichEdit
    Tanya:
    Saya membuat suatu aplikasi yang menampilkan log aktifitas secara real-time. Kesulitan saya adalah bagaimanakah saya dapat 'memaksa' TMemo ataupun TRichEdit untuk menampilkan bagian akhir dari isi teks-nya pada saat saya menambahkan isi baris yang baru ?? Terima kasih atas bantuannya.

    Jawab:
    'Paksaan' :-) ini dapat Anda lakukan dengan mengirimkan message WM_VSCROLL (Vertical Scroll) dengan parameter SB_BOTTOM, lihat baris berikut:

    PostMessage( Memo1.Handle, WM_VSCROLL, SB_BOTTOM, 0 );
    

    Go Top


    Memaksa TDateTimePicker untuk Drop-down Otomatis
    Tanya:
    Saya ingin memaksa agar TDateTimePicker dalam aplikasi saya untuk menampilkan drop-down secara otomatis (maksudnya secara pemrograman), sehingga lebih mudah dan intuitif bagi user.

    Jawab:
    Hmm, saya jadi heran, edisi Klinik Mr. Delphi ini koq banyak pemaksaan yah :-). Tentu saja Anda dapat 'memaksa' TDateTimePicker ini untuk drop-down secara pemrograman, karena TDateTimePicker akan menampilkan drop-down saat Anda menekan tombol F4, karenanya solusinya menjadi cukup sederhana, kita emulasikan bahwa tombol F4 telah ditekan, gunakan code berikut:

    with DateTimePicker1 do begin
      Perform( WM_KEYDOWN, VK_F4, 0 );
      Perform( WM_KEYUP, VK_F4, 0 );
    end;
    

    Go Top


    Version Control dalam Delphi
    Tanya:
    Kami sering mengalami kesulitan dalam mengoordinasikan pengembangan suatu project secara tim, dimana tim terdiri dari empat sampai lima orang programmer Delphi. Terkadang seorang programmer harus memberitahu yang lain bahwa source code anu sedang dia revisi, sehingga yang lain jangan melakukan perubahan dalam source code tersebut.

    Terus terang hal ini sangat mengganggu, apakah ada solusi lain untuk mengatasi hal ini ?? Kalau bisa yang gratis yah :-)

    Jawab:
    Masalah ini sebenarnya dapat dengan mudah diselesaikan dengan utility Version Control. Selain itu, utility ini juga dapat membantu kita untuk mengembalikan perubahan-perubahan yang pernah kita lakukan walaupun secara bertingkat (berkali-kali). Ada banyak utility semacam ini, namun untuk yang gratis dan cukup terintegrasi dengan Delphi, saya bisa menyarankan FreeVCS dari Thomas Hensle, yang bisa Anda simak di http://www.freevcs.de

    Ada dua macam FreeVCS, yaitu:

  • Stand-alone, mampu menangani version control untuk semua macam file program
  • IDE Expert, terintegrasi dengan IDE Delphi

    Dengan FreeVCS, kita mempunyai alur pengembangan seperti berikut:

  • Membuat project baru dalam Delphi
  • Membuat project baru dalam FreeVCS
  • Menambahkan modul baru dalam Delphi dan check-in ke FreeVCS
  • Bilamana kita akan merubah modul, maka kita cukup check-out dari FreeVCS, merubah dan melakukan testing modul, bila sudah Ok, lalu kita check-in ke FreeVCS kembali

    FreeVCS Server mampu menyimpan project Anda dalam berbagai format, diantaranya DBISAM, Interbase, Oracle, MS SQL Server, FlashFiler, dan Informix.

    Untuk lebih jelasnya, silakan Anda baca file Help di FreeVCS

    Go Top


    Copyright © 2003, Hianoto Santoso