DBMNG数据库管理与应用

抓住自己最有兴趣的东西,由浅入深,循序渐进地学……
当前位置:首页 > SQLite > 常见问题

自己修改ZeosDBO使其支持加密的SQLite

昨天提交了一些相关的代码去Source Forge,得到的结果是,对方毫不理睬,并且已经删除了我提交的代码
我尊重他们的协议,不自行发布修改后的Zeos,因此,只能将修改方法公开,以便各位自行修改。

要改的地方不是太多,大家看着我的改法,自己改一下就好了,不是很麻烦

[b]一、修改ZPlainSqLiteDriver.pas[/b]
这个文件位于\src\plain目录下

在接口IZSQLitePlainDriver内,修改Open()方法的定义
原始的定义为:[color=#0000ff]function [/color]Open([color=#0000ff]const [/color]filename: PChar; mode: Integer; [color=#0000ff]var [/color]errmsg: PChar): Psqlite;
修改为:[color=#0000ff]function [/color]Open([color=#0000ff]const [/color]filename: PChar; mode: Integer;password: PChar; [color=#0000ff]var [/color]errmsg: PChar): Psqlite;

在类TZSQLite28PlainDriver内,修改Open()方法的定义
修改方法同上,定义是一样的
在类TZSQLite3PlainDriver 内,做同样的修改

继续往下,找到 TZSQLite3PlainDriver.Open()方法,作如下修改:
原始的代码为:
[code]function TZSQLite3PlainDriver.Open(const filename: PChar; mode: Integer; var errmsg: PChar): Psqlite;

var

  Result0: Psqlite;

  Version: string;

  FileNameString: String;

begin

  Result0:= nil;

  Version := LibVersion;

  FileNameString := filename;

  {$IFNDEF VER130}

  if (Version > '3.2.5') then

    ZPlainSqLite3.sqlite_open(PAnsiChar(AnsiToUTF8(FileNameString)), Result0)

  else

  {$ENDIF}

  ZPlainSqLite3.sqlite_open(filename, Result0);

  Result := Result0;

end;[/code]

修改为:[code]function TZSQLite3PlainDriver.Open(const filename: PChar; mode: Integer; password: PChar; var errmsg: PChar): Psqlite;

var

  Result0: Psqlite;

  Version: string;

  FileNameString: String;

begin

  Result0:= nil;

  Version := LibVersion;

  FileNameString := filename;

  {$IFNDEF VER130}

  if (Version > '3.2.5') then

    ZPlainSqLite3.sqlite_open(PAnsiChar(AnsiToUTF8(FileNameString)), Result0)

  else

  {$ENDIF}

  ZPlainSqLite3.sqlite_open(filename, Result0);

  Result := Result0;

  if password <> EmptyStr then                                                     <--  此处修改

    ZPlainSqLite3.sqlite_key(Result0, password, Length(password));

end;[/code]

[b]二、修改ZDbcSqLite.pas[/b]
这个文件位于\src\dbc目录下

找到TZSQLiteConnection.Open()方法,作如下修改:
原始代码为:[code]procedure TZSQLiteConnection.Open;

var

  ErrorCode: Integer;

  ErrorMessage: PChar;

  LogMessage: string;

  SQL: string;

begin

  if not Closed then Exit;

  ErrorMessage := '';

  LogMessage := Format('CONNECT TO "%s" AS USER "%s"', [Database, User]);

  FHandle := FPlainDriver.Open(PChar(Database), 0, ErrorMessage);

  if FHandle = nil then

  begin

    CheckSQLiteError(FPlainDriver, SQLITE_ERROR, ErrorMessage,  lcConnect, LogMessage);

  end;

  DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);

  { Turn on encryption if requested }

  if StrToBoolEx(Info.Values['encrypted']) then

  begin

    ErrorCode := FPlainDriver.Key(FHandle, PChar(Password), StrLen(PChar(Password)));

    CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcConnect, 'SQLite.Key');

  end;

  try

    SQL := 'PRAGMA show_datatypes = ON';

    ErrorCode := FPlainDriver.Execute(FHandle, PChar(SQL),  nil, nil, ErrorMessage);

    CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcExecute, SQL);

{

         SQL := 'PRAGMA empty_result_callbacks = ON';

         ErrorCode := FPlainDriver.Execute(FHandle, PChar(SQL),

           nil, nil, ErrorMessage);

         CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcExecute, SQL);

}

    StartTransactionSupport;

  except

    FPlainDriver.Close(FHandle);

    FHandle := nil;

    raise;

  end;

  inherited Open;

end;[/code]

修改为:[code]procedure TZSQLiteConnection.Open;

var

  ErrorCode: Integer;

  ErrorMessage: PChar;

  LogMessage: string;

  SQL: string;

begin

  if not Closed then Exit;

  ErrorMessage := '';

  LogMessage := Format('CONNECT TO "%s" AS USER "%s"', [Database, User]);

  FHandle := FPlainDriver.Open(PChar(Database), 0, PChar(Password), ErrorMessage);           <--  此处修改

  if FHandle = nil then

  begin

    CheckSQLiteError(FPlainDriver, SQLITE_ERROR, ErrorMessage,  lcConnect, LogMessage);

  end;

  DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);

  { Turn on encryption if requested }

  if StrToBoolEx(Info.Values['encrypted']) then

  begin

    ErrorCode := FPlainDriver.Key(FHandle, PChar(Password), StrLen(PChar(Password)));

    CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcConnect, 'SQLite.Key');

  end;

  try

    SQL := 'PRAGMA show_datatypes = ON';

    ErrorCode := FPlainDriver.Execute(FHandle, PChar(SQL),  nil, nil, ErrorMessage);

    CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcExecute, SQL);



{

         SQL := 'PRAGMA empty_result_callbacks = ON';

         ErrorCode := FPlainDriver.Execute(FHandle, PChar(SQL),

           nil, nil, ErrorMessage);

         CheckSQLiteError(FPlainDriver, ErrorCode, ErrorMessage, lcExecute, SQL);

}



    StartTransactionSupport;

  except

    FPlainDriver.Close(FHandle);

    FHandle := nil;

    raise;

  end;

  inherited Open;

end;[/code[]



三、修改ZDbcSqliteUtils.pas

这个文件位于\src\dbc目录下



找到ConvertSQLiteTypeToSQLType()法,作如下修改:

原始代码为:[code]

function ConvertSQLiteTypeToSQLType(TypeName: string; var Precision: Integer;

  var Decimals: Integer): TZSQLType;

var

  P1, P2: Integer;

  Temp: string;

begin

  TypeName := UpperCase(TypeName);

  Result := stString;

  Precision := 0;

  Decimals := 0;



  P1 := Pos('(', TypeName);

  P2 := Pos(')', TypeName);

  if (P1 > 0) and (P2 > 0) then

  begin

    Temp := Copy(TypeName, P1 + 1, P2 - P1 - 1);

    TypeName := Copy(TypeName, 1, P1 - 1);

    P1 := Pos(',', Temp);

    if P1 > 0 then

    begin

      Precision := StrToIntDef(Copy(Temp, 1, P1 - 1), 0);

      Decimals := StrToIntDef(Copy(Temp, P1 + 1, Length(Temp) - P1), 0);

    end else

      Precision := StrToIntDef(Temp, 0);

  end;



  if StartsWith(TypeName, 'BOOL') then

    Result := stBoolean

  else if TypeName = 'TINYINT' then

    Result := stByte

  else if TypeName = 'SMALLINT' then

    Result := stShort

  else if TypeName = 'MEDIUMINT' then

    Result := stInteger

  else if StartsWith(TypeName, 'INT') then

    Result := stInteger

  else if TypeName = 'BIGINT' then

    Result := stLong

  else if StartsWith(TypeName, 'REAL') then

    Result := stDouble

  else if StartsWith(TypeName, 'FLOAT') then

    Result := stDouble

  else if (TypeName = 'NUMERIC') or (TypeName = 'DECIMAL')

    or (TypeName = 'NUMBER') then

  begin

   { if Decimals = 0 then

      Result := stInteger

    else} Result := stDouble;

  end

  else if StartsWith(TypeName, 'DOUB') then

    Result := stDouble

  else if TypeName = 'MONEY' then

    Result := stBigDecimal

  else if StartsWith(TypeName, 'CHAR') then

    Result := stString

  else if TypeName = 'VARCHAR' then

    Result := stString

  else if TypeName = 'VARBINARY' then

    Result := stBytes

  else if TypeName = 'BINARY' then

    Result := stBytes

  else if TypeName = 'DATE' then

    Result := stDate

  else if TypeName = 'TIME' then

    Result := stTime

  else if TypeName = 'TIMESTAMP' then

    Result := stTimestamp

  else if TypeName = 'DATETIME' then

    Result := stTimestamp

  else if Pos('BLOB', TypeName) > 0 then

    Result := stBinaryStream

  else if Pos('CLOB', TypeName) > 0 then

    Result := stAsciiStream

  else if Pos('TEXT', TypeName) > 0 then

    Result := stAsciiStream;



  if (Result = stInteger) and (Precision <> 0) then

  begin

    if Precision <= 2 then

      Result := stByte

    else if Precision <= 4 then

      Result := stShort

    else if Precision <= 9 then

      Result := stInteger

    else Result := stLong;

  end;



  if (Result = stString) and (Precision = 0) then

    Precision := 256;

end;[/code]

修改为:[code]function ConvertSQLiteTypeToSQLType(TypeName: string; var Precision: Integer;

  var Decimals: Integer): TZSQLType;

var

  P1, P2: Integer;

  Temp: string;

begin

  TypeName := UpperCase(TypeName);

  Result := stString;

  Precision := 0;

  Decimals := 0;



  P1 := Pos('(', TypeName);

  P2 := Pos(')', TypeName);

  if (P1 > 0) and (P2 > 0) then

  begin

    Temp := Copy(TypeName, P1 + 1, P2 - P1 - 1);

    TypeName := Copy(TypeName, 1, P1 - 1);

    P1 := Pos(',', Temp);

    if P1 > 0 then

    begin

      Precision := StrToIntDef(Copy(Temp, 1, P1 - 1), 0);

      Decimals := StrToIntDef(Copy(Temp, P1 + 1, Length(Temp) - P1), 0);

    end else

      Precision := StrToIntDef(Temp, 0);

  end;



  if StartsWith(TypeName, 'BOOL') then

    Result := stBoolean

  else if TypeName = 'TINYINT' then

    Result := stByte

  else if TypeName = 'SMALLINT' then

    Result := stShort

  else if TypeName = 'MEDIUMINT' then

    Result := stInteger

  else if StartsWith(TypeName, 'INT') then

    Result := stInteger

  else if TypeName = 'BIGINT' then

    Result := stLong

  else if StartsWith(TypeName, 'REAL') then

    Result := stDouble

  else if StartsWith(TypeName, 'FLOAT') then

    Result := stDouble

  else if (TypeName = 'NUMERIC') or (TypeName = 'DECIMAL')

    or (TypeName = 'NUMBER') then

  begin

   { if Decimals = 0 then

      Result := stInteger

    else} Result := stDouble;

  end

  else if StartsWith(TypeName, 'DOUB') then

    Result := stDouble

  else if TypeName = 'MONEY' then

    Result := stBigDecimal

  else if StartsWith(TypeName, 'CHAR') then

    Result := stString

  else if TypeName = 'VARCHAR' then

    Result := stString

  else if TypeName = 'VARBINARY' then

    Result := stBytes

  else if TypeName = 'BINARY' then

    Result := stBytes

  else if TypeName = 'DATE' then

    Result := stDate

  else if TypeName = 'TIME' then

    Result := stTime

  else if TypeName = 'TIMESTAMP' then

    Result := stTimestamp

  else if TypeName = 'DATETIME' then

    Result := stTimestamp

  else if Pos('BLOB', TypeName) > 0 then

    Result := stBinaryStream

  else if Pos('CLOB', TypeName) > 0 then

    Result := stAsciiStream

  else if Pos('TEXT', TypeName) > 0 then

    Result := stString;                                                 <--  此处修改



  if (Result = stInteger) and (Precision <> 0) then

  begin

    if Precision <= 2 then

      Result := stByte

    else if Precision <= 4 then

      Result := stShort

    else if Precision <= 9 then

      Result := stInteger

    else Result := stLong;

  end;



  if (Result = stString) and (Precision = 0) then

    Precision := 4096;                                               <--  此处修改

end;[/code]

四、保存修改,编译,安装
经过修改的Zeos即可支持加密的SQLite数据库,示例代码如下:[code]ZConnection1.Password := 'sa';

ZConnection1.Connect;

ZTable1.TableName := 'Employees';

ZTable1.Open;[/code]
 
本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号