Post a reply

Options
Add an Attachment

If you do not want to add an Attachment to your Post, please leave the Fields blank.

(maximum 10 MB; please compress large files; only common media, archive, text and programming file formats are allowed)

Options

Topic review

martin

Re: Running WinSCP with REBOL

Thanks for sharing this.
swhite

Running WinSCP with REBOL

I just found WinSCP last week and I love it. It solved a big problem for me involving sending files securely and automatically. The method I chose to control the operation is a scripting language called REBOL. It is not a popular language, so I thought that in the interest of spreading knowledge, I would post the program I wrote so locate all folders in a specified folder, send each folder to a secure ftp site, and delete the folder after sending it. It shows the technique of generating a command line to run WinSCP. The script below is a bit long, but it is written in a plodding manner that should make it easy to understand. Thank you. I apologize if this comes through as a mess.

REBOL [

    Title: "Securely send folders by sftp"
    Purpose: {Get the names of all the folders in a special transfer
    area.  Send them to a secure server and remove them.}
]

;; [---------------------------------------------------------------------------]
;; [ The purpose of this program is to identify all the files in the           ]
;; [ source folder, transmit them to a destination, and then delete them.      ]
;; [ We will send them with a secure ftp program that can be scripted.         ]
;; [ It appears that REBOL can't do sftp.                                      ]
;; [ The scriptable sftp program we use is at: https://winscp.net              ]
;; [                                                                           ]
;; [ The program uses the REBOL "call" function to call WinSCP (the sriptable  ]
;; [ sftp client) to send the files, and Powershell to remove the files.       ]
;; [ The reason it uses WinSCP is that REBOL can't do secure ftp, and the      ]
;; [ reason it uses Powershell to delete files is that it seems REBOL can't    ]
;; [ delete a folder without first deleting everything in it, and              ]
;; [ Powershell can simply with the "recurse" option.                          ]
;; [ It appears that the "call/wait" function does indeed wait until the       ]
;; [ called program is done, so there is no danger of trying to remove a       ]
;; [ folder before it has been sent.                                           ]
;; [                                                                           ]
;; [ In the original use scenario for this program, the data to be sent        ]
;; [ was in folders, and each folder was to be sent, recursively.              ]
;; [ WinSCP handles this very nicely.  The same syntax works for individual    ]
;; [ files, so while this program originally was used to send folders,         ]
;; [ it would work as-is (or maybe with some minor change) for individual      ]
;; [ files.                                                                    ]
;; [---------------------------------------------------------------------------]

;; [---------------------------------------------------------------------------]
;; [ Change the following items for your own installation.                     ]
;; [---------------------------------------------------------------------------]

SOURCE-DIR: %/C/OUTBOX/                ;; Folder of folders to be sent
SFTP-SERVER: "sft.servername.com"      ;; Destination server
USERID: "UserID"                       ;; Account on above server 
PASSWORD: "Password"                   ;; Password for above account
LOG-FILE-ID: %SendFolders.log          ;; Log what we do for auditing
LOG-FOLDER: %/SERVERNAME/TaskLogs/     ;; Send log here

;; [---------------------------------------------------------------------------]
;; [ HOME-DIR         Our starting folder because we will have to move.        ]
;; [ SENT-ITEM-LOCAL: The local-fomat name of the item we are going to send.   ]
;; [ BAT-FILE:        A generated DOS batch file to run WinSCP.                ]
;; [ PS1-FILE:        A generated Powershell script to remove folders.         ]
;; [ FILE-LIST:       A list of all the items we are about to send.            ]
;; [---------------------------------------------------------------------------]

HOME-DIR: what-dir                 
SENT-ITEM-LOCAL: none
BAT-FILE: ""
PS1-FILE: ""
FILE-LIST: []

;; [---------------------------------------------------------------------------]
;; [ Using a file/folder name from the list, generate its full name in         ]
;; [ a format suitable for the computer on which this program is running,      ]
;; [ which has to be a Windows computer since WinSCP runs on Windows.          ]
;; [---------------------------------------------------------------------------]

GENERATE-FILE-NAMES: func [
    SINGLE-FILE-ID
] [
    SENT-ITEM-LOCAL: to-local-file rejoin [
        to-string SOURCE-DIR
        to-string SINGLE-FILE-ID
    ]
]

;; [---------------------------------------------------------------------------]
;; [ After the local file name is generated, generate the batch file           ]
;; [ command that will run WinSCP.                                             ]
;; [---------------------------------------------------------------------------]

GENERATE-BATCH-FILE: does [
    BAT-FILE: copy ""
    BAT-FILE: rejoin [
        {winscp.com /command }
        {"open } USERID {:} PASSWORD {@} SFTP-SERVER {" }
        {"put } SENT-ITEM-LOCAL {" }
        {"close" }
        {"exit"}
    ]
]

;; [---------------------------------------------------------------------------]
;; [ After the local file name is generated, generate a Powershell command     ]
;; [ to remove the folder after it has been sent.                              ]
;; [---------------------------------------------------------------------------]

GENERATE-REMOVE-FILE: does [
    PS1-FILE: copy ""
    PS1-FILE: rejoin [
        {powershell -command }
        {"Remove-Item } SENT-ITEM-LOCAL { -recurse" }
    ]
]

;; [---------------------------------------------------------------------------]
;; [ Log a line of text with a date stamp.                                     ]
;; [---------------------------------------------------------------------------]

LOG-EVENT: func [
    LOG-LINE
] [
    write/append to-file rejoin [HOME-DIR LOG-FILE-ID] rejoin [
        now
        " "
        LOG-LINE
        newline
    ]
]

;; [---------------------------------------------------------------------------]
;; [ Go to the folder where we expect to find the folders to send.             ]
;; [ Get a list of all folder names currently in the source directory.         ]
;; [---------------------------------------------------------------------------]

LOG-EVENT "BOJ SendCaseFiles"
change-dir SOURCE-DIR
FILE-LIST: read %.
if equal? 0 length? FILE-LIST [
    LOG-EVENT "No items found to send."
]

;; [---------------------------------------------------------------------------]
;; [ For each item on the list,                                                ]
;; [ 1.  Generate the full name of the item in Windows format.                 ]
;; [ 2.  Generate the DOS command to send the item.                            ]
;; [ 3.  Generate the Powershell command to delete the item.                   ]
;; [ 4.  Send the item using the generated command.                            ]
;; [ 5.  Delete the item using the generated command.                          ]
;; [ Log the steps as we do them.                                              ]
;; [---------------------------------------------------------------------------]

foreach FILE-ID FILE-LIST [
    GENERATE-FILE-NAMES FILE-ID
    GENERATE-BATCH-FILE
    GENERATE-REMOVE-FILE
    LOG-EVENT replace copy BAT-FILE PASSWORD "???????"
    call/wait BAT-FILE
    LOG-EVENT rejoin [FILE-ID " sent."]
    LOG-EVENT PS1-FILE
    call/wait PS1-FILE
    LOG-EVENT rejoin [FILE-ID " removed."]
]

;; [---------------------------------------------------------------------------]
;; [ Finish the log for this run, and then send the log to a different         ]
;; [ area for viewing.  (Originally, this program was run on a secure server.) ]
;; [---------------------------------------------------------------------------]

LOG-EVENT "EOJ SendCaseFiles"
write to-file rejoin [LOG-FOLDER LOG-FILE-ID]
    read to-file rejoin [HOME-DIR LOG-FILE-ID]

;;Uncomment the "halt" for debugging.
;halt