ftp module

Started by cormullion, April 07, 2008, 04:58:06 AM

Previous topic - Next topic

cormullion

I've put a version of an alternative ftp module up at



http://unbalanced-parentheses.nfshost.com/downloads/ftp.lsp">//http://unbalanced-parentheses.nfshost.com/downloads/ftp.lsp



Is it good enough yet to go into the http://newlisp.nfshost.com/modules/">//http://newlisp.nfshost.com/modules/?



Tim's added some cool stuff...

Lutz

#1
The code is nice, very readable, and easy to understand. But perhaps we need more documentation explaining the usage of FTP:config and explaining the possibility of either doing the file transfer in just one function call or with several function calles explicitly connecting etc., showing which functions are used and in what sequence etc, with a simple example.



Perhaps Tim can test it too, so we have at least tried it on two different servers?

cormullion

#2
Cool - thanks Lutz. I'll see what I can do tomorrow...



Tim and I have tested it a bit - we need some additional servers to test.

Tim Johnson

#3
I've written an application that will make use of mftp and I plan to test

it against one other server tomorrow - at least and maybe more, given

time.



I'm still getting my "feet wet" with newlispdoc and still learning Lutz's

documentation protocol, but here is a rough draft of documentation,

let me know what you all think.

;; @syntax (FTP:config ...<quoted-var1> <val1> <quoted-var1> <val2> ...)
;; @description Sets control variables. Throws error if var isn't "registered" in 'control-vars
;; @example
;; (FTP:config 'quiet 1 'report-file "Uploading: ") => changes FTP:quiet and FTP:report-file
;;  control variables are as follows:
;;  quiet: Set to nil to report command transfers
;;  report: set to non-nil to report and track data transfers
;;  intro: Simple header, displayed if 'report is true
;;  report-file: Precedes announcement of file name when 'report'ing
;;  packet-marker: One or more characters to print to stdout when a packet is sent
;; NOTE: the intent of config is to
;; 1) Simplify code
;; 2) Prevent typos
;; 3) Create some sort of boundary between "private" and "public" variables


<grin>I'd hate to make more work for Lutz, but I think it would be great

if there was a doc protocol for variables, but maybe there is....

Tim
Programmer since 1987. Unix environment.

cormullion

#4
I've added a bit of newLISPdoc stuff. Starting to get confused mixing up all this HTML and newLISP syntax... :)

Lutz

#5
Nice! This goes into the next release.

newdep

#6
Nice work guys..!



A question..



Why does get-file return 'nil after succes?

I would expect 'true on success and 'nil perhpas "nothing more to fetch?

but could be a matter of taste perhpas? ;-)



...............................................................................................................................................................................................................................................................................................................nil
-- (define? (Cornflakes))

cormullion

#7
:) Well, I really don't know...! I'll have to have another look.



To be honest, I never really understand the code I write. Not to the extent of knowing every alternative outcome, at least...



Back to the drawing board...

Tim Johnson

#8
I ran into a problem. For some reason, 'send-files - being called from

'upload with a list of files as in
(map send-files (args))
was getting a string instead of list and therefore 'map complained.

So I added a coercion so that send-files looks like so:

(define (send-files f-list)
  (if (not(list? f-list))(set 'f-list(list f-list))) ;; make sure f-list _is_ a list
  (map send-file f-list)
  (report "Sent " (length f-list) " files"))

I suspect that this was a result of the way that I composed the parameter

list to FTP:upload - which looks like this:
(set 'res(apply mftp:upload (append ftp-info (upload-info 0))))
Where 'ftp-info is a list containing connection data and (upload-info 0)

is member 0 of a nested list - itself a list of filenames for upload.

Anyway, although I've got a ways to go before getting the hang of

newlisp, I can verify another server connection with a multiple upload.

Would welcome comments on whether the coercion should remain or

a better way to compose the arguments.

cheers

tim
Programmer since 1987. Unix environment.

cormullion

#9
Quote(set 'res(apply mftp:upload (append ftp-info (upload-info 0))))


This works for me, as long as the files are supplied in a list. Perhaps you could set a  temp variable to the list and print it first, to see what you're actually passing to apply...



I can't get get-file to work properly now... It returns nil too often...



Edit: I think I know what I did. I managed to revert to an old version of get-file without realising. Ha... I'm glad that I don't do this for a living - I would have just got fired... :)

Tim Johnson

#10
:-) Actually, I added a 'test variable - implementation is meant to be

temporary - so

mftp:upload looks like this:
(define (upload host user-name password working-dir)
  (cond (test
(println "host = "  host)
(println "user-name = "  user-name)
(println "password = "  password)
(println "working-dir = "  working-dir)
(println "args = "  (args))
)
((not test)
(and
 (connect host)
 (login user-name password working-dir)
 (report intro)
 (map send-files (args))
 (logout)
 (disconnect))
))
  )
;; call to FTP:config
(mftp:config 'test true)
;; and output looks like this:
host = 000.000.000.000
user-name = <user>
password = <pwd>
working-dir = /cgi-bin/libraries/python
args = ("mylib.py" "valid.py")

Note to window users - there's a number of utilities in linux that

have a "test" switch that allows the user to test functionality before

commitment.. I'm kind of emulating that protocol.
Programmer since 1987. Unix environment.

cormullion

#11
That's the sort of thing. Your formulation works as you hoped:


(set 'list1 '("ftp..." "user" "pass" "tmp"))
(set 'list2 '(("test1.txt" "test2.txt")))
(append list1 list2)
(set 'res (apply upload (append list1 list2)))
...
Connected to host. Upload follows:
227 Entering Passive Mode (...).
150 Opening BINARY mode data connection for test1.txt
Sending: test1.txt.
226 Transfer complete
227 Entering Passive Mode (...).
150 Opening BINARY mode data connection for test2.txt
Sending: test2.txt.
226 Transfer complete
Sent 2 files221 Goodbye.


The files are transferred OK, but res will (always) be nil! That's because either logout or disconnect returns nil at some point, and upload does them after the transfers. I'll have to put the tracer on it later.



By the way, I noticed that you do this:


(define (report) ; print progress etc.
  (if report (doargs (i) (print i))))


where report was originally a boolean flag, and gets redefined as a function. But doesn't that mean that report is always true?

Tim Johnson

#12
Yikes! Of course you are right. I'm surprised that didn't recurse the

stack all to hell and gone!

The function should be 'report-data-transfer

thanks

tim
Programmer since 1987. Unix environment.

cormullion

#13
I've put in some more fixes and uploaded it again. Version 0.12... :)



Perhaps we should host this somewhere like http://github.com/">//http://github.com/ so everyone could have a go...!

Tim Johnson

#14
Sure. I know I would learn a lot from that.

tj
Programmer since 1987. Unix environment.