SrmUnit.~pa
上传用户:tj00001
上传日期:2007-01-07
资源大小:672k
文件大小:12k
源码类别:

行业应用

开发平台:

Delphi

  1. //---------------------------------------------------------------------------
  2. //(R)CopyRight KivenSoft International ,inc 1999
  3. //单元名称:数据库单元
  4. //程序名称:电子书库
  5. //作    者:李会文
  6. //开始时间:1998.07.28
  7. //最后修改:1999.07.22
  8. //备注:此单元定义了SRM文件的读写接口
  9. //---------------------------------------------------------------------------
  10. unit SrmUnit;
  11. interface
  12. uses
  13.   Windows,SysUtils,Classes, SrmConst;
  14. type
  15. PCharArray=^TCharArray;
  16. TCharArray=array[0..0] of char;
  17. PDwordArray=^TDwordArray;
  18. TDwordArray=array[0..0] of DWORD;
  19. PIntArray=^TIntArray;
  20. TIntArray=array[0..0] of integer;
  21. PTreeData=^TTreeData;
  22. TTreeData=record        //索引信息
  23.   Pos: longint;
  24.   DataType: longint;
  25. end;
  26. PTdArray=^TTdArray;
  27. TTdArray=array[0..0] of TTreeData;
  28. PFileHead=^TFileHead;
  29. TFileHead=record
  30.   OpenFlag      :Longint;                      //数据库打开标志
  31.   LastViewPos   :longint;                   //关闭时的位置
  32.   IndexPos      :longint;                   //索引位置
  33.   EditDate      :TDateTime;                 //最后修改日期
  34.   Key           :DWORD;                     //密钥
  35.   Password      :array[0..11] of char;      //口令
  36.   Author        :array[0..15] of char;      //作者
  37.   BuildDate     :TDateTime;                 //建库日期
  38.   DataType      :longint;                   //数据库格式
  39.   DataFlag      :array[0..7] of char;       //数据库标志
  40.   Version       :longint;                   //数据库版本
  41.   BookMerg      :array[0..9] of longint;    //10个书签
  42.   Keep          :longint;                   //保留字段
  43. end;
  44. //DataType 0:Index    1:Normal Dir     2:Notmal TXT    3:Normal HTML
  45. PIndexHead=^TIndexHead;
  46. TIndexHead=record
  47.   DataType      :longint;                   //段类型
  48.   Key           :DWORD;                     //密钥
  49.   Count         :longint;                   //标题数量
  50.   Size          :longint;                   //标题长度
  51.   Keep          :longint;                   //保留字段
  52. end;
  53. PDataHead=^TDataHead;
  54. TDataHead=record
  55.   DataType      :longint;                   //段类型
  56.   Author        :array[0..15] of char;      //作者
  57.   PubDate       :TDateTime;                 //收录日期
  58.   Key           :DWORD;                     //密钥
  59.   Num           :longint;                   //附件数量
  60.   SearchKey     :array[0..51] of char;      //关键词
  61.   Password      :array[0..11] of char;      //口令
  62.   Keep          :longint;                   //保留字段
  63. end;
  64. //------------------------------------------------------------------------
  65. TSrmObject=class
  66.   private
  67.     FChangeFlag         :boolean;   //在文件后有增加新信息的变量
  68.     FDbChanged          :boolean;   //数据库属性有变动
  69.     FIndexChanged       :boolean;   //索引有变动
  70.     FItemHeadChanged    :boolean;   //标题头有变动
  71.     FItemDataChanged    :boolean;   //标题内容有变动
  72.     FFileHead           :TFileHead;
  73.     FIndexHead          :TIndexHead;
  74.     FDataHead           :TDataHead;
  75.     FFileHandle         :integer;       //文件句柄
  76.     FFileName           :string;
  77.     FActivePos          :longint;       //当前读出内容的位置
  78.     procedure Encypher(Cypher:DWORD;var Buf;Count:integer);
  79.     procedure Decypher(Cypher:DWORD;var Buf;Count:integer);
  80.     procedure CreateSrmFile;            //建立一个空数据库
  81.     procedure SetDbChanged(Value:boolean);
  82.     procedure SetIndexChanged(Value:boolean);
  83.     procedure SetItemHeadChanged(Value:boolean);
  84.     procedure SetItemDataChanged(Value:boolean);
  85.   public
  86.     property FileName:string read FFileName;
  87.     property FileHead:TFileHead read FFileHead write FFileHead;
  88.     property IndexHead:TIndexHead read FIndexHead write FIndexHead;
  89.     property DataHead:TDataHead read FDataHead write FDataHead;
  90.     property ActivePos:longint read FActivePos write FActivePos;
  91.     property DbChanged:boolean read FDbChanged write SetDbChanged;
  92.     property IndexChanged:boolean read FIndexChanged write SetIndexChanged;
  93.     property ItemHeadChanged:boolean read FItemHeadChanged write SetItemHeadChanged;
  94.     property ItemDataChanged:boolean read FItemDataChanged write SetItemDataChanged;
  95.     constructor Create(Fn:string;Mode:Word);
  96.     destructor Destroy;override;
  97.     procedure Free;
  98.     procedure SaveSrmFile;          //不关闭文件情况下保存文件
  99.     procedure LoadIndex(Msh,Msd:TMemoryStream); //读索引
  100.     procedure SaveIndex(Msh,Msd:TMemoryStream);//写索引
  101.     class function IsSrmFile(var Fn:string):boolean;//判断是否是SRM格式数据库文件
  102.     procedure ReadItemHead(Ps:longint);  //读数据段头
  103.     procedure ReadItemData(DataStream:TMemoryStream);  //读数据段内容
  104.     procedure EditItemHead(Ps:longint);    //修改数据头
  105.     function AddItemHead:longint;          //写数据段头
  106.     procedure AddItemData(DataStream:TMemoryStream); //写数据段内容
  107.     function GetItemPassword(Ps:longint):string; //得某标题口令
  108.  end;
  109. //------------------------------------------------------------------------
  110. implementation
  111. //------------------------------------------------------------------------
  112. procedure TSrmObject.Encypher(Cypher:DWORD;var Buf;Count:integer);
  113. var
  114.   i:integer;
  115. begin
  116.   Cypher:=not Cypher;
  117.   Dec(Count);
  118.   for i:=0 to Count do
  119.     TDwordArray(Buf)[i]:=TDwordArray(Buf)[i] xor Cypher;
  120. end;
  121. procedure TSrmObject.Decypher(Cypher:DWORD;var Buf;Count:integer);
  122. var
  123.   i:integer;
  124. begin
  125.   Cypher:=not Cypher;
  126.   Dec(Count);
  127.   for i:=0 to Count do
  128.     TDwordArray(Buf)[i]:=TDwordArray(Buf)[i] xor Cypher;
  129. end;
  130. //------------------------------------------------------------------------
  131. procedure TSrmObject.CreateSrmFile;    //建立一个空数据库
  132. var
  133.   i:integer;
  134. begin
  135.     FFileHandle:=FileCreate(FFileName);
  136.     if FFileHandle=-1 then raise Exception.Create(csCanNotCreate);
  137.     //添充缺省信息头
  138.     with FFileHead do
  139.     begin
  140.       OpenFlag:=0;
  141.       LastViewPos:=0;
  142.       IndexPos:=sizeof(TFileHead);
  143.       EditDate:=Now;
  144.       Key:=GetTickCount;
  145.       Password[0]:=#0;
  146.       Author[0]:=#0;
  147.       BuildDate:=EditDate;
  148.       DataType:=0;
  149.       Version:=3;
  150.       Keep:=0;
  151.       DataFlag[0]:='K';
  152.       DataFlag[1]:='i';
  153.       DataFlag[2]:='v';
  154.       DataFlag[3]:='e';
  155.       DataFlag[4]:='n';
  156.       for i:=0 to 9 do BookMerg[i]:=-1;
  157.     end;
  158.     //添充缺省索引
  159.     with FIndexHead do
  160.     begin
  161.       DataType:=0;
  162.       Key:=GetTickCount;
  163.       Count:=0;
  164.       Size:=0;
  165.       Keep:=0;
  166.     end;
  167.     //加密写入文件后解密
  168.     with FFileHead do
  169.     begin
  170.       Encypher(Key,Author,4);
  171.       Encypher(Key,Password,3);
  172.       FileWrite(FFileHandle,FFileHead,sizeof(TFileHead));
  173.       FileWrite(FFileHandle,FIndexHead,sizeof(TIndexHead));
  174.       Decypher(Key,Author,4);
  175.       Decypher(Key,Password,3);
  176.     end;
  177. end;
  178. constructor TSrmObject.Create(Fn:string;Mode:Word);
  179. begin
  180.   FFileName:=Fn;
  181.   FChangeFlag:=false;
  182.   FDbChanged:=false;
  183.   FIndexChanged:=false;
  184.   FItemHeadChanged:=false;
  185.   FItemDataChanged:=false;
  186.   FDataHead.Keep:=0;
  187.   //打开文件时读文件头,否则建新文件
  188.   if Mode=fmOpenReadWrite then
  189.   begin
  190.     FFileHandle:=FileOpen(FFileName,fmOpenReadWrite);
  191.     FileRead(FFileHandle,FFileHead,sizeof(TFileHead));
  192.     with FFileHead do
  193.     begin
  194.       Decypher(Key,Password,3);
  195.       Decypher(Key,Author,4);
  196.     end;
  197.   end
  198.   else if Mode=fmCreate then
  199.   begin
  200.     CreateSrmFile;
  201.   end;
  202. end;
  203. destructor TSrmObject.Destroy;
  204. begin
  205.   if FFileHandle<>-1 then
  206.   begin
  207.     FileClose(FFileHandle);  //关闭文件
  208.     FFileHandle:=-1;
  209.   end;
  210.   inherited;
  211. end;
  212. procedure TSrmObject.Free;
  213. begin
  214.   if Assigned(self) then Destroy;
  215. end;
  216. procedure TSrmObject.SaveSrmFile;
  217. begin
  218.   //写入更新后的文件头
  219.   with FFileHead do
  220.   begin
  221.     FileSeek(FFileHandle,0,0);
  222.     EditDate:=Now;
  223.     Key:=GetTickCount;
  224.     Encypher(Key,Password,3);
  225.     Encypher(Key,Author,4);
  226.     FileWrite(FFileHandle,FFileHead,sizeof(TFileHead));
  227.     Decypher(Key,Password,3);
  228.     Decypher(Key,Author,4);
  229.   end;
  230. end;
  231. class function TSrmObject.IsSrmFile(var Fn:string):boolean;
  232. var
  233.   Fh: TFileHead;
  234.   Fs: TFileStream;
  235. begin
  236.   Result:=false;
  237.   Fs:=TFileStream.Create(Fn,fmOpenRead);
  238.   //根据文件长度判断
  239.   with Fs do
  240.   begin
  241.     if (Size<(sizeof(TFileHead)+sizeof(TIndexHead))) then
  242.     begin
  243.       Free;
  244.       Result:=false;
  245.       Exit;
  246.     end;
  247.     Read(Fh,sizeof(TFileHead));
  248.     Free;
  249.   end;
  250.   //根据文件标志判断
  251.   with Fh do
  252.   begin
  253.     if ( (DataFlag[0]='K') and (DataFlag[1]='i') and
  254.         (DataFlag[2]='v') and (DataFlag[3]='e') and
  255.         (DataFlag[4]='n') ) then
  256.       Result:=true;
  257.   end;
  258. end;
  259. procedure TSrmObject.LoadIndex(Msh,Msd:TMemoryStream);
  260. begin
  261.   //读出索引头
  262.   FileSeek(FFileHandle,FFileHead.IndexPos,0);
  263.   FileRead(FFileHandle,FIndexHead,sizeof(TIndexHead));
  264.   //处理索引长度为0的状况,否则读出具体索引
  265.   if (FIndexHead.Size=0) then
  266.   begin
  267.     Msh.SetSize(0);
  268.     Msd.SetSize(0);
  269.   end
  270.   else
  271.   begin
  272.     Msh.SetSize(FIndexHead.Size);
  273.     Msd.SetSize(FIndexHead.Count*sizeof(longint)*2);
  274.     FileRead(FFileHandle,Msh.Memory^,Msh.Size);
  275.     FileRead(FFileHandle,Msd.Memory^,Msd.Size);
  276.     Decypher(FIndexHead.Key,Msh.Memory^,Msh.Size div 4);
  277.   end;
  278. end;
  279. procedure TSrmObject.SaveIndex(Msh,Msd:TMemoryStream);
  280. begin
  281.   if FChangeFlag then  //增加过新内容时
  282.     FFileHead.IndexPos:=FileSeek(FFileHandle,0,2)
  283.   else                 //无新增内容
  284.     FileSeek(FFileHandle,FFileHead.IndexPos,0);
  285.   //设置数据头
  286.   with FIndexHead do
  287.   begin
  288.     Key:=GetTickCount;
  289.     Size:=Msh.Size;
  290.     Count:=Msd.Size div (sizeof(longint)*2);
  291.   end;
  292.   //加密标题内容
  293.   Encypher(FIndexHead.Key,Msh.Memory^,Msh.Size div 4);
  294.   //写入索引
  295.   FileWrite(FFileHandle,FIndexHead,sizeof(TIndexHead));
  296.   FileWrite(FFileHandle,Msh.Memory^,Msh.Size);
  297.   FileWrite(FFileHandle,Msd.Memory^,Msd.Size);
  298. end;
  299. procedure TSrmObject.ReadItemHead(Ps:longint);
  300. begin
  301.   FActivePos:=Ps;  //保存当前数据位置
  302.   //读出并解密
  303.   with FDataHead do
  304.   begin
  305.     FileSeek(FFileHandle,Ps,0);
  306.     FileRead(FFileHandle,FDataHead,sizeof(TDataHead));
  307.     Decypher(Key,SearchKey,13);
  308.     Decypher(Key,Author,4);
  309.     Decypher(Key,Password,3);
  310.   end;
  311. end;
  312. procedure TSrmObject.ReadItemData(DataStream:TMemoryStream);
  313. var
  314.   size:longint;
  315. begin
  316.   //读出具体内容
  317.   FileRead(FFileHandle,size,sizeof(longint));
  318.   DataStream.SetSize(size);
  319.   FileRead(FFileHandle,DataStream.Memory^,size);
  320.   Decypher(FDataHead.Key,DataStream.Memory^,size div 4);
  321. end;
  322. procedure TSrmObject.EditItemHead(Ps:longint);
  323. begin
  324.   //修改数据头
  325.   FileSeek(FFileHandle,Ps,0);
  326.   with FDataHead do
  327.   begin
  328.     Encypher(Key,SearchKey,13);
  329.     Encypher(Key,Author,4);
  330.     Encypher(Key,Password,3);
  331.     FileWrite(FFileHandle,FDataHead,sizeof(TDataHead));
  332.     Decypher(Key,SearchKey,13);
  333.     Decypher(Key,Author,4);
  334.     Decypher(Key,Password,3);
  335.   end;
  336. end;
  337. function TSrmObject.AddItemHead:longint;
  338. begin
  339.   //新内容增加时移到文件尾添加
  340.   FChangeFlag:=true;
  341.   with FDataHead do
  342.   begin
  343.     Result:=FileSeek(FFileHandle,0,2);
  344.     Key:=GetTickCount;
  345.     PubDate:=Now;
  346.     Encypher(Key,SearchKey,13);
  347.     Encypher(Key,Author,4);
  348.     Encypher(Key,Password,3);
  349.     FileWrite(FFileHandle,FDataHead,sizeof(TDataHead));
  350.     Decypher(Key,SearchKey,13);
  351.     Decypher(Key,Author,4);
  352.     Decypher(Key,Password,3);
  353.   end;
  354. end;
  355. procedure TSrmObject.AddItemData(DataStream:TMemoryStream);
  356. var
  357.   size:longint;
  358. begin
  359.   size:=DataStream.Size;
  360.   FileWrite(FFileHandle,size,sizeof(longint));
  361.   Encypher(FDataHead.Key,DataStream.Memory^,size div 4);
  362.   FileWrite(FFileHandle,DataStream.Memory^,size);
  363. end;
  364. function TSrmObject.GetItemPassword(Ps:longint):string; //得某标题口令
  365. var
  366.   Dh:TDataHead;
  367. begin
  368.   //读出并解密
  369.   with Dh do
  370.   begin
  371.     FileSeek(FFileHandle,Ps,0);
  372.     FileRead(FFileHandle,Dh,sizeof(TDataHead));
  373.     Decypher(Key,Password,3);
  374.   end;
  375.   result:=string(Dh.Password);
  376. end;
  377. procedure TSrmObject.SetDbChanged(Value:boolean);
  378. begin
  379.   FDbChanged:=Value;
  380. end;
  381. procedure TSrmObject.SetIndexChanged(Value:boolean);
  382. begin
  383.   FIndexChanged:=Value;
  384.   if Value then FDbChanged:=Value;
  385. end;
  386. procedure TSrmObject.SetItemHeadChanged(Value:boolean);
  387. begin
  388.   FItemHeadChanged:=Value;
  389.   if Value then
  390.   begin
  391.     FIndexChanged:=Value;
  392.     FDbChanged:=Value;
  393.   end;
  394. end;
  395. procedure TSrmObject.SetItemDataChanged(Value:boolean);
  396. begin
  397.   FItemDataChanged:=Value;
  398.   if Value then
  399.   begin
  400.     FIndexChanged:=Value;
  401.     FDbChanged:=Value;
  402.   end;
  403. end;
  404. end.