~openerp-commiter/openobject-addons/extra-6.0

« back to all changes in this revision

Viewing changes to document_sftp/sftp_server/SFTPHandle.py

  • Committer: Fabien Pinckaers
  • Date: 2009-04-22 19:24:14 UTC
  • mfrom: (3589.8.19 trunk-extra-addons)
  • Revision ID: fp@tinyerp.com-20090422192414-rke20j736h6dx9j7
adding_test_server

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- encoding: utf-8 -*-
2
 
##############################################################################
3
 
#
4
 
#    OpenERP, Open Source Management Solution   
5
 
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6
 
#    $Id$
7
 
#
8
 
#    This program is free software: you can redistribute it and/or modify
9
 
#    it under the terms of the GNU General Public License as published by
10
 
#    the Free Software Foundation, either version 3 of the License, or
11
 
#    (at your option) any later version.
12
 
#
13
 
#    This program is distributed in the hope that it will be useful,
14
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
#    GNU General Public License for more details.
17
 
#
18
 
#    You should have received a copy of the GNU General Public License
19
 
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
#
21
 
##############################################################################
22
 
 
23
 
import paramiko
24
 
class SFTPHandle (paramiko.SFTPHandle):
25
 
    def __init__(self, flags=0):
26
 
        """
27
 
        Create a new file handle representing a local file being served over
28
 
        SFTP.  If C{flags} is passed in, it's used to determine if the file
29
 
        is open in append mode.
30
 
        
31
 
        @param flags: optional flags as passed to L{SFTPServerInterface.open}
32
 
        @type flags: int
33
 
        """
34
 
        self.__flags = flags
35
 
        self.__name = None
36
 
        # only for handles to folders:
37
 
        self.__files = { }
38
 
        self.__tell = None
39
 
 
40
 
    def close(self):
41
 
        """
42
 
        When a client closes a file, this method is called on the handle.
43
 
        Normally you would use this method to close the underlying OS level
44
 
        file object(s).
45
 
        
46
 
        The default implementation checks for attributes on C{self} named
47
 
        C{readfile} and/or C{writefile}, and if either or both are present,
48
 
        their C{close()} methods are called.  This means that if you are
49
 
        using the default implementations of L{read} and L{write}, this
50
 
        method's default implementation should be fine also.
51
 
        """
52
 
        readfile = getattr(self, 'readfile', None)
53
 
        if readfile is not None:
54
 
            readfile.close()
55
 
        writefile = getattr(self, 'writefile', None)
56
 
        if writefile is not None:
57
 
            writefile.close()
58
 
 
59
 
    def read(self, offset, length):
60
 
        """
61
 
        Read up to C{length} bytes from this file, starting at position
62
 
        C{offset}.  The offset may be a python long, since SFTP allows it
63
 
        to be 64 bits.
64
 
 
65
 
        If the end of the file has been reached, this method may return an
66
 
        empty string to signify EOF, or it may also return L{SFTP_EOF}.
67
 
 
68
 
        The default implementation checks for an attribute on C{self} named
69
 
        C{readfile}, and if present, performs the read operation on the python
70
 
        file-like object found there.  (This is meant as a time saver for the
71
 
        common case where you are wrapping a python file object.)
72
 
 
73
 
        @param offset: position in the file to start reading from.
74
 
        @type offset: int or long
75
 
        @param length: number of bytes to attempt to read.
76
 
        @type length: int
77
 
        @return: data read from the file, or an SFTP error code.
78
 
        @rtype: str
79
 
        """
80
 
        readfile = getattr(self, 'readfile', None)
81
 
        if readfile is None:
82
 
            return SFTP_OP_UNSUPPORTED
83
 
        try:
84
 
            if self.__tell is None:
85
 
                self.__tell = readfile.tell()
86
 
            if offset != self.__tell:
87
 
                readfile.seek(offset)
88
 
                self.__tell = offset
89
 
            data = readfile.read(length)
90
 
        except IOError, e:
91
 
            self.__tell = None
92
 
            return SFTPServer.convert_errno(e.errno)
93
 
        self.__tell += len(data)
94
 
        return data
95
 
 
96
 
    def write(self, offset, data):
97
 
        """
98
 
        Write C{data} into this file at position C{offset}.  Extending the
99
 
        file past its original end is expected.  Unlike python's normal
100
 
        C{write()} methods, this method cannot do a partial write: it must
101
 
        write all of C{data} or else return an error.
102
 
 
103
 
        The default implementation checks for an attribute on C{self} named
104
 
        C{writefile}, and if present, performs the write operation on the
105
 
        python file-like object found there.  The attribute is named
106
 
        differently from C{readfile} to make it easy to implement read-only
107
 
        (or write-only) files, but if both attributes are present, they should
108
 
        refer to the same file.
109
 
        
110
 
        @param offset: position in the file to start reading from.
111
 
        @type offset: int or long
112
 
        @param data: data to write into the file.
113
 
        @type data: str
114
 
        @return: an SFTP error code like L{SFTP_OK}.
115
 
        """
116
 
        writefile = getattr(self, 'writefile', None)
117
 
        if writefile is None:
118
 
            return SFTP_OP_UNSUPPORTED
119
 
        try:
120
 
            # in append mode, don't care about seeking
121
 
            if (self.__flags & os.O_APPEND) == 0:
122
 
                if self.__tell is None:
123
 
                    self.__tell = writefile.tell()
124
 
                if offset != self.__tell:
125
 
                    writefile.seek(offset)
126
 
                    self.__tell = offset
127
 
            writefile.write(data)
128
 
            writefile.flush()
129
 
        except IOError, e:
130
 
            self.__tell = None
131
 
            return SFTPServer.convert_errno(e.errno)
132
 
        if self.__tell is not None:
133
 
            self.__tell += len(data)
134
 
        return SFTP_OK    
135
 
 
136
 
    def chattr(self, attr):
137
 
        """
138
 
        Change the attributes of this file.  The C{attr} object will contain
139
 
        only those fields provided by the client in its request, so you should
140
 
        check for the presence of fields before using them.
141
 
 
142
 
        @param attr: the attributes to change on this file.
143
 
        @type attr: L{SFTPAttributes}
144
 
        @return: an error code like L{SFTP_OK}.
145
 
        @rtype: int
146
 
        """
147
 
        return SFTP_OP_UNSUPPORTED
148
 
 
149
 
 
150
 
    ###  internals...
151
 
 
152
 
    
153
 
    def _set_files(self, files):
154
 
        """
155
 
        Used by the SFTP server code to cache a directory listing.  (In
156
 
        the SFTP protocol, listing a directory is a multi-stage process
157
 
        requiring a temporary handle.)
158
 
        """
159
 
        self.__files = files
160
 
 
161
 
    def _get_next_files(self):
162
 
        """
163
 
        Used by the SFTP server code to retreive a cached directory
164
 
        listing.
165
 
        """
166
 
        fnlist = self.__files[:16]
167
 
        self.__files = self.__files[16:]
168
 
        return fnlist
169
 
 
170
 
    def _get_name(self):
171
 
        return self.__name
172
 
 
173
 
    def _set_name(self, name):
174
 
        self.__name = name
175
 
 
176
 
 
177