serverthread.pas

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

PAS
1,289
字号
  if (ClientSocket <> nil) and ClientSocket.Connected then
    ClientSocket.Close;
end;

procedure TSSHServerThread.OnSrvError(Sender : TObject; ErrorCode : integer);
begin
  Log('Error ' + IntToStr(ErrorCode));
end;

procedure TSSHServerThread.OnSrvOpenShell(Sender: TObject; Conn: TElSSHTunnelConnection);
var
  Thread : TElSSHSubsystemThread;
begin
  Log('Shell opened');
  Thread := TElSSHSubsystemThread.Create(TElShellSSHSubsystemHandler, Conn, true);
  Thread.OnTerminate := OnThreadTerminate;
  Thread.FreeOnTerminate := true;
  FSubsystemThreads.Add(Thread);
  Thread.Resume;
  ChangeState(ssActive);
end;

procedure TSSHServerThread.OnSrvOpenCommand(Sender: TObject; Conn: TElSSHTunnelConnection;
  const Command: string);
var
  Thread : TElSSHSubsystemThread;
begin
  Log('Command opened: ' + Command);
  Thread := TElSSHSubsystemThread.Create(TElShellSSHSubsystemHandler, Conn, true);
  TElShellSSHSubsystemHandler(Thread.Handler).Command := Command;
  Thread.OnTerminate := OnThreadTerminate;
  Thread.FreeOnTerminate := true;
  FSubsystemThreads.Add(Thread);
  Thread.Resume;
  ChangeState(ssActive);
end;

procedure TSSHServerThread.OnSrvOpenSubsystem(Sender: TObject; Conn: TElSSHTunnelConnection;
  const Subsystem: string);
var
  Thread: TElSSHSubsystemThread;
begin
  if (lowercase(Subsystem) = 'sftp') and (Settings.AllowSFTP) then
  begin
    Log('Subsystem (' + Subsystem + ') opened');
    Thread := TElSSHSubsystemThread.Create(TElSFTPSSHSubsystemHandler, Conn, true);
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnOpen := OnSftpOpen;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnClose := OnSftpClose;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnCloseHandle := OnSftpCloseHandle;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnCreateDirectory := OnSftpCreateDirectory;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnFindClose := OnSftpFindClose;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnFindFirst := OnSftpFindFirst;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnFindNext := OnSftpFindNext;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnOpenFile := OnSftpOpenFile;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnReadFile := OnSftpReadFile;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnRemove := OnSftpRemove;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnRenameFile := OnSftpRenameFile;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnRequestAbsolutePath := OnSftpRequestAbsolutePath;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnRequestAttributes := OnSftpRequestAttributes;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnRequestAttributes2 := OnSftpRequestAttributes2;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnSetAttributes := OnSftpSetAttributes;
    TElSFTPSSHSubsystemHandler(Thread.Handler).Server.OnWriteFile := OnSftpWriteFile;
    FSubsystemThreads.Add(Thread);
    Thread.Resume;
    ChangeState(ssActive);
  end
  else begin
    Log('Subsystem opened: ' + Subsystem);
    ChangeState(ssActive);
  end;
end;

procedure TSSHServerThread.OnSrvBeforeOpenClientForwarding(Sender: TObject;
  const DestHost: string; DestPort: integer; const SrcHost: string; SrcPort: integer;
  var Accept: boolean);
begin
  // checking whether user is allowed to forward connections
  // ...
  Accept := true;
end;

procedure TSSHServerThread.OnSrvOpenClientForwarding(Sender: TObject;
  Connection: TElSSHTunnelConnection; const DestHost: string; DestPort: integer;
  const SrcHost : string; SrcPort: integer);
var
  Thread : TElSSHSubsystemThread;
begin
  Log('Establishing client TCP forwarding to ' + DestHost + ':' + IntToStr(DestPort));
  Thread := TElSSHSubsystemThread.Create(TElClientTCPForwardingSSHSubsystemHandler,
    Connection, true);
  TElClientTCPForwardingSSHSubsystemHandler(Thread.Handler).Host := DestHost;
  TElClientTCPForwardingSSHSubsystemHandler(Thread.Handler).Port := DestPort;
  Thread.OnTerminate := OnThreadTerminate;
  Thread.FreeOnTerminate := true;
  FSubsystemThreads.Add(Thread);
  Thread.Resume;
  ChangeState(ssActive);
end;

procedure TSSHServerThread.OnSrvOpenServerForwarding(Sender: TObject;
  Connection: TElSSHTunnelConnection);
begin
  TSSHServerForwardingThread(Connection.Data).Run(Connection);
  ChangeState(ssActive);
end;

procedure TSSHServerThread.OnSrvServerForwardingFailed(Sender: TObject; Data: pointer);
begin
  TSSHServerForwardingThread(Data).Handler.Terminate;
end;

procedure TSSHServerThread.OnSrvServerForwardingRequest(Sender: TObject;
  const Address: string; Port : integer; var Accept : boolean; var RealPort: integer);
var
  ListeningSocket : TServerSocket;
begin
  ListeningSocket := TServerSocket.Create(nil);
  try
    ListeningSocket.ServerType := stThreadBlocking;
    ListeningSocket.OnGetThread := OnForwardingSocketGetThread;
    ListeningSocket.Port := Port;
    ListeningSocket.Open;
    FServerForwardings.Add(ListeningSocket);
    Accept := true;
  except
    ListeningSocket.Free;
    Accept := false;
  end;
end;

procedure TSSHServerThread.OnSrvServerForwardingCancel(Sender: TObject;
  const Address: string; Port : integer);
var
  I : integer;
begin
  for I := 0 to FServerForwardings.Count - 1 do
  begin
    if (TServerSocket(FServerForwardings[I]).Socket.LocalAddress = Address) and
      (TServerSocket(FServerForwardings[I]).Socket.LocalPort = Port) then
    begin
      TServerSocket(FServerForwardings[I]).Close;
      TServerSocket(FServerForwardings[I]).Free;
      FServerForwardings.Delete(I);
    end;
  end;
end;

procedure TSSHServerThread.OnForwardingSocketGetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
begin
  SocketThread := TSSHServerForwardingThread.Create(ClientSocket);
  FSSHServer.OpenServerForwarding(ClientSocket.ServerWinSocket.LocalAddress,
    ClientSocket.ServerWinSocket.LocalPort,
    ClientSocket.RemoteAddress, ClientSocket.RemotePort, SocketThread);
end;

procedure TSSHServerThread.OnThreadTerminate(Sender: TObject);
begin
  FSubsystemThreads.Remove(Sender);
  ChangeState(ssActive);
end;

procedure TSSHServerThread.DoLog;
begin
  FOnLog(Self, FCurrLogLine);
end;

procedure TSSHServerThread.DoAuthAttempt;
begin
  FCurrBool := false;
  FOnAuthAttempt(Self, FCurrUsername, FCurrAuthType, FCurrBool);
end;

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

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

procedure TSSHServerThread.DoConnClosed;
begin
  if Assigned(FOnConnClosed) then
    FOnConnClosed(Self);
end;

procedure TSSHServerThread.DoRefreshInfo;
begin
  if Assigned(FOnRefreshInfo) then
    FOnRefreshInfo(Self);
end;

procedure TSSHServerThread.Log(const S : string);
begin
  if Assigned(FOnLog) then
  begin
    FCurrLogLine := S;
    Synchronize(DoLog);
  end;
end;

function TSSHServerThread.GetTunnelCount: integer;
var
  I : integer;
begin
  Result := FSubsystemThreads.Count;
  for I := 0 to FServerForwardings.Count - 1 do
    Result := Result + TServerSocket(FServerForwardings[I]).Socket.ActiveConnections;
end;

procedure TSSHServerThread.ChangeState(NewState: TSSHServerState);
begin
  FState := NewState;
  Synchronize(DoRefreshInfo);
end;
// ----------------------------------------------------------------------------

function TSSHServerThread.FileInfoFromRec(r: TSearchRec): TElSftpFileInfo;
var
  inf: TElSftpFileInfo;
begin
  inf := TElSftpFileInfo.Create;
  if SftpVersion > 3 then
  begin
    inf.Name := ConvertToUTF8String(r.Name);
//    inf.LongName := Utf8Encode(r.Name);
  end
  else
  begin
    inf.Name := r.Name;
    inf.LongName := r.Name;
  end;
  inf.Attributes.Size := r.size;
  if (r.Attr and faDirectory) <> 0 then
  begin
    inf.Attributes.Directory := true;
    inf.Attributes.FileType := ftDirectory;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_DIRECTORY);
  end
  else
  begin
    inf.Attributes.Directory := false;
    inf.Attributes.FileType := ftFile;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_REGULAR);
  end;
  inf.Attributes.UserRead := true;
  inf.Attributes.GroupRead := true;
  inf.Attributes.OtherRead := true;
  if (r.Attr and faReadOnly) = 0 then
  begin
    inf.Attributes.UserWrite := true;
    inf.Attributes.GroupWrite := true;
    inf.Attributes.OtherWrite := true;
  end;
  inf.Attributes.MTime := FileDateToDateTime(r.Time);
  inf.Attributes.CTime := inf.Attributes.MTime;
  inf.Attributes.ATime := inf.Attributes.MTime;
  result := inf;
end;

function SizeOfFile(const n: string): int64;
var
  f: TFileStream;
begin
  try
    f := TFileStream.Create(n, fmOpenRead);
    try
      Result := f.Size;
    finally
      f.Free;
    end;
  except
    result := -1;
  end;
end;

function replace(var Str: string; const SourceString, DestString: string): boolean;
var
  i: integer;
begin
  i := pos(SourceString, Str);
  if i = 0 then
  begin
    Result := false;
    exit;
  end;
  Delete(Str, i, Length(SourceString));
  if Length(DestString)>0 then
    Insert(DestString, Str, i);
  Result := true;
end;

function TSSHServerThread.StatFile(name: string): TElSftpFileInfo;
var
  inf: TElSftpFileInfo;
  a: integer;

begin
  result := nil;
  inf := TElSftpFileInfo.Create;
  if SftpVersion > 3 then
    name := ConvertFromUTF8String(name);
  while replace(name, '/', '\') do ;
  inf.Name := ExtractFileName(name);
  inf.LongName := inf.Name;
  a := FileGetAttr(name);
  if (a = -1) then
    Exit;
  if (a and faDirectory) <> 0 then
  begin
    inf.Attributes.Directory := true;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_DIRECTORY);
  end
  else
  begin
    inf.Attributes.Directory := false;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_REGULAR);
    inf.Attributes.Size := SizeOfFile(name);
    if inf.Attributes.Size < 0 then
    begin
      inf.Free;
      exit;
    end;
  end;
  inf.Attributes.UserRead := true;
  inf.Attributes.GroupRead := true;
  inf.Attributes.OtherRead := true;
  if (a and faReadOnly) = 0 then
  begin
    inf.Attributes.UserWrite := true;
    inf.Attributes.GroupWrite := true;
    inf.Attributes.OtherWrite := true;
  end;
  inf.Attributes.MTimeCardinal := FileAge(name);
  inf.Attributes.ATimeCardinal := inf.Attributes.MTimeCardinal;
  result := inf;
end;


function TSSHServerThread.StatOpenFile(Data : pointer): TElSftpFileInfo;
{var
  inf: TElSftpFileInfo;
  a: integer;
  hs: string;}
begin
(*
  inf := TElSftpFileInfo.Create;
  hs := h.path;
  if SftpVersion > 3 then
    hs := ConvertFromUTF8String(hs);

  while replace(hs, '/', '\') do ;
  inf.Name := ExtractFileName(ConvertToUTF8String(hs));
  inf.LongName := inf.Name;
  a := FileGetAttr(hs);
  if (a and faDirectory) <> 0 then
  begin
    inf.Attributes.Directory := true;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_DIRECTORY);
  end
  else
  begin
    inf.Attributes.Directory := false;
//    inf.Attributes.FileType := TSBSftpFileType(SSH_FILEXFER_TYPE_REGULAR);
    inf.Attributes.Size := h.fil.Size;
  end;
  inf.Attributes.UserRead := true;
  inf.Attributes.GroupRead := true;
  inf.Attributes.OtherRead := true;
  if (a and faReadOnly) = 0 then
  begin
    inf.Attributes.UserWrite := true;
    inf.Attributes.GroupWrite := true;
    inf.Attributes.OtherWrite := true;
  end;
  inf.Attributes.MTimeCardinal := FileGetDate(h.fil.Handle);
  inf.Attributes.ATimeCardinal := inf.Attributes.MTimeCardinal;
  result := inf;
  *)
end;

function rpos(c: widechar; s: widestring): integer;
var
  i: integer;
begin
  result := -1;
  i := Length(s);
  while i > 0 do
    if s[i] = c then
    begin
      result := i;
      break;
    end
    else
      dec(i);
end;

function UpDir(p: widestring): widestring;
var
  i: integer;
begin
  i := rpos('/', p);
  if i < Length(p) then
    result := copy(p, 1, i - 1)
  else
    result := p;
end;

function ResolveDots(p: widestring): widestring;
var
  d, us, hu: widestring;
  i: integer;
begin
  d := '';
  if (Length(p) > 1) and (p[2] = ':') then
  begin
    d := copy(p, 1, 2);
    delete(p, 1, 2);
  end;
  i := pos('/', p);
  us := '';
  while true do
  begin

⌨️ 快捷键说明

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