Forumda aradım ancak bulamadım. Ayrıca google üzerinden de arattırdım ancak genelde hep ticari bileşen paketi siteleri çıkıyor.
Bu nedenle biraz deneme yanılma yoluyla bu konuya bir çözüm buldum. Umarım beğenirsiniz ve yorumlarınızı da bekliyorum. Bulduğum çözümü sizinle paylaşmak istiyorum. (Böylece bu ticari paketlere de gereksinimimiz kalmaz) Ayrıca çözümleyemediğim bir konu var (sıralama) o konuda fikir verebilirseniz de sevinirim.
Öncelikle bir özgeçmiş vereyim: Şimdi bir sözlük uygulamamız var. Bu sözlük uygulamamızın verileri, FB VT'de saklanıyor. Eğer nasip olursa ticari bir uygulama haline gelecek. Ancak kullanıcıya veritabanı dosyasını dağıtacağımız ve uygulamanın veritabanını gömülü (embedded) sunumcu şeklinde kullanacağı için, birilerinin basitçe VT içerisindeki kelime ve tanımları kopyalayıp kendi sözlüğünde kullanması riski var. Bunu önlemek için, VT içerisindeki alanları şifrelemeyi ve hemen göstermeden önce de deşifrelemeyi düşündüm.
Pekçok deneme ve yanılmadan sonra en kolay ve yapılabilir çözümün TField bileşeninin onGetText ve OnSetText olay işleyicilerinin kullanıması olduğunu gördüm.
Bunun için kodumuz şöyle:
Önce OnGetText ve OnSetText olay işleyicilerle tıpatıp aynı parametreleri olan iki prosedür oluşturuyoruz.
Kod: Tümünü seç
TForm1 = class(TForm)
...
...
...
procedure DataFieldSetText(Sender: TField;const Text: String);
procedure DataFieldGetText(Sender: TField;var Text: String;
DisplayText: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
......
Daha sonra Ctrl-Shift-C tuş kombinasyonuna basıp, bu prosedürlerin iskeletinin birim (Unit) içerisinde otomatik olarak oluşturulmasını sağlıyoruz. Ve içlerini aşağıdaki şekilde dolduruyoruz.
Kod: Tümünü seç
procedure TForm1.DataFieldGetText(Sender: TField; var Text: String;
DisplayText: Boolean);
begin
//bu jenerik get text
Text := Desifrele((Sender as TField).AsString);
end;
Kod: Tümünü seç
procedure TForm1.DataFieldSetText(Sender: TField; const Text: String);
var
gecicimetin : String;
begin
gecicimetin := Text;
gecicimetin := Sifrele(gecicimetin);
(Sender as TField).AsString := gecicimetin;
end;
Kod: Tümünü seç
procedure TForm1.FormCreate(Sender: TObject);
Var
i : integer;
AComponent : TComponent;
begin
//burada ilgili fieldları bul ve bunların ONGetText ve OnSetText eventlerini ayarla
For i := 0 to ComponentCount-1 do
begin
AComponent := Components[i];
If AComponent is TField then
begin
If (AComponent as TField).Name =
IBDataSet1ENCRYPTEDFIELD.Name then
begin
(AComponent as TField).OnGetText := DataFieldGetText;
(AComponent as TField).OnSetText := DataFieldSetText;
{$IFDEF HATAAYIKLA}
OutputDebugString(PChar(Format('(AComponent as TField).Name:%s',[(AComponent as TField).Name])));
{$ENDIF}
end;
end;
end;
//burada ilgili fieldları bul ve bunların ONGetText ve OnSetText eventlerini ayarla SON
/burada veritabanını açma işlemlerini yapınız
..........
..........
/burada veritabanını açma işlemlerini yapınız SON
end;
Burada (daha) önemli olan diğer bir konu, bizim oluşturduğumuz prosedürlerin aldığı parametrelerle, OnSetText, OnGetText olay işleyicilerinin aldığı parametrelerin birebir aynı olması. Aksi takdirde bu tayin işlemini (yani (AComponent as TField).OnGetText := DataFieldGetText; vs işlemini) yapamıyoruz derleyici basitçe yapmayı reddediyor.
Diğer bir husus ise Sifrele/Desifrele fonksiyonu bu fonksiyonlar bir string parametresi alıyor ve string sonucu döndürüyor. Fonksiyonların içlerini yazmayacağım çünkü herkesin kendine göre bir şifreleme yöntemi var. Ancak burada ipucu vermek istiyorum. Şifreleme için bu fonksiyonlar içerisinde Delphi Encryption Compendium'un bileşenlerini (ücretsizdir) kullandım. Bu bileşenler 2048 bite kadar şifreleme yapabiliyor. Yani çok güçlü.



Bu işlemleri yapmadan önce boş bir veritabanı oluşturunuz. Bu veritabanı içerisinde TEST adlı bir tablomuz ve bu tablomuzun ise SIRANO ve ENCRYPTEDFIELD alanlarımız olsun.
Birer adet IBDataBase, IBTransaction, IBDataSet, Datasource bileşeni yerleştiriniz. Gerekli Login, Veritabanı konumu ve gerekli diğer parametreler neyse onları ayarlayınız ve IBDataSet'in SQL ifadelerini falan oluşturunuz.
Forma bir DBGrid, DBNavigator, bir DBEdit (veya DBMemo) bileşeni koyunuz ve DBGrid ve DBNavigator'un DataSource özelliğini DataSource'a ayarlayınız. Şimdi çalıştırınız, veri giriniz ve kaydediniz. Programı kapatırken, Commit, ya da CommitRetaining prosedürünü kullanınız. IBExpert'te aynı tablonun verilerine baktığınızda şaşıracaksınız. Çünkü alanın içerdiği veri, uygulamada şifrelenmemiş şekilde gösterilirken, VT içerisinde şifrelenmiş durumdadır.


Şimdi elimde olanı paylaştıktan sonra, sizden bir konuda yardım etmenizi isteyeceğim. Şimdi bunun bir sözlük olması itibariyle, arama özelliği var (StoredProcedure (SP) ile hallettim). Ancak SP ve uygulama içerisindeki IBDataset bileşenlerinin order by KELIME COLLATE PXW_TURK ifadelerini kullanıyor. Ancak veri şifreli olduğu için (yani SP açısından anlamsız olduğu için), çekilen veriyi doğru şekilde sıralamıyor.
Acaba VT'den çekilen veriyi uygulama içerisinde (SQL, vs. kullanmaksızın) tekrar sıralamamın mümkünatı var mıdır? SQL kullanamayağım kesin çünkü veri şifrelenmiş durumda. Bu konuda bir fikri olan var mıdır? Saygılarımla.
Önemli Not : OnGetText ve OnSetText olay işleyicileri yalnızca veri bilinçli (Data Aware) bileşenler üzerinde veri değişikliği yapıldığında ateşleniyor. Eğer kod içerisinde alanların değerlerini programsal olarak değiştiriyorsak, OnGetText ve OnSetText olay işleyicileri ateşlenmiyor. Bu durumda, şu şekilde kod yazmak gerekiyor
Kod: Tümünü seç
IBDataSet1KELIME.AsString := Sifrele('Ne Mutlu Türküm Diyene');
Umarım birilerinin işine yarar ve hep birlikte daha gelişmiş bir hale getirebiliriz.