serverthread.pas

来自「著名的SecureBlackBox控件完整源码」· PAS 代码 · 共 1,275 行 · 第 1/3 页

PAS
1,275
字号
  end;
  inf.Attributes.UserRead := true;
  inf.Attributes.GroupRead := true;
  inf.Attributes.OtherRead := true;
  if (r.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  begin
    inf.Attributes.UserWrite := true;
    inf.Attributes.GroupWrite := true;
    inf.Attributes.OtherWrite := true;
  end;
  { begin JPM modifications }
  inf.Attributes.IncludedAttributes := [saPermissions, saSize];
  //Note that that we do things this way because we want the date in GMT while
  //Borland's TSearchRec itself only has the time converted to local time.
  //You can also get more information from the original Win32_FIND_DATA
  inf.Attributes.MTime := FileTimeToTDateTime(r.ftLastWriteTime);
  inf.Attributes.CTime := FileTimeToTDateTime(r.ftCreationTime);
  inf.Attributes.ATime := FileTimeToTDateTime(r.ftLastAccessTime);
  inf.Attributes.AttribBits :=  Win32AttrToSFTPAttr(R.dwFileAttributes);
  inf.Attributes.IncludedAttributes := inf.Attributes.IncludedAttributes +
    [saATime, saMTime, saCTime,saAttribBits ];
  { end JPM modifications }
  result := inf;
end;

function TSSHServerThread.StatFile(name: string): TElSftpFileInfo;
var
  FindData : WIN32_FIND_DATA;
  H : THandle;
begin
  result := nil;
  if SftpVersion > 3 then
    name := ConvertFromUTF8String(name);
  // converting slashes to backslashes as we are on Win32 system
  while replace(name, '/', '\') do ;
  // removing double slashes
  while replace(name, '\\', '\') do ;
  if CompareText(Name, 'C:\') = 0 then
  begin
    // creating stub for root directory
    FillChar(FindData, SizeOf(FindData), 0);
    FindData.dwFileAttributes := FILE_ATTRIBUTE_DIRECTORY;
    StrPCopy(FindData.cFileName, 'C:\');
    result := FileInfoFromRec(FindData);
  end
  else
  begin
    H := FindFirstFile(PChar(Name), FindData);
    if H <> INVALID_HANDLE_VALUE then
    begin
      result := FileInfoFromRec(FindData);
      FindClose(H);
    end;
  end;
end;

function TSSHServerThread.StatOpenFile(Data : pointer): TElSftpFileInfo;
var
  FileInfo : BY_HANDLE_FILE_INFORMATION;
  FindData : WIN32_FIND_DATA;
begin
  if GetFileInformationByHandle(TFileStream(Data).Handle, FileInfo) then
  begin
    // copying file information to the temporary structure
    FillChar(FindData, SizeOf(FindData), 0);
    FindData.dwFileAttributes := FileInfo.dwFileAttributes;
    Move(FileInfo.ftCreationTime, FindData.ftCreationTime, SizeOf(FindData.ftCreationTime));
    Move(FileInfo.ftLastAccessTime, FindData.ftLastAccessTime, SizeOf(FindData.ftLastAccessTime));
    Move(FileInfo.ftLastWriteTime, FindData.ftLastWriteTime, SizeOf(FindData.ftLastWriteTime));
    FindData.nFileSizeHigh := FileInfo.nFileSizeHigh;
    FindData.nFileSizeLow := FileInfo.nFileSizeLow;
    Result := FileInfoFromRec(FindData);
  end
  else
    Result := nil;
end;

procedure TSSHServerThread.OnSftpOpen(Sender: TObject);
begin
  SftpVersion := TElSFTPServer(Sender).ServerVersion;
end;

procedure TSSHServerThread.OnSftpCloseHandle(Sender: TObject; Data : pointer;
  var ErrorCode: integer; var Comment: string);
begin
  TFileStream(Data).Free;
  ErrorCode := 0;
  Comment := '';
end;

procedure TSSHServerThread.OnSftpCreateDirectory(Sender: TObject;
  const Path: string; Attributes: TElSftpFileAttributes;
  var ErrorCode: integer; var Comment: string);
var
  p: string;
begin
  Comment := '';
  ErrorCode := SSH_FX_OK;
  p := FormRealPath(Path, FCurrentDir);
{$I-}
  MkDir('C:\' + p);
  if IOResult = 0 then
    exit;
{$I+}
  Comment := 'Can''t create directory';
  ErrorCode := SSH_FX_FAILURE;
end;

procedure TSSHServerThread.OnSftpFindClose(Sender: TObject; Data : pointer;
  var ErrorCode: integer; var Comment: string);
begin
  SysUtils.FindClose(PSearchRec(Data)^);
  Dispose(PSearchRec(Data)); 
  ErrorCode := SSH_ERROR_OK;
end;

procedure TSSHServerThread.DoAuthPublicKey;
begin
  FCurrBool := false;
  FOnAuthPublicKey(Self, FCurrUsername, FCurrKey, FCurrBool);
end;

procedure TSSHServerThread.DoFurtherAuthNeeded;
begin
  FCurrBool := false;
  FOnFurtherAuthNeeded(Self, FCurrUsername, FCurrBool);
  FSSHServer.AuthenticationTypes := FSSHServer.AuthenticationTypes and not AuthAllTypes;
end;

procedure TSSHServerThread.OnSftpFindFirst(Sender: TObject; const Path: string;
  var Data : pointer; Info: TElSftpFileInfo; var ErrorCode: integer; var Comment: string);
var
  i: TElSftpFileInfo;
  p: string;
  Rec : PSearchRec;
begin
  p := FormRealPath(Path, FCurrentDir);
  if not DirectoryExists('C:' + p) then
  begin
    Comment := 'Invalid directory path';
    if SftpVersion < 3 then
      ErrorCode := SSH_FX_FAILURE
    else
      ErrorCode := SSH_FX_NO_SUCH_FILE;
    exit;
  end;
  Comment := '';

  New(Rec);
  ErrorCode := FindFirst('C:' + p + '\*.*', faAnyFile, Rec^);
  if ErrorCode = 0 then
  begin
    i := FileInfoFromRec(Rec^.FindData);
    i.CopyTo(Info);
    i.Free;
    ErrorCode := 0;
    Data := Rec;
    Comment := '';
  end
  else
  begin
    ErrorCode := SSH_FX_EOF;
    Comment := 'No files';
  end;
end;

procedure TSSHServerThread.OnSftpFindNext(Sender: TObject; Data : pointer;
  Info: TElSftpFileInfo; var ErrorCode: integer; var Comment: string);
var
  i: TElSftpFileInfo;
  Rec : PSearchRec;
begin
  Rec := Data;
  ErrorCode := FindNext(Rec^);
  if ErrorCode = 0 then
  begin
    i := FileInfoFromRec(Rec^.FindData);
    i.CopyTo(Info);
    i.Free;
    ErrorCode := 0;
    Comment := '';
  end
  else
  begin
    ErrorCode := SSH_FX_EOF;
    Comment := 'No files';
  end;
end;

procedure TSSHServerThread.OnSftpOpenFile(Sender: TObject; const Path: string;
  Modes: TSBSftpFileOpenModes; Access: TSBSftpFileOpenAccess;
  DesiredAccess: Cardinal; Attributes: TElSftpFileAttributes; var Data: pointer;
  var ErrorCode: integer; var Comment: string);
var
  p: string;
  md: integer;
begin
  p := FormRealPath(Path, FCurrentDir);
  p := 'C:\' + p;
  md := 0;

  if ((fmCreate in Modes) and (fmTruncate in Modes)) then
    md := Classes.fmCreate
  else
    if ((fmCreate in Modes) and (fmExcl in Modes)) then
    begin
      if FileExists(p) then
      begin
        Comment := 'Can''t open file';
        if SftpVersion > 2 then
          ErrorCode := SSH_FX_FILE_ALREADY_EXISTS
        else
          ErrorCode := SSH_FX_FAILURE;
      end
      else
        md := Classes.fmCreate;
    end
    else
      if (fmCreate in Modes) then
      begin
        if FileExists(p) then
          md := fmOpenReadWrite
        else
          md := Classes.fmCreate;
      end
      else
        if (fmAppend in Modes) then
          md := fmOpenReadWrite
        else
          if ((fmRead in Modes) and (fmWrite in Modes)) then
            md := fmOpenReadWrite
          else
            if (fmRead in Modes) then
              md := fmOpenRead
            else
              if (fmWrite in Modes) then
                md := fmOpenWrite
              else
                md := fmOpenReadWrite;
  try
    Data := TFileStream.Create(p, md);
    Comment := '';
    ErrorCode := SSH_FX_OK;
  except
    Comment := 'Can''t open file';
    ErrorCode := SSH_FX_FAILURE;
    exit;
  end;
  if (fmAppend in Modes) then
    TFileStream(Data).Position := TFileStream(Data).Size;
end;

procedure TSSHServerThread.OnSftpReadFile(Sender: TObject;
  Data : pointer; Offset: Int64; Buffer: Pointer; Count: integer;
  var Read, ErrorCode: integer; var Comment: string);
begin
  Comment := '';
  ErrorCode := 0;
  if Offset >= TFileStream(Data).Size then
  begin
    Comment := 'Reading beyond end of file';
    ErrorCode := SSH_FX_EOF;
    exit;
  end;
  TFileStream(Data).Position := Offset;
  try
    Read := TFileStream(Data).Read(Buffer^, Count);
  except
    on E : Exception do
    begin
      Comment := 'File read error: ' + E.Message;
      ErrorCode := SSH_FX_FAILURE;
      Read := 0;
    end;
  end;
end;

procedure TSSHServerThread.OnSftpRemove(Sender: TObject;
  const Path: string; var ErrorCode: integer; var Comment: string);
var
  p: string;
begin
  p := FormRealPath(Path, FCurrentDir);
  p := 'C:\' + p;
  ErrorCode := 0;
  Comment := '';
  if DirectoryExists(p) then
  begin
    if RemoveDir(p) then
      exit;
    ErrorCode := SSH_FX_FAILURE;
    Comment := 'Can''t remove directory. May be it isn''t empty?';
  end
  else
    if FileExists(p) then
    begin
      if SysUtils.DeleteFile(p) then
        exit;
      ErrorCode := SSH_FX_FAILURE;
      Comment := 'Can''t remove file';
    end
    else
    begin
      if SftpVersion < 3 then
        ErrorCode := SSH_FX_FAILURE
      else
        ErrorCode := SSH_FX_NO_SUCH_PATH;
      Comment := 'Invalid file or directory path';
    end;
end;

procedure TSSHServerThread.OnSftpRenameFile(Sender: TObject; const OldPath,
  NewPath: string; Flags : TSBSftpRenameFlags; var ErrorCode: integer; var Comment: string);
var
  p, p2: string;
begin
  p := 'C:\' + FormRealPath(OldPath, FCurrentDir);
  p2 := 'C:\' + FormRealPath(NewPath, FCurrentDir);
  Comment := '';
  ErrorCode := 0;
  if not RenameFile(p, p2) then
  begin
    Comment := 'Can''t rename file or directory';
    ErrorCode := SSH_FX_FAILURE;
  end;
end;

procedure TSSHServerThread.OnSftpRequestAbsolutePath(Sender: TObject;
  const Path: string; var AbsolutePath: string; Control : TSBSftpRealpathControl;
  ComposePath : TStringList; var ErrorCode: integer;
  var Comment: string);
begin
  Comment := '';
  ErrorCode := 0;
  AbsolutePath := FormRealPath(Path, FCurrentDir);
end;

procedure TSSHServerThread.OnSftpRequestAttributes(Sender: TObject;
  const Path: string; FollowSymLinks: boolean;
  Attributes: TElSftpFileAttributes; var ErrorCode: integer;
  var Comment: string);
var
  i: TElSftpFileInfo;
  LPath : String;
begin
  Comment := '';
  ErrorCode := 0;
  // JPM modifications
  LPath :=  'C:\' + FormRealPath(Path, FCurrentDir);
  i := StatFile(LPath);
  // end modifications
  if (i <> nil) then
  begin
    i.Attributes.CopyTo(Attributes);
    i.Free;
  end
  else
  begin
    ErrorCode := SSH_ERROR_NO_SUCH_FILE;
    Comment := 'No such file or directory';
  end;
end;

procedure TSSHServerThread.OnSftpRequestAttributes2(Sender: TObject;
  Data: pointer; Attributes: TElSftpFileAttributes;
  var ErrorCode: integer; var Comment: string);
var
  Info : TElSftpFileInfo;
begin
  Comment := '';
  ErrorCode := 0;
  Info := StatOpenFile(Data);
  if Info <> nil then
  begin
    Info.Attributes.CopyTo(Attributes);
    FreeAndNil(Info);
  end
  else
  begin
    ErrorCode := SSH_ERROR_INVALID_HANDLE;
    Comment := 'Invalid handle';
  end;
end;

procedure TSSHServerThread.OnSftpWriteFile(Sender: TObject;
  Data : pointer; Offset: Int64; Buffer: Pointer; Count: integer;
  var ErrorCode: integer; var Comment: string);
var
  l: integer;
begin
  Comment := '';
  ErrorCode := 0;
  TFileStream(Data).Position := Offset;
  l := TFileStream(Data).Write(Buffer^, Count);
  if l <> Count then
  begin
    Comment := 'File write error';
    ErrorCode := SSH_FX_FAILURE;
  end;
end;

procedure TSSHServerThread.OnSrvFurtherAuthNeeded(Sender: TObject; const
    Username: string; var Needed: boolean);
begin
  if Assigned(FOnFurtherAuthNeeded) then
  begin
    FCurrUsername := Username;
    FUsername := Username;
    Synchronize(DoFurtherAuthNeeded);
    Needed := FCurrBool;
  end
  else
    Needed := false;
end;

procedure TSSHServerThread.DoAuthKeyboard;
var
  FCP: boolean;
begin
  FCurrBool := false;
  FOnAuthKeyboard(Self, FCurrUsername, FCurrPassword, FCurrBool, FCP);
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?