~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/protocols/telnet.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
 
 
6
"""TELNET implementation, with line-oriented command handling.
 
7
"""
 
8
 
 
9
import warnings
 
10
warnings.warn(
 
11
    "As of Twisted 2.1, twisted.protocols.telnet is deprecated.  "
 
12
    "See twisted.conch.telnet for the current, supported API.",
 
13
    DeprecationWarning,
 
14
    stacklevel=2)
 
15
 
 
16
 
 
17
# System Imports
 
18
try:
 
19
    from cStringIO import StringIO
 
20
except ImportError:
 
21
    from StringIO import StringIO
 
22
 
 
23
# Twisted Imports
 
24
from twisted import copyright
 
25
from twisted.internet import protocol
 
26
 
 
27
# Some utility chars.
 
28
ESC =            chr(27) # ESC for doing fanciness
 
29
BOLD_MODE_ON =   ESC+"[1m" # turn bold on
 
30
BOLD_MODE_OFF=   ESC+"[m"  # no char attributes
 
31
 
 
32
 
 
33
# Characters gleaned from the various (and conflicting) RFCs.  Not all of these are correct.
 
34
 
 
35
NULL =            chr(0)  # No operation.
 
36
LF   =           chr(10)  # Moves the printer to the
 
37
                          # next print line, keeping the
 
38
                          # same horizontal position.
 
39
CR =             chr(13)  # Moves the printer to the left
 
40
                          # margin of the current line.
 
41
BEL =             chr(7)  # Produces an audible or
 
42
                          # visible signal (which does
 
43
                          # NOT move the print head).
 
44
BS  =             chr(8)  # Moves the print head one
 
45
                          # character position towards
 
46
                          # the left margin.
 
47
HT  =             chr(9)  # Moves the printer to the
 
48
                          # next horizontal tab stop.
 
49
                          # It remains unspecified how
 
50
                          # either party determines or
 
51
                          # establishes where such tab
 
52
                          # stops are located.
 
53
VT =             chr(11)  # Moves the printer to the
 
54
                          # next vertical tab stop.  It
 
55
                          # remains unspecified how
 
56
                          # either party determines or
 
57
                          # establishes where such tab
 
58
                          # stops are located.
 
59
FF =             chr(12)  # Moves the printer to the top
 
60
                          # of the next page, keeping
 
61
                          # the same horizontal position.
 
62
SE =            chr(240)  # End of subnegotiation parameters.
 
63
NOP=            chr(241)  # No operation.
 
64
DM =            chr(242)  # "Data Mark": The data stream portion
 
65
                          # of a Synch.  This should always be
 
66
                          # accompanied by a TCP Urgent
 
67
                          # notification.
 
68
BRK=            chr(243)  # NVT character Break.
 
69
IP =            chr(244)  # The function Interrupt Process.
 
70
AO =            chr(245)  # The function Abort Output
 
71
AYT=            chr(246)  # The function Are You There.
 
72
EC =            chr(247)  # The function Erase Character.
 
73
EL =            chr(248)  # The function Erase Line
 
74
GA =            chr(249)  # The Go Ahead signal.
 
75
SB =            chr(250)  # Indicates that what follows is
 
76
                          # subnegotiation of the indicated
 
77
                          # option.
 
78
WILL =          chr(251)  # Indicates the desire to begin
 
79
                          # performing, or confirmation that
 
80
                          # you are now performing, the
 
81
                          # indicated option.
 
82
WONT =          chr(252)  # Indicates the refusal to perform,
 
83
                          # or continue performing, the
 
84
                          # indicated option.
 
85
DO =            chr(253)  # Indicates the request that the
 
86
                          # other party perform, or
 
87
                          # confirmation that you are expecting
 
88
                          # the other party to perform, the
 
89
                          # indicated option.
 
90
DONT =          chr(254)  # Indicates the demand that the
 
91
                          # other party stop performing,
 
92
                          # or confirmation that you are no
 
93
                          # longer expecting the other party
 
94
                          # to perform, the indicated option.
 
95
IAC =           chr(255)  # Data Byte 255.
 
96
 
 
97
# features
 
98
 
 
99
ECHO  =           chr(1)  # User-to-Server:  Asks the server to send
 
100
                          # Echos of the transmitted data.
 
101
 
 
102
                          # Server-to User:  States that the server is
 
103
                          # sending echos of the transmitted data.
 
104
                          # Sent only as a reply to ECHO or NO ECHO.
 
105
 
 
106
SUPGA =           chr(3)  # Supress Go Ahead...? "Modern" telnet servers
 
107
                          # are supposed to do this.
 
108
 
 
109
LINEMODE =       chr(34)  # I don't care that Jon Postel is dead.
 
110
 
 
111
HIDE  =         chr(133)  # The intention is that a server will send
 
112
                          # this signal to a user system which is
 
113
                          # echoing locally (to the user) when the user
 
114
                          # is about to type something secret (e.g. a
 
115
                          # password).  In this case, the user system
 
116
                          # is to suppress local echoing or overprint
 
117
                          # the input (or something) until the server
 
118
                          # sends a NOECHO signal.  In situations where
 
119
                          # the user system is not echoing locally,
 
120
                          # this signal must not be sent by the server.
 
121
 
 
122
 
 
123
NOECHO=         chr(131)  # User-to-Server:  Asks the server not to
 
124
                          # return Echos of the transmitted data.
 
125
                          # 
 
126
                          # Server-to-User:  States that the server is
 
127
                          # not sending echos of the transmitted data.
 
128
                          # Sent only as a reply to ECHO or NO ECHO,
 
129
                          # or to end the hide your input.
 
130
 
 
131
 
 
132
 
 
133
iacBytes = {
 
134
    DO:   'DO',
 
135
    DONT: 'DONT',
 
136
    WILL: 'WILL',
 
137
    WONT: 'WONT',
 
138
    IP:   'IP'
 
139
    }
 
140
 
 
141
def multireplace(st, dct):
 
142
    for k, v in dct.items():
 
143
        st = st.replace(k, v)
 
144
    return st
 
145
 
 
146
class Telnet(protocol.Protocol):
 
147
    """I am a Protocol for handling Telnet connections. I have two
 
148
    sets of special methods, telnet_* and iac_*.
 
149
 
 
150
    telnet_* methods get called on every line sent to me. The method
 
151
    to call is decided by the current mode. The initial mode is 'User';
 
152
    this means that telnet_User is the first telnet_* method to be called.
 
153
    All telnet_* methods should return a string which specifies the mode
 
154
    to go into next; thus dictating which telnet_* method to call next.
 
155
    For example, the default telnet_User method returns 'Password' to go
 
156
    into Password mode, and the default telnet_Password method returns
 
157
    'Command' to go into Command mode.
 
158
 
 
159
    The iac_* methods are less-used; they are called when an IAC telnet
 
160
    byte is received. You can define iac_DO, iac_DONT, iac_WILL, iac_WONT,
 
161
    and iac_IP methods to do what you want when one of these bytes is
 
162
    received."""
 
163
 
 
164
 
 
165
    gotIAC = 0
 
166
    iacByte = None
 
167
    lastLine = None
 
168
    buffer = ''
 
169
    echo = 0
 
170
    delimiters = ['\r\n', '\r\000']
 
171
    mode = "User"
 
172
 
 
173
    def write(self, data):
 
174
        """Send the given data over my transport."""
 
175
        self.transport.write(data)
 
176
 
 
177
 
 
178
    def connectionMade(self):
 
179
        """I will write a welcomeMessage and loginPrompt to the client."""
 
180
        self.write(self.welcomeMessage() + self.loginPrompt())
 
181
 
 
182
    def welcomeMessage(self):
 
183
        """Override me to return a string which will be sent to the client
 
184
        before login."""
 
185
        x = self.factory.__class__
 
186
        return ("\r\n" + x.__module__ + '.' + x.__name__ +
 
187
                '\r\nTwisted %s\r\n' % copyright.version
 
188
                )
 
189
 
 
190
    def loginPrompt(self):
 
191
        """Override me to return a 'login:'-type prompt."""
 
192
        return "username: "
 
193
 
 
194
    def iacSBchunk(self, chunk):
 
195
        pass
 
196
 
 
197
    def iac_DO(self, feature):
 
198
        pass
 
199
 
 
200
    def iac_DONT(self, feature):
 
201
        pass
 
202
 
 
203
    def iac_WILL(self, feature):
 
204
        pass
 
205
 
 
206
    def iac_WONT(self, feature):
 
207
        pass
 
208
 
 
209
    def iac_IP(self, feature):
 
210
        pass
 
211
 
 
212
    def processLine(self, line):
 
213
        """I call a method that looks like 'telnet_*' where '*' is filled
 
214
        in by the current mode. telnet_* methods should return a string which
 
215
        will become the new mode.  If None is returned, the mode will not change.
 
216
        """
 
217
        mode = getattr(self, "telnet_"+self.mode)(line)
 
218
        if mode is not None:
 
219
            self.mode = mode
 
220
 
 
221
    def telnet_User(self, user):
 
222
        """I take a username, set it to the 'self.username' attribute,
 
223
        print out a password prompt, and switch to 'Password' mode. If
 
224
        you want to do something else when the username is received (ie,
 
225
        create a new user if the user doesn't exist), override me."""
 
226
        self.username = user
 
227
        self.write(IAC+WILL+ECHO+"password: ")
 
228
        return "Password"
 
229
 
 
230
    def telnet_Password(self, paswd):
 
231
        """I accept a password as an argument, and check it with the
 
232
        checkUserAndPass method. If the login is successful, I call
 
233
        loggedIn()."""
 
234
        self.write(IAC+WONT+ECHO+"*****\r\n")
 
235
        try:
 
236
            checked = self.checkUserAndPass(self.username, paswd)
 
237
        except:
 
238
            return "Done"
 
239
        if not checked:
 
240
            return "Done"
 
241
        self.loggedIn()
 
242
        return "Command"
 
243
 
 
244
    def telnet_Command(self, cmd):
 
245
        """The default 'command processing' mode. You probably want to
 
246
        override me."""
 
247
        return "Command"
 
248
 
 
249
    def processChunk(self, chunk):
 
250
        """I take a chunk of data and delegate out to telnet_* methods
 
251
        by way of processLine. If the current mode is 'Done', I'll close
 
252
        the connection. """
 
253
        self.buffer = self.buffer + chunk
 
254
 
 
255
        #yech.
 
256
        for delim in self.delimiters:
 
257
            idx = self.buffer.find(delim)
 
258
            if idx != -1:
 
259
                break
 
260
            
 
261
        while idx != -1:
 
262
            buf, self.buffer = self.buffer[:idx], self.buffer[idx+2:]
 
263
            self.processLine(buf)
 
264
            if self.mode == 'Done':
 
265
                self.transport.loseConnection()
 
266
 
 
267
            for delim in self.delimiters:
 
268
                idx = self.buffer.find(delim)
 
269
                if idx != -1:
 
270
                    break
 
271
 
 
272
    def dataReceived(self, data):
 
273
        chunk = StringIO()
 
274
        # silly little IAC state-machine
 
275
        for char in data:
 
276
            if self.gotIAC:
 
277
                # working on an IAC request state
 
278
                if self.iacByte:
 
279
                    # we're in SB mode, getting a chunk
 
280
                    if self.iacByte == SB:
 
281
                        if char == SE:
 
282
                            self.iacSBchunk(chunk.getvalue())
 
283
                            chunk = StringIO()
 
284
                            del self.iacByte
 
285
                            del self.gotIAC
 
286
                        else:
 
287
                            chunk.write(char)
 
288
                    else:
 
289
                        # got all I need to know state
 
290
                        try:
 
291
                            getattr(self, 'iac_%s' % iacBytes[self.iacByte])(char)
 
292
                        except KeyError:
 
293
                            pass
 
294
                        del self.iacByte
 
295
                        del self.gotIAC
 
296
                else:
 
297
                    # got IAC, this is my W/W/D/D (or perhaps sb)
 
298
                    self.iacByte = char
 
299
            elif char == IAC:
 
300
                # Process what I've got so far before going into
 
301
                # the IAC state; don't want to process characters
 
302
                # in an inconsistent state with what they were
 
303
                # received in.
 
304
                c = chunk.getvalue()
 
305
                if c:
 
306
                    why = self.processChunk(c)
 
307
                    if why:
 
308
                        return why
 
309
                    chunk = StringIO()
 
310
                self.gotIAC = 1
 
311
            else:
 
312
                chunk.write(char)
 
313
        # chunks are of a relatively indeterminate size.
 
314
        c = chunk.getvalue()
 
315
        if c:
 
316
            why = self.processChunk(c)
 
317
            if why:
 
318
                return why
 
319
 
 
320
    def loggedIn(self):
 
321
        """Called after the user succesfully logged in.
 
322
        
 
323
        Override in subclasses.
 
324
        """
 
325
        pass