~launchpad-pqm/launchpad/devel

8687.15.18 by Karl Fogel
Add the copyright header block to files under lib/canonical/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
3
4
__metaclass__ = type
5
9264.4.2 by Gary Poster
remove zope branch more thoroughly (and a few other similar cleanups)
6
import asyncore
9264.4.4 by Gary Poster
address some lint complaints
7
import tempfile
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
8
from time import time
9
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
10
from zope.server.ftp.server import (
11
    FTPServerChannel,
12
    STORChannel as OriginalSTORChannel,
13
    )
14
from zope.server.serverbase import ServerBase
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
15
from zope.server.taskthreads import ThreadedTaskDispatcher
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
16
10529.1.1 by Jonathan Lange
Move poppy to lp
17
from lp.poppy.filesystem import UploadFileSystem
1469 by Canonical.com Patch Queue Manager
poppy no longer times out.
18
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
19
20
class Channel(FTPServerChannel):
21
22
    def __init__(self, server, conn, addr, adj=None):
23
        # Work around a zope3 bug where the status messages dict is copied by
24
        # reference, not by value.
25
        self.status_messages = dict(self.status_messages)
26
        self.status_messages['SERVER_READY'] = (
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
27
            '220 %s Canonical FTP server ready.')
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
28
29
        FTPServerChannel.__init__(self, server, conn, addr, adj=None)
30
        self.peername = self.socket.getpeername()
31
        self.uploadfilesystem, self.fsroot = server.newClient(self)
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
32
        self.hook = server.auth_verify_hook
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
33
34
    def close(self):
35
        FTPServerChannel.close(self)
36
        self.server.clientFinished(self)
37
38
    def _getFileSystem(self):
39
        return self.uploadfilesystem
40
1409 by Canonical.com Patch Queue Manager
Small security refactor. Ellision-aware page test runner. Merge of Bjorn's team-awareness for malone. Sensible ordering for dbschema vocabularies.
41
    def received(self, data):
10529.1.8 by Jonathan Lange
Whitespace & comment cleanups
42
        # XXX Steve Alexander 2005-01-18
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
43
        #     This is a work-around for a bug in Zope 3's ServerChannelBase
1409 by Canonical.com Patch Queue Manager
Small security refactor. Ellision-aware page test runner. Merge of Bjorn's team-awareness for malone. Sensible ordering for dbschema vocabularies.
44
        #     that it doesn't update self.last_activity.
45
        #     This method can be removed once Zope3 is fixed, and we're using
46
        #     that code.
47
        #     http://collector.zope.org/Zope3-dev/350
1469 by Canonical.com Patch Queue Manager
poppy no longer times out.
48
        self.record_activity()
49
        FTPServerChannel.received(self, data)
50
51
    def record_activity(self):
1409 by Canonical.com Patch Queue Manager
Small security refactor. Ellision-aware page test runner. Merge of Bjorn's team-awareness for malone. Sensible ordering for dbschema vocabularies.
52
        self.last_activity = time()
53
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
54
    def cmd_pass(self, args):
55
        'See IFTPCommandHandler'
56
        self.authenticated = 0
57
        password = args
58
        credentials = (self.username, password)
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
59
        okay = True
60
        if self.hook:
61
            try:
62
                if not self.hook(self.fsroot, self.username, password):
63
                    okay = False
64
            except:
65
                okay = False
66
        if not okay:
67
            self.reply('LOGIN_MISMATCH')
68
            self.close_when_done()
69
        else:
70
            self.credentials = credentials
71
            self.authenticated = 1
72
            self.reply('LOGIN_SUCCESS')
844 by Canonical.com Patch Queue Manager
added ftp server. added annotation-in-zodb support.
73
1469 by Canonical.com Patch Queue Manager
poppy no longer times out.
74
    def cmd_stor(self, args, write_mode='w'):
75
        'See IFTPCommandHandler'
76
        if not args:
77
            self.reply('ERR_ARGS')
78
            return
79
        path = self._generatePath(args)
80
81
        start = 0
82
        if self.restart_position:
83
            self.start = self.restart_position
84
        mode = write_mode + self.type_mode_map[self.transfer_mode]
85
86
        if not self._getFileSystem().writable(path):
87
            self.reply('ERR_OPEN_WRITE', "Can't write file")
88
            return
89
90
        cdc = STORChannel(self, (path, mode, start))
91
        self.syncConnectData(cdc)
92
        self.reply('OPEN_CONN', (self.type_map[self.transfer_mode], path))
93
3691.444.3 by Celso Providelo
Add directory supporting for poppy: recursive mkdir & rmdir, ls/lsinfo/type and protection for underneath directories. Add also support to automatically creation of directories 'CWD'ed in. Tested with dupload and dput
94
    def cmd_cwd(self, args):
95
        """Permissive 'cwd', creates any target directories requested.
96
97
        It relies on the filesystem layer to create directories recursivelly.
98
        """
99
        path = self._generatePath(args)
100
        if not self._getFileSystem().type(path) == 'd':
101
            self._getFileSystem().mkdir(path)
102
        self.cwd = path
103
        self.reply('SUCCESS_250', 'CWD')
104
105
1469 by Canonical.com Patch Queue Manager
poppy no longer times out.
106
class STORChannel(OriginalSTORChannel):
107
108
    def received (self, data):
109
        if data:
110
            self.inbuf.append(data)
111
            self.control_channel.record_activity()
112
            # This is the point at which some data for an upload has been
113
            # received by the server from a client.
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
114
10529.1.8 by Jonathan Lange
Whitespace & comment cleanups
115
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
116
class Server(ServerBase):
117
118
    channel_class = Channel
119
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
120
    def __init__(self, ip, port,
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
121
                 new_client_hook, client_done_hook, auth_verify_hook,
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
122
                 *args, **kw):
123
        ServerBase.__init__(self, ip, port, *args, **kw)
124
        self.new_client_hook = new_client_hook
125
        self.client_done_hook = client_done_hook
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
126
        self.auth_verify_hook = auth_verify_hook
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
127
128
    def newClient(self, channel):
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
129
        fsroot = tempfile.mkdtemp("-poppy")
130
        uploadfilesystem = UploadFileSystem(fsroot)
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
131
        clienthost, clientport = channel.peername
132
        try:
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
133
            self.new_client_hook(fsroot, clienthost, clientport)
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
134
        except Exception:
135
            # Almost bare except, result logged, to keep server running.
136
            self.logger.exception("Exception during new client hook")
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
137
        return uploadfilesystem, fsroot
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
138
139
    def clientFinished(self, channel):
140
        clienthost, clientport = channel.peername
141
        try:
142
            self.client_done_hook(channel.fsroot, clienthost, clientport)
143
        except Exception:
144
            # Almost bare except, result logged, to keep server running.
145
            self.logger.exception("Exception during client done hook")
146
147
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
148
def run_server(host, port, ident, numthreads,
10529.1.2 by Jonathan Lange
Minor cleanups
149
               new_client_hook, client_done_hook, auth_verify_hook=None):
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
150
    task_dispatcher = ThreadedTaskDispatcher()
151
    task_dispatcher.setThreadCount(numthreads)
2865.6.8 by Gustavo Niemeyer
The Soyuz upload mechanism was changed to avoid the potential
152
    server = Server(host, port,
1474 by Canonical.com Patch Queue Manager
GPGV movement, initial poppy-upload and clean up ftpserver signon
153
                    new_client_hook, client_done_hook, auth_verify_hook,
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
154
                    task_dispatcher=task_dispatcher)
155
    server.SERVER_IDENT = ident
156
    try:
9264.4.2 by Gary Poster
remove zope branch more thoroughly (and a few other similar cleanups)
157
        asyncore.loop()
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
158
    except KeyboardInterrupt:
159
        # Exit without spewing an exception.
160
        pass