Added support for asking destination filename in file transfer.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 19 Feb 2004 19:10:55 +0000 (19:10 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 19 Feb 2004 19:10:55 +0000 (19:10 +0000)
CHANGES
apps/irssi/src/silc/core/silc-servers.c
lib/silcclient/client_ftp.c
lib/silcclient/protocol.c
lib/silcclient/silcclient.h

diff --git a/CHANGES b/CHANGES
index 5a820180833372172fae7e3daf8376cd1dbea20f..fa7f18d328fe4e0ae4628b67e019e4b09ffd43ab 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+Fri Feb 19 21:09:22 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for asking the destination filename where
+         the downloaded file is saved in the file transfer.  Affected
+         files are lib/silccilent/silcclient.h, client_ftp.c.
+
 Wed Feb 18 02:46:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed error handling in resuming data processing.  Affected
index 0a952318950a5e0e638cc2c49688a137de416629..37a0b9eb6b40ac66be6ebc251c896a74afb865d5 100644 (file)
@@ -888,7 +888,8 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
 
       ret = silc_client_file_receive(silc_client, conn,
                                     silc_client_file_monitor, server, NULL,
-                                    server->current_session->session_id);
+                                    server->current_session->session_id,
+                                    NULL, NULL);
       if (ret != SILC_CLIENT_FILE_OK) {
        if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
          printformat_module("fe-common/silc", server, NULL,
@@ -919,7 +920,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       if (ftp->client_entry == client_entry && !ftp->filepath) {
        ret = silc_client_file_receive(silc_client, conn,
                                       silc_client_file_monitor, server,
-                                      NULL, ftp->session_id);
+                                      NULL, ftp->session_id, NULL, NULL);
        if (ret != SILC_CLIENT_FILE_OK) {
          if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
            printformat_module("fe-common/silc", server, NULL,
index 1073ae7fd99bb8e5adbf26ebb9de8c906b0e9ef2..4806cf622c068468214a919708623256d18d6e0f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -48,6 +48,8 @@ struct SilcClientFtpSessionStruct {
 
   SilcClientFileMonitor monitor;
   void *monitor_context;
+  SilcClientFileAskName ask_name;
+  void *ask_name_context;
   char *filepath;
   char *path;
 
@@ -329,7 +331,7 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
                          SILC_CLIENT_FILE_MONITOR_ERROR,
-                         SILC_CLIENT_FILE_ERROR, 0, 0,
+                         SILC_CLIENT_FILE_PERMISSION_DENIED, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
     return;
@@ -352,6 +354,37 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
                        session->filepath, session->monitor_context);
 }
 
+static void silc_client_ftp_ask_name(const char *filepath,
+                                    void *context)
+{
+  SilcClientFtpSession session = (SilcClientFtpSession)context;
+  SilcSFTPAttributesStruct attr;
+  char *remote_file = NULL;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (filepath) {
+    remote_file = session->filepath;
+    session->filepath = NULL;
+    silc_free(session->path);
+    session->path = NULL;
+    session->filepath = strdup(filepath);
+  } else {
+    remote_file = strdup(session->filepath);
+  }
+
+  /* Now open the file */
+  memset(&attr, 0, sizeof(attr));
+  silc_sftp_open(session->sftp, remote_file, SILC_SFTP_FXF_READ, &attr,
+                silc_client_ftp_open_handle, session);
+
+  /* Close the directory handle */
+  silc_sftp_close(session->sftp, session->dir_handle, NULL, NULL);
+  session->dir_handle = NULL;
+
+  silc_free(remote_file);
+}
+
 /* Returns the file name available for download. This is the downloader's
    function. */
 
@@ -361,7 +394,6 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
                                         void *context)
 {
   SilcClientFtpSession session = (SilcClientFtpSession)context;
-  SilcSFTPAttributesStruct attr;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -380,18 +412,21 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
     return;
   }
 
-  /* Now open the file */
-  memset(&attr, 0, sizeof(attr));
-  silc_sftp_open(sftp, name->filename[0], SILC_SFTP_FXF_READ, &attr,
-                silc_client_ftp_open_handle, session);
-
   /* Save the important attributes like filename and file size */
   session->filepath = strdup(name->filename[0]);
   session->filesize = name->attrs[0]->size;
 
-  /* Close the directory handle */
-  silc_sftp_close(sftp, session->dir_handle, NULL, NULL);
-  session->dir_handle = NULL;
+  /* If the path was not provided, ask from application where to save the
+     downloaded file. */
+  if (!session->path && session->ask_name) {
+    session->ask_name(session->client, session->conn, session->session_id,
+                     name->filename[0], silc_client_ftp_ask_name, session,
+                     session->ask_name_context);
+    return;
+  }
+
+  /* Start downloading immediately to current directory. */
+  silc_client_ftp_ask_name(NULL, session);
 }
 
 /* Returns the file handle after giving opendir command. This is the
@@ -917,7 +952,9 @@ silc_client_file_receive(SilcClient client,
                         SilcClientFileMonitor monitor,
                         void *monitor_context,
                         const char *path,
-                        SilcUInt32 session_id)
+                        SilcUInt32 session_id,
+                        SilcClientFileAskName ask_name,
+                        void *ask_name_context)
 {
   SilcClientFtpSession session;
   SilcBuffer keyagr, ftp;
@@ -948,6 +985,8 @@ silc_client_file_receive(SilcClient client,
 
   session->monitor = monitor;
   session->monitor_context = monitor_context;
+  session->ask_name = ask_name;
+  session->ask_name_context = ask_name_context;
   session->conn = conn;
   session->path = path ? strdup(path) : NULL;
 
index 4ff4582147e8aa00e241bd2588345066681d456a..1f89a4212be7b45b0ea24ec958a3fc83dffb6c37 100644 (file)
@@ -2,14 +2,13 @@
 
   protocol.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,9 +16,6 @@
   GNU General Public License for more details.
 
 */
-/*
- * Client side of the protocols.
- */
 /* $Id$ */
 
 #include "silcincludes.h"
index 94f67983f479e693b209b6323b67ed62bea6b6c5..d518c42b8531fa86c69525b0cb102f93b3169f8f 100644 (file)
@@ -654,7 +654,9 @@ typedef struct {
   /* Called to indicate that connection was disconnected to the server.
      The `status' may tell the reason of the disconnection, and if the
      `message' is non-NULL it may include the disconnection message
-     received from server. */
+     received from server. Application must not call the
+     silc_client_close_connection in this callback.  The 'conn' is also
+     invalid after this function returns back to library. */
   void (*disconnected)(SilcClient client, SilcClientConnection conn,
                       SilcStatus status, const char *message);
 
@@ -2456,6 +2458,54 @@ typedef void (*SilcClientFileMonitor)(SilcClient client,
                                      const char *filepath,
                                      void *context);
 
+/****f* silcclient/SilcClientAPI/SilcClientFileName
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientFileName)(SilcUInt32 session_id,
+ *                                       void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Completion callback for the SilcClientFileAskName callback function.
+ *    Application calls this to deliver the filepath and filename where
+ *    the downloaded file is to be saved.
+ *
+ ***/
+typedef void (*SilcClientFileName)(const char *filepath,
+                                  void *context);
+
+/****f* silcclient/SilcClientAPI/SilcClientFileAskName
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientFileAskName)(SilcClient client,
+ *                                          SilcClientConnection conn,
+ *                                          SilcUInt32 session_id,
+ *                                          const char *remote_filename,
+ *                                          SilcClientFileName completion,
+ *                                          void *completion_context,
+ *                                          void *context);
+ *
+ * DESCRIPTION
+ *
+ *    File name asking callback, that is called if it is given to the
+ *    silc_client_file_receive and the path given to that as argument was
+ *    NULL.  The library calls this to ask the filename and filepath to
+ *    where the file is to be saved.  The 'remote_filename' is the file
+ *    that is being downloaded.  Application must call the 'completion'
+ *    with 'completion_context' to continue with the file downloading.
+ *    It is not mandatory to provide this to the silc_client_file_receive.
+ *
+ ***/
+typedef void (*SilcClientFileAskName)(SilcClient client,
+                                     SilcClientConnection conn,
+                                     SilcUInt32 session_id,
+                                     const char *remote_filename,
+                                     SilcClientFileName completion,
+                                     void *completion_context,
+                                     void *context);
+
 /****f* silcclient/SilcClientAPI/silc_client_file_send
  *
  * SYNOPSIS
@@ -2521,7 +2571,9 @@ silc_client_file_send(SilcClient client,
  *                             SilcClientFileMonitor monitor,
  *                             void *monitor_context,
  *                             const char *path,
- *                             SilcUInt32 session_id);
+ *                             SilcUInt32 session_id,
+ *                             SilcClientFileAskName ask_name,
+ *                             void *ask_name_context);
  *
  * DESCRIPTION
  *
@@ -2530,9 +2582,11 @@ silc_client_file_send(SilcClient client,
  *    received in the `ftp' client operation function.  This will actually
  *    perform the key agreement protocol with the remote client before
  *    actually starting the file transmission.  The `monitor' callback
- *    will be called to monitor the transmission.  If `path' is non NULL
+ *    will be called to monitor the transmission.  If `path' is non-NULL
  *    the file will be saved into that directory.  If NULL the file is
- *    saved in the current working directory.
+ *    saved in the current working directory, unless the 'ask_name'
+ *    callback is non-NULL.  In this case the callback is called to ask
+ *    the path and filename from application.
  *
  *    If error will occur during the file transfer process the error
  *    status will be returned in the monitor callback.  In this case
@@ -2546,7 +2600,9 @@ silc_client_file_receive(SilcClient client,
                         SilcClientFileMonitor monitor,
                         void *monitor_context,
                         const char *path,
-                        SilcUInt32 session_id);
+                        SilcUInt32 session_id,
+                        SilcClientFileAskName ask_name,
+                        void *ask_name_context);
 
 /****f* silcclient/SilcClientAPI/silc_client_file_close
  *