~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to twisted/reality/plumbing.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2004-06-21 22:01:11 UTC
  • mto: (2.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040621220111-vkf909euqnyrp3nr
Tags: upstream-1.3.0
ImportĀ upstreamĀ versionĀ 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
# Twisted, the Framework of Your Internet
3
 
# Copyright (C) 2001 Matthew W. Lefkowitz
4
 
5
 
# This library is free software; you can redistribute it and/or
6
 
# modify it under the terms of version 2.1 of the GNU Lesser General Public
7
 
# License as published by the Free Software Foundation.
8
 
9
 
# This library is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
# Lesser General Public License for more details.
13
 
14
 
# You should have received a copy of the GNU Lesser General Public
15
 
# License along with this library; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
"""Plumbing classes (pump, pipeline) to put Twisted Reality on the net.
19
 
"""
20
 
 
21
 
import md5
22
 
import string
23
 
from cStringIO import StringIO
24
 
 
25
 
from twisted.reality import player
26
 
from twisted.protocols import telnet, protocol, http
27
 
from twisted.python import log
28
 
from twisted.internet import tcp
29
 
from twisted.web import resource, html, widgets, guard
30
 
from twisted import copyright
31
 
 
32
 
# New-style Imports
33
 
from twisted.cred.util import Unauthorized
34
 
 
35
 
portno  = 8889
36
 
tportno = 8888
37
 
 
38
 
class Hose(telnet.Telnet):
39
 
    """A telnet protocol implementation for TR.
40
 
    """
41
 
    mode = "User"
42
 
 
43
 
    def welcomeMessage(self):
44
 
        """A message welcoming you to TR.
45
 
        """
46
 
        return "\r\nTwisted Reality %s\r\n" % copyright.version
47
 
 
48
 
 
49
 
    def loginPrompt(self):
50
 
        """A login prompt that asks for your character name.
51
 
        """
52
 
        return "character: "
53
 
 
54
 
 
55
 
    def processPassword(self, password):
56
 
        """Checks authentication against the reality; returns a boolean indicating success.
57
 
        """
58
 
        self.transport.write(telnet.IAC+ telnet.WONT+ telnet.ECHO+".....\r\n")
59
 
        req = self.factory.reality.application.authorizer.getIdentityRequest(self.username)
60
 
        self.pw = password
61
 
        req.addCallbacks(self.loggedIn, self.notLoggedIn)
62
 
        req.arm()
63
 
        # kludge; this really ought to be called later, but since the arm()
64
 
        # call actually calls self.loggedIn, then the return value of this
65
 
        # function will be used to assign to self.mode... ugh.
66
 
        if self.mode == 'Command':
67
 
            return 'Command'
68
 
        return "Pending"
69
 
 
70
 
    def loggedIn(self, identity):
71
 
        """The player's identity has been retrieved.  Now, check their password.
72
 
        """
73
 
        if identity.verifyPlainPassword(self.pw):
74
 
            # The identity checks out.
75
 
            characters = []
76
 
            # XXX REFACTOR: Hmm.  Is this next bit common behavior?
77
 
            r = self.factory.reality
78
 
            nm = r.getServiceName()
79
 
            for serviceName, perspectiveName in identity.getAllKeys():
80
 
                if serviceName == nm:
81
 
                    ### XXX FIXME
82
 
                    ### This can't really be done this way.
83
 
                    ### getPerspectiveNamed ought to be asynchronous.
84
 
                    characters.append(r.getPerspectiveNamed(perspectiveName))
85
 
            lc = len(characters)
86
 
            if lc == 1:
87
 
                p = characters[0]
88
 
            elif lc > 1:
89
 
                p = characters[0]
90
 
                self.transport.write("TODO: character selection menu\r\n")
91
 
            else:
92
 
                raise Unauthorized("that identity has no TR characters")
93
 
 
94
 
            p = p.attached(self, identity)
95
 
            self.player = p
96
 
            self.identity = identity
97
 
            self.transport.write("Hello "+self.player.name+", welcome to Reality!\r\n"+
98
 
                                 telnet.IAC+telnet.WONT+telnet.ECHO)
99
 
            self.mode = "Command"
100
 
        else:
101
 
            log.msg("incorrect password") 
102
 
            self.transport.loseConnection()
103
 
 
104
 
    def notLoggedIn(self, err):
105
 
        log.msg('requested bad username')
106
 
        self.transport.loseConnection()
107
 
 
108
 
    def processPending(self, pend):
109
 
        self.transport.write("Please hold...\r\n")
110
 
        return "Pending"
111
 
 
112
 
    def processCommand(self, cmd):
113
 
        """Execute a command as a player.
114
 
        """
115
 
        self.player.execute(cmd)
116
 
        return "Command"
117
 
 
118
 
    def connectionLost(self):
119
 
        """Disconnect player from this Intelligence, and clean up connection.
120
 
        """
121
 
        telnet.Telnet.connectionLost(self)
122
 
        if hasattr(self, 'player'):
123
 
            if hasattr(self.player, 'intelligence'):
124
 
                self.player.detached(self, self.identity)
125
 
 
126
 
    def seeName(self, name):
127
 
        """Display a focused name bracketed, in bold.
128
 
        """
129
 
        self.transport.write(telnet.BOLD_MODE_ON+"[ "+name+" ]"+telnet.BOLD_MODE_OFF+
130
 
                             "\r\n")
131
 
 
132
 
    def callRemote(self, key, *args, **kw):
133
 
        # pass-through of remote methods
134
 
        apply(getattr(self, key), args, kw)
135
 
 
136
 
 
137
 
    def seeItem(self, key, parent, value):
138
 
        """Display an item that's present.
139
 
        """
140
 
        self.transport.write(" "+value+"\r\n")
141
 
 
142
 
    def dontSeeItem(self, key, parent):
143
 
        """no-op; would be nonsensical over telnet.
144
 
        """
145
 
 
146
 
    def seeNoItems(self):
147
 
        """no-op; would be nonsensical over telnet.
148
 
        """
149
 
 
150
 
    def seeExit(self, direction):
151
 
        """Display a single exit.
152
 
        """
153
 
        self.transport.write("You can go "+direction+"\r\n")
154
 
 
155
 
    def dontSeeExit(self, direction):
156
 
        """no-op; would be nonsensical over telnet.
157
 
        """
158
 
 
159
 
    def seeNoExits(self):
160
 
        """no-op; would be nonsensical over telnet.
161
 
        """
162
 
 
163
 
    def seeDescription(self, key, description):
164
 
        """Displays a description.
165
 
        """
166
 
        self.transport.write(description+"\r\n")
167
 
 
168
 
    def dontSeeDescription(self, key):
169
 
        """no-op; would be nonsensical over telnet.
170
 
        """
171
 
 
172
 
    def seeNoDescriptions(self):
173
 
        """no-op; would be nonsensical over telnet.
174
 
        """
175
 
 
176
 
    def seeEvent(self, string):
177
 
        """Displays an event to the player.
178
 
        """
179
 
        self.transport.write(string+'\r\n')
180
 
 
181
 
    def request(self, question,default,ok,cancel):
182
 
        """Requests are not supported by this interface; calls cancel() immediately.
183
 
        """
184
 
        self.transport.write('edit operations not supported in telnet!\r\n')
185
 
        cancel()
186
 
 
187
 
 
188
 
 
189
 
class Spigot(protocol.Factory):
190
 
    """
191
 
    A telnet factory for twisted.reality.
192
 
    """
193
 
 
194
 
    def buildProtocol(self, addr):
195
 
        p = Hose()
196
 
        p.factory = self
197
 
        return p
198
 
    
199
 
    def __init__(self, world):
200
 
        """Initialize with a twisted.reality.Reality instance.
201
 
        """
202
 
        self.reality = world
203
 
 
204
 
class ThingWidget(widgets.StreamWidget):
205
 
    """A web-based interface to a twisted.reality.thing.Thing.
206
 
    """
207
 
    def __init__(self, thing):
208
 
        """Initialize with a particular thing.
209
 
        """
210
 
        self.thing = thing
211
 
 
212
 
    def getTitle(self, request):
213
 
        """Return a page title formatting the request.
214
 
        """
215
 
        session = request.getSession()
216
 
        return "Twisted Reality: %s" % self.thing.shortName(session.truser)
217
 
 
218
 
    def stream(self, write, request):
219
 
        """Display representation of a Thing (or move a Thing and redirect, depending on URI).
220
 
        """
221
 
        player = request.getSession().truser
222
 
        if request.args.has_key("action"):
223
 
            # cheating...
224
 
            # request.setHeader("refresh","0; URL=%s" % (request.prePathURL()))
225
 
            player.location = self.thing
226
 
            log.msg("Eep?")
227
 
            write("I have an action key! %s, %s" % (player.location, self.thing))
228
 
            # write("Redirecting...")
229
 
        write("<table><tr><td colspan=2>")
230
 
        write(self.thing.descriptionTo(player))
231
 
        write('<br><A HREF="%s?action=moveMe">Move Me Here</a>' %
232
 
              (request.prePathURL()))
233
 
        write("</td></tr><tr><td><ul>")
234
 
        for thing in self.thing.getThings(player):
235
 
            write('<LI><A HREF="%s">%s</A>' % (
236
 
                thing.thing_id,
237
 
                thing.presentPhrase(player)))
238
 
        if self.thing in player.locations:
239
 
            write('<hr><li><A HREF="%s">You are here.</a>' % (player.thing_id))
240
 
        write("</ul></td><td>")
241
 
        write("<UL>")
242
 
        for direc in self.thing.exits:
243
 
            dest = self.thing.findExit(direc)
244
 
            write("<LI>")
245
 
            write(direc)
246
 
            write(": ")
247
 
            write('<A HREF="%s">' % dest.thing_id)
248
 
            write(dest.shortName(player))
249
 
            write('</A>')
250
 
        write("</UL>")
251
 
        write("</td></tr></table>")
252
 
 
253
 
class Web(guard.ResourceGuard):
254
 
    def __init__(self, reality):
255
 
        guard.ResourceGuard.__init__(self, _Web(reality), reality, 'realIdent', 'truser')
256
 
 
257
 
class _Web(widgets.Gadget, widgets.StreamWidget):
258
 
    """A web interface to a twisted.reality.reality.Reality.
259
 
    """
260
 
    def __init__(self, in_reality):
261
 
        """Initialize with a reality.
262
 
        """
263
 
        widgets.Gadget.__init__(self)
264
 
        self.reality = in_reality
265
 
 
266
 
    def getWidget(self, name, request):
267
 
        """Get a Thing from this reality.
268
 
        """
269
 
        return ThingWidget(self.reality.getThingById(int(name)))
270
 
 
271
 
    def stream(self, write, request):
272
 
        """List all availble Things and there IDs
273
 
        """
274
 
        player = request.getSession().truser
275
 
        write('<UL>\n')
276
 
        for thing in self.reality.objects():
277
 
            np = thing.nounPhrase(player)
278
 
            write('<LI><A HREF="%s">%s</a>\n'% (str(thing.thing_id),np))
279
 
        write('</UL>\n')
280