chrism01 has asked for the wisdom of the Perl Monks concerning the following question:

Guys,
I've got a program that extracts attachments from emails that I then need to send/save to another box.
Using the Mail::Message routines, I end up with the file name and payload ie contents separately.
I'd like to write the payload to the remote box without creating a local file first, ie using sftp->do_open, do_write, do_close ...
My problem atm is that do_open() requires "$flags" ie

"$flags should be a bitmask of open flags, whose values can be obtained from Net::SFTP::Constants
use Net::SFTP::Constants qw( :flags );

However, the CPAN page for this does not specify what flag values are avail/should be used for do_write(), only saying it can be blank for do_read().
I've googled all over, but cannot find a single example of how to do this.
I'd like to do a simple

$sftp->do_open(...);
$sftp->do_write(...);
$sftp->do_close(...);

for each file.
Has any body got a working example, please, with $flags and $attributes values?
Cheers
Chris

Replies are listed 'Best First'.
Re: sftp->do_write howto?
by marto (Cardinal) on Sep 21, 2005 at 08:33 UTC
    Hi,

    I dont have this module installed, and am unable to do so at the moment.
    If all you want to do is upload a file from A to B try the following, from the documentation:
    #!/usr/bin/perl use Net::SFTP; my $host = 'marto.lacksimagination.com'; my %args = ( "user", 'marto', "password", 'mytopsecretpassword' ); my $localFilename = 'backup.zip'; my $remoteFilename = 'backup.zip'; my $sftp = Net::SFTP->new($host,%args); $sftp->put($localFilename,$remoteFilename);
    Obviously replace my dummy values with the correct ones (host,user,password).
    As I said, this is untested code. If you have any problems let us know.

    Hope this helps.

    Martin
Re: sftp->do_write howto?
by idsfa (Vicar) on Sep 21, 2005 at 15:09 UTC

    Since you said that you are trying to do this without creating a local file, the previous response doesn't really answer the question. Reading the source, the flags for open are the Constants prefixed with SSH2_FXF_. Specifically,

    'SSH2_FXF_READ' => 0x01, 'SSH2_FXF_WRITE' => 0x02, 'SSH2_FXF_APPEND' => 0x04, 'SSH2_FXF_CREAT' => 0x08, 'SSH2_FXF_TRUNC' => 0x10, 'SSH2_FXF_EXCL' => 0x20,

    Which should look familiar to anyone who has ever opened a file à la C. You say you want to append to an existing remote file, so you do not need READ, CREAT(e), TRUNC(ate) or EXCL(ude). You do need WRITE and APPEND, so your flags are:

    SSH2_FXF_WRITE | SSH2_FXF_APPEND

    (Remember that you OR flags when you want them both)

    Update: As is pointed out by insaniac, this is not the only code change. You either neet to use the hex listed above (less portable) or follow the instructions in the docs:

    use Net::SFTP::Constants qw( SSH2_FXP_WRITE SSH2_FXF_APPEND );

    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. -- Cyrus H. Gordon
      Thx for the hints.
      Actually, I'm not appending, i'm simply "copying" (ie creating) the attachments to their own files on the remote system, but without creating a local copy first (inefficient).
      I've tried this test prog:
      $filename = "testfile.dat"; $payload = "qwertyuiop"; $args{user} = "xxx"; $args{password} = "yyy"; $host = "s.a.c.u"; $path = "/some/path/".$filename; print "connecting\n"; $sftp = Net::SFTP->new($host, %args); print "open\n"; $handle = $sftp->do_open($path, SSH2_FXF_WRITE | SSH2_FXF_CREAT); print "write\n"; $sftp->do_write($handle, 0, $payload); print "close\n"; $sftp->do_close($handle);
      (where I've obscured the real values).
      but it says

      Permission denied at /usr/lib/perl5/site_perl/5.8.5/Net/SFTP.pm line 62

      which is this line

      $ssh->login($param{user}, $param{password});

      I've tried replacing this with the hardcoded vals from my program and printed out the host value (looks ok), but same error.
      FYI, I can successfully login manually from the cmd line using the same values(!), so I'm stuck...
      Any ideas??
      Cheers
      Chris
        tip 1: use strict; use warnings;! Then you would have seen:
        Bareword "SSH2_FXF_WRITE" not allowed while "strict subs" in use at ne +t_sftp.pl line 17. Bareword "SSH2_FXF_CREAT" not allowed while "strict subs" in use at ne +t_sftp.pl line 17. Execution of net_sftp.pl aborted due to compilation errors.
        When you use the hex values shown above, the code connects to your remote host.
        It even sends the file! Your code works just by replacing SSH2_FXF_WRITE | SSH2_FXF_CREAT by their hex values.

        Update:
        See idsfa's remark about the Net::SFTP::Constants ;-)

        Cheers!

        to ask a question is a moment of shame
        to remain ignorant is a lifelong shame