/ / -------------------------------------------------------------------------------------------- --------------------------- // (r) Copyright Kivensoft International, Inc 1999 // Unit Name: Database unit // Program Name: Electronic Book // Author: Li Huiwen // Start Time: 1998.07.28 // Last modified: 1999.07.22 // Note: This unit defines the reading and writing interface of the SRM file / / ---------- -------------------------------------------------- -------------- Unit Srmunit;
Interface
Uses Windows, Sysutils, Classes, SRMCONST
TYPCHARRAY = ^ Tchararray; tchararray = array [0..0] of char; pdwordArray = ^ TdwordArray; TdwordArray = array [0..0] of dword; PintArray = ^ TintArray; TintArray = array [0..0] of integer ;
PTREEDATA = ^ TTREEDATA; TTREEDATA = Record // Index Information POS: Longint; DataType: longint; end; ptdarray = ^ TtdAray; ttdarray = array [0..0] of tTREEDATA;
PfileHead; tfilehead = record OpenFlag: longint; // Database Open flag LastviewPos: longint; // Close position Indexpos: longint; // Index location editdate: tdatetime; // Last modified date key: dword; // Key Password: array [0..11] of char; // password Author: array [0..15] of char; // author builddate: tdatetime; // Jian library date DataType: longint; // database format DataFlag : array [0..7] of char; // Database Sign Version: longint; // Database version BOOKMERG: Array [0..9] of longint; // 10 bookmarks KEEP: longint; // Reserved field end;
// DataType 0: Index 1: Normal Dir 2: NOTMAL TXT 3: Normal HTMLPINDEXHEAD = ^ TINDEXHEAD; TINDEXHEAD = Record DataType: longint; // segment type key: dword; // Key count: longint; // Tit number Size : longint; // Title length Keep: longint; // Reserved field end; pdatahead = ^ tdatahead; tdatahead = Record DataType: longint; // segment type Author: array [0..15] of char; // Author Pubdate: TDATETIME; // Remarks Date Key: DWORD; // Key Num: longint; // Accessories Searchkey: array [0..51] of char; // Keyword Password: array [0..11] of char; // Password Keep: longint; // Reserved field end;
/ / -------------------------------------------------------------------------------------------- ------------------------ TsrmObject = Class Private Fchangeflag: boolean; // There is a variable that adds new information after the file fdbchange; // database properties are subject to change FIndexChanged: boolean; // index are subject to change FItemHeadChanged: boolean; // title head are subject to change FItemDataChanged: boolean; // title contents are subject to change FFileHead: TFileHead; FIndexHead: TIndexHead; FDataHead: TDataHead; FFileHandle: integer; // File handle FFileName: string; FactivePos: longint; // The location of the current sense
procedure Encypher (Cypher: DWORD; var Buf; Count: integer); procedure Decypher (Cypher: DWORD; var Buf; Count: integer); procedure CreateSrmFile; // Create an empty database procedure SetDbChanged (Value: boolean); procedure SetIndexChanged ( Value: boolean); procedure SetItemHeadChanged (Value: boolean); procedure SetItemDataChanged (Value: boolean); public property FileName: string read FFileName; property FileHead: TFileHead read FFileHead write FFileHead; property IndexHead: TIndexHead read FIndexHead write FIndexHead; property DataHead: TDataHead read FDataHead write FDataHead; property ActivePos: longint read FActivePos write FActivePos; property DbChanged: boolean read FDbChanged write SetDbChanged; property IndexChanged: boolean read FIndexChanged write SetIndexChanged; property ItemHeadChanged: boolean read FItemHeadChanged write SetItemHeadChanged; property ItemDataChanged: boolean read FItemDataChanged write SetItemDataChanged Constructor Create (FN: String; Mode: W ord); destructor Destroy; override; procedure Free; procedure SaveSrmFile; // save the file without closing the procedure LoadIndex (Msh, Msd case file under: TMemoryStream); // read index procedure SaveIndex (Msh, Msd: TMemoryStream); // write Index Class Function Issrmfile (VAR FN: String): boolean; // Determine whether it is a SRM format database file procedure readitemhead (ps: longint); // read data segment head Procedure ReadItemData (DataStream: tmemorystream); // Read Data Section Content procedure EditItemHead (Ps: longint); // modify header function AddItemHead: longint; // write data section header procedure AddItemData (DataStream: TMemoryStream); // write the pieces of content data function GetItemPassword (Ps: longint): string; // Get a title password end; // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------
IMPLEMentation
/ / -------------------------------------------------------------------------------------------- ------------------------ Procedure TsrmObject.encypher (Cypher: dword; var buf; count: integer; begin cypher: = NOT CYPHER; DEC (count); for i: = 0 to count do tdwordArray (buf) [i]: = tdwordArray (buf) [i] xor cypher; end; procedure tsrmobject.decypher (Cypher: dword; var buf; count : integer; var i: integer; begin cypher: = not cypher; dec (count); for i: = 0 to count do tdwordArray (buf) [i]: = TDWORDARRAY (BUF) [i] xor cypher; / / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
procedure TSrmObject.CreateSrmFile; // Create an empty database var i: integer; begin FFileHandle: = FileCreate (FFileName); if FFileHandle = -1 then raise Exception.Create (csCanNotCreate); // default information Tim filling head with FFileHead do Begin openflag: = 0; LastviewPos: = 0; indexpos: = sizeof (tfilehead); editdate: = now; key: = gettickcount; password [0]: = # 0; author [0]: = # 0; builddate: = Editdate; DataType: = 0; Version: = 3; Keep: = 0; DataFlag [0]: = 'k'; DataFlag [1]: = 'i'; DataFlag [2]: = 'v'; DataFlag [3 ]: = 'E'; DataFlag [4]: = 'n'; for i: = 0 to 9 do bookmerg [i]: = - 1; end; // Add deficiency index with Findexhead do begattype: = 0; key: = 0; size: = 0; Keep: = 0; end; // Encrypted write file After decrypting with ffilehead do begin Encypher (Key, Author, 4); EncyPher (key, password , 3); FileWrite (FFileHandle, FFileHead); FileWrite (FFileHandle, FINDEXHEAD, SIZEOF (TINDEXHEAD)); DECYPHER (KEY, AUTHOR, 4); Decypher (Key, Password, 3); End;
constructor TSrmObject.Create (Fn: string; Mode: Word); begin FFileName: = Fn; FChangeFlag: = false; FDbChanged: = false; FIndexChanged: = false; FItemHeadChanged: = false; FItemDataChanged: = false; FDataHead.Keep: = 0; read the file header when // open a file, or build a new file if Mode = fmOpenReadWrite then begin FFileHandle: = FileOpen (FFileName, fmOpenReadWrite); FileRead (FFileHandle, FFileHead, sizeof (TFileHead)); with FFileHead do begin Decypher (Key, Password, 3); Decypher (Key, Author, 4); end; end else if Mode = fmCreate then begin CreateSrmFile; end; end; destructor TSrmObject.Destroy; begin if FFileHandle <> - 1 then begin FileClose (FFileHandle); / / Close the file ffileHandle: = - 1; end; inherited;
Procedure TsrmObject.Free; Begin if Assigned (Self) THEN DESTROY;
Procedure TsrmFile; begin // Write updated file header with ffilehead do begin fileseek (ffilehandle, 0); editdate: = now; key: = gettickcount; Encypher (key, password, 3); Encypher , Author, 4); FileWrite (FFileHandle, FFileHead, Sizeof (TFileHead); DECYPHER (Key, Password, 3); DECYPHER (Key, Author, 4); end; end;
Class Function TsrmObject.issRmfile (var fn: string): boolean; var fh: tfilehead; fs: tfilestream; begin result: = false; fs: = tfilestream.create (fs: = tfilestream.create (fmopenread); / / Depending on the file length with fs do Begin IF (SIZEOEAD SIZEOF (TINDEXHEAD))) The begin Free; Result: = FALSE; EXIT; End; Read (FH, SIZEOF (TFileHead)); Free; End; // Depending on file flag WITH FH DO BEGIN IF ((DataFlag [0] = 'k') AND (DataFlag [1] = 'I') AND (DataFlag [2] = 'V') AND (DataFlag [3] = 'E') (DataFlag [4] = 'n')) THEN Result: = true; end; end; procedure tsrmobject.loadIndex (MSH, MSD: TMemoryStream); Begin // Read the index headeseek (ffilehandle, ffilehead.indexpos, 0) FileRead (FFileHandle, FINDEXHEAD, SIZEOF (TINDEXHEAD)); // Process the status of index length 0, otherwise reads the specific index IF (FINDEXHEAD.SIZE = 0) Then Begin msh.setsize (0); msd.setsize (0 ); End else begin msh.setsize; msd.setsize (FINDEXHEAD.COUNT * SIZEOF (longInt) * 2); FileRead (ffileHandle, Msh.Memory ^, MSH.Size); FileRead (FFileHandle, MSD. Memory ^, MSD .Size); DECYPHER (FINDEXHEAD.KEY, MSH.MEMORY ^, MSH.SIZE DIV 4); end;
procedure TSrmObject.SaveIndex (Msh, Msd: TMemoryStream); when begin if FChangeFlag then // increase over new content FFileHead.IndexPos: = FileSeek (FFileHandle, 0,2) else // no new content FileSeek (FFileHandle, FFileHead.IndexPos , 0); // Setting the data head with Findexhead Do Begin Key: = gettickcount; size: = msh.size; count: = msd.size div (sizeof (longint) * 2); end; // encryption title ENCYPHER FINDEXHEAD.KEY, MSH.MEMORY ^, MSH.Size Div 4); // Write Index FileWrite (FileHndle, FINDEXHEAD, SIZEOF (TINDEXHEAD)); FileWrite (ffileHandle, Msh.Memory ^, MSH.Size); FileWrite (ffileHandle , MSD.MEMORY ^, MSD.Size); end; procedure tsrmobject.readItemhead (ps: longint); begin factivepos: = ps; // Save the current data location // Read and decrypt with fdatahead do begin Fileseek (ffileHandle, PS , 0); FileRead (FFileHandle, FDatahead); Decypher (Key, Searchkey, 13); DECYPHER (Key, Author, 4); DECYPHER (Key, Password, 3); end;
procedure TSrmObject.ReadItemData (DataStream: TMemoryStream); var size: longint; begin // read specific content FileRead (FFileHandle, size, sizeof (longint)); DataStream.SetSize (size); FileRead (FFileHandle, DataStream.Memory ^, Size); DECYPHER (fdatahead.key, datastream.memory ^, size div 4);
Procedure TsrmObject.edititemhead (ps: longint); begin // Modify Data Head Fileseek (FFileHandle, PS, 0); with fdatahead do begin Encypher (Key, Searchkey, 13); Encypher (Key, Author, 4); Encypher (Key) , Password, 3); FileWrite (FFileHandle, FDatahead, Sizeof (TDataHead); DecyPher (Key, SearchKey, 13); DECYPHER (Key, Author, 4); DECYPHER (Key, Password, 3); End;
Function TsrmObject.additemhead: longint; begin // New content is moved to the file end to add fchangeflag: = true; with fdatahead do begin result: = fileseek (ffilehandle, 0, 2); key: = gettickcount; pubdate: = now; Encypher (Key, Searchkey, 13); Encypher (Key, Author, 4); Encypher (Key, Password, 3); FileWrite (FFileHandle, FDatahead, Sizeof (TDatahead)); DECYPHER (Key, SearchKey, 13); DECYPHER Key, Author, 4); Decypher (Key, Password, 3); end; end; procedure TSrmObject.AddItemData (DataStream: TMemoryStream); var size: longint; begin size: = DataStream.Size; FileWrite (FFileHandle, size, sizeof (longint); Encypher (fdatahead.key, datastream.memory ^, size div 4); FileWrite (ffileHandle, DataStream.Memory ^, size);
Function TsrmObject.getItemPassword (ps: longint): String; // Get a title password VAR DH: tdatahead; begin // Read and decrypt with DH do Begin Fileseek (FFileHandle, PS, 0); FileRead (FFileHandle, DH, Sizeof) (Tdatahead); DECYPHER (Key, Password, 3); end; result: = string (DH.Password);
Procedure TsrmObject.setdbchanged (value: boolean); begin fdbchanged: = value;
Procedure TsrmObject.setIndexchanged (value: boolean); begin FINDEXCHANGED: = value; if value dam fdbchanged: = value;
Procedure TsrmObject.SetItem HEADCHANGED (VALUE: BOOLEAN); Begin Fitemheadchanged: = Value; if Value1 Begin FINDEXCHANGED: = VALUE; END;
Procedure tsrmobject.setitemdatachanged (value; = value; fdbchange): = value; fdbchanged: = value; fdbcha;
End.