/*
 * Copyright (c) 2001  Lucas Fisher       <ljfisher@purdue.edu>
 * Copyright (c) 2009  Andreas Schneider  <mail@cynapses.org>
 * Copyright (c) 2020  Martin Sandsmark   <martin@sandsmark.ninja>
 *                     KDE2 port
 * Copyright (c) 2022  Mavridis Philippe  <mavridisf@gmail.com>
 *                     Trinity port
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License (LGPL) as published by the Free Software Foundation;
 * either version 2 of the License, or (at your option) any later
 * version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef __tdeio_sftp_h__
#define __tdeio_sftp_h__

#include <kurl.h>
#include <tdeio/global.h>
#include <tdeio/slavebase.h>
#include <kdebug.h>
#include <stdint.h>

#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <libssh/callbacks.h>

// How big should each data packet be? Definitely not bigger than 64kb or
// you will overflow the 2 byte size variable in a sftp packet.
#define MAX_XFER_BUF_SIZE 60 * 1024
#define TDEIO_SFTP_DB 7120


#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 7, 90)
#define TDEIO_SSH_KNOWN_HOSTS_OK        SSH_SERVER_KNOWN_OK
#define TDEIO_SSH_KNOWN_HOSTS_OTHER     SSH_SERVER_FOUND_OTHER
#define TDEIO_SSH_KNOWN_HOSTS_CHANGED   SSH_SERVER_KNOWN_CHANGED
#define TDEIO_SSH_KNOWN_HOSTS_NOT_FOUND SSH_SERVER_FILE_NOT_FOUND
#define TDEIO_SSH_KNOWN_HOSTS_UNKNOWN   SSH_SERVER_NOT_KNOWN
#define TDEIO_SSH_KNOWN_HOSTS_ERROR     SSH_SERVER_ERROR

#else
#define TDEIO_SSH_KNOWN_HOSTS_OK        SSH_KNOWN_HOSTS_OK
#define TDEIO_SSH_KNOWN_HOSTS_OTHER     SSH_KNOWN_HOSTS_OTHER
#define TDEIO_SSH_KNOWN_HOSTS_CHANGED   SSH_KNOWN_HOSTS_CHANGED
#define TDEIO_SSH_KNOWN_HOSTS_NOT_FOUND SSH_KNOWN_HOSTS_NOT_FOUND
#define TDEIO_SSH_KNOWN_HOSTS_UNKNOWN   SSH_KNOWN_HOSTS_UNKNOWN
#define TDEIO_SSH_KNOWN_HOSTS_ERROR     SSH_KNOWN_HOSTS_ERROR
#endif

namespace TDEIO {
  class AuthInfo;
}

class sftpProtocol : public TDEIO::SlaveBase
{

public:
  sftpProtocol(const TQCString &pool_socket, const TQCString &app_socket);
  virtual ~sftpProtocol();
  virtual void setHost(const TQString& h, int port, const TQString& user, const TQString& pass) override;
  virtual void get(const KURL& url) override;
  virtual void listDir(const KURL& url)  override;
  virtual void mimetype(const KURL& url) override;
  virtual void stat(const KURL& url) override;
  virtual void put(const KURL& url, int permissions, bool overwrite, bool resume) override;
  virtual void copy(const KURL &src, const KURL &dest, int permissions, bool overwrite) override;
  virtual void closeConnection() override;
  virtual void slave_status() override;
  virtual void del(const KURL &url, bool isfile) override;
  virtual void chmod(const KURL& url, int permissions) override;
  virtual void symlink(const TQString& target, const KURL& dest, bool overwrite) override;
  virtual void rename(const KURL& src, const KURL& dest, bool overwrite) override;
  virtual void mkdir(const KURL& url, int permissions) override;
  virtual void openConnection() override;

  // libssh authentication callback (note that this is called by the
  // global ::auth_callback() call.
  int auth_callback(const char *prompt, char *buf, size_t len,
                    int echo, int verify, void *userdata);

  // libssh logging callback (note that this is called by the
  // global ::log_callback() call.
  void log_callback(ssh_session session, int priority, const char *message,
                    void *userdata);


private: // Private variables
  void statMime(const KURL &url);
  void closeFile();
  /** True if ioslave is connected to sftp server. */
  bool mConnected;

  /** Host we are connected to. */
  TQString mHost;

  /** Port we are connected to. */
  int mPort;

  /** The ssh session for the connection */
  ssh_session mSession;

  /** The sftp session for the connection */
  sftp_session mSftp;

  /** Username to use when connecting */
  TQString mUsername;

  /** User's password */
  TQString mPassword;

  /** The open file */
  sftp_file mOpenFile;

  /** The open URL */
  KURL mOpenUrl;

  ssh_callbacks mCallbacks;

  /** Version of the sftp protocol we are using. */
  int sftpVersion;

  //struct Status
  //{
  //  int code;
  //  TDEIO::filesize_t size;
  //  TQString text;
  //};

  TDEIO::AuthInfo *pubKeyInfo;

private: // private methods

  int authenticateKeyboardInteractive(TDEIO::AuthInfo &info);
  void clearPubKeyAuthInfo();

  void reportError(const KURL &url, const int err);

  bool createUDSEntry(const TQString &filename, const TQByteArray &path,
      TDEIO::UDSEntry &entry, short int details);

  TQString canonicalizePath(const TQString &path);
};

#endif