Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / core / howto / tutorial / listings / finger / finger22.py
1 # Do everything properly, and componentize
2 from twisted.application import internet, service
3 from twisted.internet import protocol, reactor, defer
4 from twisted.words.protocols import irc
5 from twisted.protocols import basic
6 from twisted.python import components
7 from twisted.web import resource, server, static, xmlrpc, microdom
8 from twisted.spread import pb
9 from zope.interface import Interface, implements
10 from OpenSSL import SSL
11 import cgi
12
13 class IFingerService(Interface):
14
15     def getUser(user):
16         """
17         Return a deferred returning a string.
18         """
19
20     def getUsers():
21         """
22         Return a deferred returning a list of strings.
23         """
24
25
26 class IFingerSetterService(Interface):
27
28     def setUser(user, status):
29         """
30         Set the user's status to something.
31         """
32
33
34 def catchError(err):
35     return "Internal error in server"
36
37
38 class FingerProtocol(basic.LineReceiver):
39
40     def lineReceived(self, user):
41         d = self.factory.getUser(user)
42         d.addErrback(catchError)
43         def writeValue(value):
44             self.transport.write(value+'\r\n')
45             self.transport.loseConnection()
46         d.addCallback(writeValue)
47
48
49 class IFingerFactory(Interface):
50
51     def getUser(user):
52         """
53         Return a deferred returning a string.
54         """
55
56     def buildProtocol(addr):
57         """
58         Return a protocol returning a string.
59         """
60
61
62 class FingerFactoryFromService(protocol.ServerFactory):
63
64     implements(IFingerFactory)
65
66     protocol = FingerProtocol
67
68     def __init__(self, service):
69         self.service = service
70
71     def getUser(self, user):
72         return self.service.getUser(user)
73
74 components.registerAdapter(FingerFactoryFromService,
75                            IFingerService,
76                            IFingerFactory)
77
78
79 class FingerSetterProtocol(basic.LineReceiver):
80
81     def connectionMade(self):
82         self.lines = []
83
84     def lineReceived(self, line):
85         self.lines.append(line)
86
87     def connectionLost(self, reason):
88         if len(self.lines) == 2:
89             self.factory.setUser(*self.lines)
90
91
92 class IFingerSetterFactory(Interface):
93
94     def setUser(user, status):
95         """
96         Return a deferred returning a string.
97         """
98
99     def buildProtocol(addr):
100         """
101         Return a protocol returning a string.
102         """
103
104
105 class FingerSetterFactoryFromService(protocol.ServerFactory):
106
107     implements(IFingerSetterFactory)
108
109     protocol = FingerSetterProtocol
110
111     def __init__(self, service):
112         self.service = service
113
114     def setUser(self, user, status):
115         self.service.setUser(user, status)
116
117
118 components.registerAdapter(FingerSetterFactoryFromService,
119                            IFingerSetterService,
120                            IFingerSetterFactory)
121
122
123 class IRCReplyBot(irc.IRCClient):
124
125     def connectionMade(self):
126         self.nickname = self.factory.nickname
127         irc.IRCClient.connectionMade(self)
128
129     def privmsg(self, user, channel, msg):
130         user = user.split('!')[0]
131         if self.nickname.lower() == channel.lower():
132             d = self.factory.getUser(msg)
133             d.addErrback(catchError)
134             d.addCallback(lambda m: "Status of %s: %s" % (msg, m))
135             d.addCallback(lambda m: self.msg(user, m))
136
137
138 class IIRCClientFactory(Interface):
139
140     """
141     @ivar nickname
142     """
143
144     def getUser(user):
145         """
146         Return a deferred returning a string.
147         """
148
149     def buildProtocol(addr):
150         """
151         Return a protocol.
152         """
153
154
155 class IRCClientFactoryFromService(protocol.ClientFactory):
156
157     implements(IIRCClientFactory)
158
159     protocol = IRCReplyBot
160     nickname = None
161
162     def __init__(self, service):
163         self.service = service
164
165     def getUser(self, user):
166         return self.service.getUser(user)
167
168 components.registerAdapter(IRCClientFactoryFromService,
169                            IFingerService,
170                            IIRCClientFactory)
171
172
173 class UserStatusTree(resource.Resource):
174
175     def __init__(self, service):
176         resource.Resource.__init__(self)
177         self.service=service
178
179         # add a specific child for the path "RPC2"
180         self.putChild("RPC2", UserStatusXR(self.service))
181
182         # need to do this for resources at the root of the site
183         self.putChild("", self)
184
185     def _cb_render_GET(self, users, request):
186         userOutput = ''.join(["<li><a href=\"%s\">%s</a></li>" % (user, user)
187                 for user in users])
188         request.write("""
189             <html><head><title>Users</title></head><body>
190             <h1>Users</h1>
191             <ul>
192             %s
193             </ul></body></html>""" % userOutput)
194         request.finish()
195         
196     def render_GET(self, request):
197         d = self.service.getUsers()
198         d.addCallback(self._cb_render_GET, request)
199
200         # signal that the rendering is not complete
201         return server.NOT_DONE_YET
202
203     def getChild(self, path, request):
204         return UserStatus(user=path, service=self.service)
205
206 components.registerAdapter(UserStatusTree, IFingerService, resource.IResource)
207
208
209 class UserStatus(resource.Resource):
210
211     def __init__(self, user, service):
212         resource.Resource.__init__(self)
213         self.user = user
214         self.service = service
215
216     def _cb_render_GET(self, status, request):
217         request.write("""<html><head><title>%s</title></head>
218         <body><h1>%s</h1>
219         <p>%s</p>
220         </body></html>""" % (self.user, self.user, status))
221         request.finish()
222     
223     def render_GET(self, request):
224         d = self.service.getUser(self.user)
225         d.addCallback(self._cb_render_GET, request)
226
227         # signal that the rendering is not complete
228         return server.NOT_DONE_YET
229
230
231 class UserStatusXR(xmlrpc.XMLRPC):
232
233     def __init__(self, service):
234         xmlrpc.XMLRPC.__init__(self)
235         self.service = service
236
237     def xmlrpc_getUser(self, user):
238         return self.service.getUser(user)
239
240     def xmlrpc_getUsers(self):
241         return self.service.getUsers()
242
243
244 class IPerspectiveFinger(Interface):
245
246     def remote_getUser(username):
247         """
248         Return a user's status.
249         """
250
251     def remote_getUsers():
252         """
253         Return a user's status.
254         """
255
256 class PerspectiveFingerFromService(pb.Root):
257
258     implements(IPerspectiveFinger)
259
260     def __init__(self, service):
261         self.service = service
262
263     def remote_getUser(self, username):
264         return self.service.getUser(username)
265
266     def remote_getUsers(self):
267         return self.service.getUsers()
268
269 components.registerAdapter(PerspectiveFingerFromService,
270                            IFingerService,
271                            IPerspectiveFinger)
272
273
274 class FingerService(service.Service):
275
276     implements(IFingerService)
277
278     def __init__(self, filename):
279         self.filename = filename
280         self.users = {}
281
282     def _read(self):
283         self.users.clear()
284         for line in file(self.filename):
285             user, status = line.split(':', 1)
286             user = user.strip()
287             status = status.strip()
288             self.users[user] = status
289         self.call = reactor.callLater(30, self._read)
290
291     def getUser(self, user):
292         return defer.succeed(self.users.get(user, "No such user"))
293
294     def getUsers(self):
295         return defer.succeed(self.users.keys())
296
297     def startService(self):
298         self._read()
299         service.Service.startService(self)
300
301     def stopService(self):
302         service.Service.stopService(self)
303         self.call.cancel()
304
305
306 class ServerContextFactory:
307
308     def getContext(self):
309         """
310         Create an SSL context.
311
312         This is a sample implementation that loads a certificate from a file
313         called 'server.pem'.
314         """
315         ctx = SSL.Context(SSL.SSLv23_METHOD)
316         ctx.use_certificate_file('server.pem')
317         ctx.use_privatekey_file('server.pem')
318         return ctx
319
320
321 application = service.Application('finger', uid=1, gid=1)
322 f = FingerService('/etc/users')
323 serviceCollection = service.IServiceCollection(application)
324 f.setServiceParent(serviceCollection)
325 internet.TCPServer(79, IFingerFactory(f)
326                    ).setServiceParent(serviceCollection)
327 site = server.Site(resource.IResource(f))
328 internet.TCPServer(8000, site
329                    ).setServiceParent(serviceCollection)
330 internet.SSLServer(443, site, ServerContextFactory()
331                    ).setServiceParent(serviceCollection)
332 i = IIRCClientFactory(f)
333 i.nickname = 'fingerbot'
334 internet.TCPClient('irc.freenode.org', 6667, i
335                    ).setServiceParent(serviceCollection)
336 internet.TCPServer(8889, pb.PBServerFactory(IPerspectiveFinger(f))
337                    ).setServiceParent(serviceCollection)