~ubuntu-branches/ubuntu/raring/duplicity/raring-updates

« back to all changes in this revision

Viewing changes to src/backends/ftpsbackend.py

  • Committer: Bazaar Package Importer
  • Author(s): Michael Terry
  • Date: 2011-04-03 20:40:34 UTC
  • mfrom: (1.9.1 upstream) (16.2.6 natty)
  • Revision ID: james.westby@ubuntu.com-20110403204034-5m1eri4z5qr0nyrr
Tags: 0.6.13-0ubuntu1
* Resync with Debian, no remaining changes
* New upstream release
  - silent data corruption with checkpoint/restore (LP: #613244)
  - Assertion error "time not moving forward at appropriate pace"
    (LP: #579958)
* debian/patches/04future.dpatch:
  - Dropped, applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 
2
#
 
3
# Copyright 2002 Ben Escoto <ben@emerose.org>
 
4
# Copyright 2007 Kenneth Loafman <kenneth@loafman.com>
 
5
# Copyright 2010 Marcel Pennewiss <opensource@pennewiss.de>
 
6
#
 
7
# This file is part of duplicity.
 
8
#
 
9
# Duplicity is free software; you can redistribute it and/or modify it
 
10
# under the terms of the GNU General Public License as published by the
 
11
# Free Software Foundation; either version 2 of the License, or (at your
 
12
# option) any later version.
 
13
#
 
14
# Duplicity is distributed in the hope that it will be useful, but
 
15
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
# General Public License for more details.
 
18
#
 
19
# You should have received a copy of the GNU General Public License
 
20
# along with duplicity; if not, write to the Free Software Foundation,
 
21
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
22
 
 
23
import os
 
24
import os.path
 
25
import urllib
 
26
import re
 
27
 
 
28
import duplicity.backend
 
29
from duplicity import globals
 
30
from duplicity import log
 
31
from duplicity.errors import *
 
32
from duplicity import tempdir
 
33
 
 
34
class FTPSBackend(duplicity.backend.Backend):
 
35
    """Connect to remote store using File Transfer Protocol"""
 
36
    def __init__(self, parsed_url):
 
37
        duplicity.backend.Backend.__init__(self, parsed_url)
 
38
 
 
39
        # we expect an output
 
40
        try:
 
41
            p = os.popen("lftp --version")
 
42
            fout = p.read()
 
43
            ret = p.close()
 
44
        except:
 
45
            pass
 
46
        # there is no output if lftp not found
 
47
        if not fout:
 
48
            log.FatalError("LFTP not found:  Please install LFTP.",
 
49
                           log.ErrorCode.ftps_lftp_missing)
 
50
 
 
51
        # version is the second word of the second part of the first line
 
52
        version = fout.split('\n')[0].split(' | ')[1].split()[1]
 
53
        log.Notice("LFTP version is %s" % version)
 
54
 
 
55
        self.parsed_url = parsed_url
 
56
 
 
57
        self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url)
 
58
 
 
59
        # Use an explicit directory name.
 
60
        if self.url_string[-1] != '/':
 
61
            self.url_string += '/'
 
62
 
 
63
        self.password = self.get_password()
 
64
 
 
65
        if globals.ftp_connection == 'regular':
 
66
            self.conn_opt = 'off'
 
67
        else:
 
68
            self.conn_opt = 'on'
 
69
 
 
70
        if parsed_url.port != None and parsed_url.port != 21:
 
71
            self.portflag = " -p '%s'" % (parsed_url.port)
 
72
        else:
 
73
            self.portflag = ""
 
74
 
 
75
        self.tempfile, self.tempname = tempdir.default().mkstemp()
 
76
        os.write(self.tempfile, "set ftp:ssl-allow true\n")
 
77
        os.write(self.tempfile, "set ftp:ssl-protect-data true\n")
 
78
        os.write(self.tempfile, "set ftp:ssl-protect-list true\n")
 
79
        os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout)
 
80
        os.write(self.tempfile, "set net:max-retries 1\n")
 
81
        os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt)
 
82
        os.write(self.tempfile, "open %s %s\n" % (self.portflag, self.parsed_url.hostname))
 
83
        os.write(self.tempfile, "user %s %s\n" % (self.parsed_url.username, self.password))
 
84
        os.close(self.tempfile)
 
85
 
 
86
        self.flags = "-f %s" % self.tempname
 
87
 
 
88
    def put(self, source_path, remote_filename = None):
 
89
        """Transfer source_path to remote_filename"""
 
90
        if not remote_filename:
 
91
            remote_filename = source_path.get_filename()
 
92
        remote_path = os.path.join(urllib.unquote(self.parsed_url.path.lstrip('/')), remote_filename).rstrip()
 
93
        commandline = "lftp -c 'source %s;put \'%s\' -o \'%s\''" % \
 
94
            (self.tempname, source_path.name, remote_path)
 
95
        l = self.run_command_persist(commandline)
 
96
 
 
97
    def get(self, remote_filename, local_path):
 
98
        """Get remote filename, saving it to local_path"""
 
99
        remote_path = os.path.join(urllib.unquote(self.parsed_url.path), remote_filename).rstrip()
 
100
        commandline = "lftp -c 'source %s;get %s -o %s'" % \
 
101
            (self.tempname, remote_path.lstrip('/'), local_path.name)
 
102
        self.run_command_persist(commandline)
 
103
        local_path.setdata()
 
104
 
 
105
    def list(self):
 
106
        """List files in directory"""
 
107
        # Do a long listing to avoid connection reset
 
108
        remote_dir = urllib.unquote(self.parsed_url.path.lstrip('/')).rstrip()
 
109
        commandline = "lftp -c 'source %s;ls \'%s\''" % (self.tempname, remote_dir)
 
110
        l = self.popen_persist(commandline).split('\n')
 
111
        l = filter(lambda x: x, l)
 
112
        # Look for our files as the last element of a long list line
 
113
        return [x.split()[-1] for x in l]
 
114
 
 
115
    def delete(self, filename_list):
 
116
        """Delete files in filename_list"""
 
117
        filelist = ""
 
118
        for filename in filename_list:
 
119
            filelist += "\'%s\' " % filename
 
120
        remote_dir = urllib.unquote(self.parsed_url.path.lstrip('/')).rstrip()
 
121
        commandline = "lftp -c 'source %s;cd \'%s\';rm %s'" % (self.tempname, remote_dir, filelist.rstrip())
 
122
        self.popen_persist(commandline)
 
123
 
 
124
duplicity.backend.register_backend("ftps", FTPSBackend)