Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: IM Server  (gelezen 6116 keer)

Offline Mij

  • Lid
IM Server
« Gepost op: 2009/06/26, 10:20:25 »
Ik was eventjes bezig met een servertje om een webbased IM-programmaatje te maken die niet van externe servers afhankelijk is. Valt te draaien door http://localhost:8000 te gebruiken in browser of je interne IP op te zoeken en een andere computer te gebruiken door http://<ip>:8000.

server.py:
from wsgiref.simple_server import make_server
import os
import string
import time
#hosts = ["127.0.0.1"]

messages = []
def send(environ, start_response):
    print environ
    if 'PATH_INFO' not in environ or environ['PATH_INFO'] == '/':
        status = '200 OK'
        headers = [('Content-type', 'text/html')]
        start_response(status, headers)
        return compose_IM(environ)
    else:
        status = '200 OK'
        path = environ["PATH_INFO"]
        if path.endswith(".png"):
            headers = [('Content-type', 'image/png')]
        elif path.endswith(".html"):
            headers = [('Content-type', 'text/html')]
            if path == '/index.html':
                start_response(status, headers)
                return compose_IM(environ)
        elif path.endswith(".js"):
            headers = [('Content-type', 'text/javascript')]
        else:
            headers = [('Content-type', 'text/html')]
        start_response(status, headers)
        file = open(os.path.dirname(__file__) + path)
        return file.readlines()

def compose_IM(environ):
    header = open(os.path.dirname(__file__) + "/index.html")
    footer = open(os.path.dirname(__file__) + "/footer.html")
    if environ['QUERY_STRING']: messages.append(environ['REMOTE_ADDR'] \
    + "("+ time.strftime("%H:%M:%S") + ")" + ": " \
    +  environ['QUERY_STRING'][8:].replace("+", " ") + "<br />")
    return header.readlines() + messages + footer.readlines()

httpd = make_server('', 8000, send)
httpd.serve_forever()
index.html:
<html>
  <head>
    <title>IMPerso</title>
  </head>
  <body>
    <br />
footer.html
 <form name="input" action="index.html" method="get">
    <input type="text" name="message" />
    <input type="submit" value="Send" />
  </form>
  <script type="text/javascript">
    document.input.message.focus();
  </script>
</body>
</html>

Ik wil een paar dingen weten:
1. Hoe kan je een bericht extraheren wanneer je gebruik maakt van de post methode? De get methode heeft als nadeel dat de url steeds veranderd en dat als je refresht het bericht dubbel staat.
2. Hoe kan je bestanden op de server downloaden van cliënt met post?
« Laatst bewerkt op: 2009/06/26, 11:48:25 door Mij »

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #1 Gepost op: 2009/06/26, 13:13:24 »
Ik kan er helaas zo niets over vinden.

Zelf ben ik Django aan het leren (ook een python gebaseerd webframework). Hierin is het gemakkelijk om de POST van een response op te halen. Ook kun je de IM berichten opslaan in een database.

Django is redelijk gemakkelijk te leren, en erg goed uitbreidbaar. Maar misschien wel een beetje overkill voor alleen maar een IM programma. Django is dan ook meer geschikt als een project wat groter begint te worden.
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

kajivar

  • Gast
Re: IM Server
« Reactie #2 Gepost op: 2009/06/27, 12:08:22 »
Waarom maak je niet gewoon een IM met PHP/MySQL/JS? Python is inderdaad beter voor ingewikkeldere webapplicaties, maar voor een IM client/server, is het makkelijker om een PHP/Ajax versie te maken. Ik heb het persoonlijk al een keertje gemaakt (wel lang geleden), en die deed het prima.

Verder kan ik je niet helpen met Python...

Succes!

Kaj-Ivar

Offline Mij

  • Lid
Re: IM Server
« Reactie #3 Gepost op: 2009/06/28, 15:37:07 »
Waarom maak je niet gewoon een IM met PHP/MySQL/JS? Python is inderdaad beter voor ingewikkeldere webapplicaties, maar voor een IM client/server, is het makkelijker om een PHP/Ajax versie te maken. Ik heb het persoonlijk al een keertje gemaakt (wel lang geleden), en die deed het prima.
Verder kan ik je niet helpen met Python...
Succes!
Kaj-Ivar

Ik wil het graag in Python doen. De bedoeling is dat uiteindelijk twee computers allebei server én cliënt zijn. Het nadeel is dat je voor server op het web je echte ip aan je computer moet toewijzen in plaats van je interne, wat bij een router standaard het geval is. Daarnaast hoef ik geen hele gecompliceerde webserver te draaien.
Het is nu bijna gelukt met BaseHTTPServer, heb alleen nog een klein vraagje.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import string,cgi,time
MESSAGES = 'Conversation started ' + time.strftime("%H:%M:%S")

class handler(BaseHTTPRequestHandler):

    def do_GET(self):
        try:
            print self.path
            if '?' in self.path:
                index = self.path.index('?')
                self.path = self.path[:index]
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            if self.path == '/' or self.path == '/index.html':
                f = open(os.path.dirname(__file__) + '/index.html')
                g = open(os.path.dirname(__file__) + '/footer.html')
                self.wfile.write(f.read() + MESSAGES + g.read())
                f.close()
                g.close()
                return
            f = open(os.path.dirname(__file__) + self.path)
            self.wfile.write(f.read())
            f.close()
            return
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)

    def do_POST(self):
        self.send_header('Content-type', 'text/html')
        self.send_response(200)
        self.end_headers()
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
        length = int(self.headers.getheader('content-length'))
        #files, todo integrate
        if ctype == 'multipart/form-data':
            query=cgi.parse_multipart(self.rfile, pdict)
            upfilecontent = query.get('upfile')
            self.wfile.write("<html>POST OK.<br /><br /></html>")
            self.wfile.write(upfilecontent[0])
        #text
        elif ctype == 'application/x-www-form-urlencoded':
            qs = self.rfile.read(length)
            query = cgi.parse_qs(qs, keep_blank_values=1)
            if query.has_key('message'):
                MESSAGES += '<br />' + query['message'][0]
                f = open(os.path.dirname(__file__) + '/index.html')
                g = open(os.path.dirname(__file__) + '/footer.html')
                self.wfile.write(f.read() + messages + g.read())
                f.close()
                g.close()
                return

def run(server_class=HTTPServer,
        handler_class=BaseHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler)
    httpd.serve_forever()
 
if __name__ == "__main__":
    run()
De regel MESSAGES += '<br />' + query['message'][0] geeft de foutmelding 'local variable 'MESSAGES' referenced before assignment', terwijl hij het in def do_GET wel doet?

Offline Mij

  • Lid
Re: IM Server
« Reactie #4 Gepost op: 2009/06/29, 07:48:53 »
Is nu gelukt, gewoon door messages aan begin class te zetten en dan handler.MESSAGES aan te roepen. def __init__ leek mij een betere manier maar dat lijkt niet te lukken.

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #5 Gepost op: 2009/06/29, 09:34:31 »
Het volgende zou moeten werken:
En messages liever niet met hoofdletters schrijven, omdat variabelen met hoofdletters gebruik worden voor variabelen die nooit veranderen (constanten dus)

class handler(BaseHTTPRequestHandler):
    def __init__(self):
        self.messages = 'Conversation started ' + time.strftime("%H:%M:%S")

    def do_POST(self):
        self.messages += '<br />' + query['message'][0]

Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Mij

  • Lid
Re: IM Server
« Reactie #6 Gepost op: 2009/06/29, 13:34:18 »
Het volgende zou moeten werken:
En messages liever niet met hoofdletters schrijven, omdat variabelen met hoofdletters gebruik worden voor variabelen die nooit veranderen (constanten dus)

class handler(BaseHTTPRequestHandler):
    def __init__(self):
        self.messages = 'Conversation started ' + time.strftime("%H:%M:%S")

    def do_POST(self):
        self.messages += '<br />' + query['message'][0]

Dat werkt dus helaas niet, de def_init moet dan een aantal extra variabelen hebben en de POST en GET methoden werken niet meer. Ik heb MESSAGES nu met kleine letters geschreven.

Inmiddels is het programmaatje iets interessanter geworden. HTML gebruiken kan in principe niet meer en er is ondersteuning voor plaatjes, video's en links door gebruik van img:, video: en link:. Er is wel nog een probleempje: op een of andere manier worden slashes verkeerd geïntepreteerd. Daardoor worden geopende elementen niet afgesloten.
Zo ziet de code van pagina eruit:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <title>personim</title>
    <link rel="icon" type="image/gif" href="msn_ico.jpg" />
  </head>
  <body>
    <font size="2">
    <a href="index.html">Refresh this page</a><br />

    <form name="input" action="index.html" method="post">Conversation started at 13:11:19<br />192.168.1.71(13:11:33): Lol<br />192.168.1.71(13:11:36): Mooi<br />192.168.1.71(13:11:37): Dus<br />192.168.1.71(13:11:47): <video src="http://tinyvid.tv/file/p8xrbyh7zjph.ogg" controls="true" /<br />192.168.1.71    <input type="text" name="message" />
    <input type="submit" value="Send" />

en die van een selectie (Firefox, View selection source).

<font size="2">Conversation started at 13:11:19<br>192.168.1.71(13:11:33): Lol<br>192.168.1.71(13:11:36): Mooi<br>192.168.1.71(13:11:37): Dus<br>192.168.1.71(13:11:47): <video tabindex="0" src="http://tinyvid.tv/file/p8xrbyh7zjph.ogg" controls="true"><br>192.168.1.71    <input name="message" type="text">
    <input value="Send" type="submit">
 
  </video></font>
Merk op dat de slashes van programmacode zijn verdwenen. Hoe zou dat komen?

Zo is de code nu:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import string,cgi,time

class handler(BaseHTTPRequestHandler):
    messages = 'Conversation started at ' + time.strftime("%H:%M:%S")
    previous = ''
    def do_GET(self):
        try:
            if '?' in self.path:
                index = self.path.index('?')
                self.path = self.path[:index]
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            if self.path == '/' or self.path == '/index.html':
                f = open(os.path.dirname(__file__) + '/index.html')
                g = open(os.path.dirname(__file__) + '/footer.html')
                self.wfile.write(f.read() + handler.messages + '<br />' + self.client_address[0] + g.read())
                f.close()
                g.close()
                return
            f = open(os.path.dirname(__file__) + self.path)
            self.wfile.write(f.read())
            f.close()
            return
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)

    def do_POST(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
        length = int(self.headers.getheader('content-length'))
        #files, todo integrate
        if ctype == 'multipart/form-data':
            query=cgi.parse_multipart(self.rfile, pdict)
            upfilecontent = query.get('upfile')
            self.wfile.write("<html>POST OK.<br /><br /></html>")
            self.wfile.write(upfilecontent[0])
        #text
        elif ctype == 'application/x-www-form-urlencoded':
            if length > 400:
                handler.MESSAGES += '<br />' + self.client_address[0] \
                    + '(' + time.strftime("%H:%M:%S")+ '): ' + '<i>Message too long</i>'
                f = open(os.path.dirname(__file__) + '/index.html')
                g = open(os.path.dirname(__file__) + '/footer.html')
                self.wfile.write(f.read() + handler.messages + '<br />' + self.client_address[0] + g.read())
                return
            qs = self.rfile.read(length)
            query = cgi.parse_qs(qs, keep_blank_values=1)
            if query.has_key('message'):
                query = query['message'][0]
                if handler.previous != query:
                    query = query.replace('<','&lt;')
                    query = query.replace('>','&gt;')
                    while 'vid:' in query:
                        index = query.index('vid:') + 4
                        if len(query[index:]) == 0 or query[index] == " ":
                            query = query.replace('vid:', 'vid&#58;', 1)
                            break
                        if " " in query[index:]:
                            source = query[index:query.index(" ")]
                        else:
                            source = query[index:]
                        if source.endswith('.ogg') or source.endswith('.ogv'):
                            query = query.replace('vid:' + source, '<video src="' + source \
                                + '" controls="true" /')
                        else:
                            query = query.replace('vid:'+ source, '<i>Video format not supported: </i><a href="' \
                                + source +'" />', 1)

                    while 'img:' in query:
                        index = query.index('img:') + 4
                        if len(query[index:]) == 0 or query[index] == " ":
                            query = query.replace('img:', 'img&#58;', 1)
                            break
                        if " " in query[index:]:
                            source = query[index:query.index(" ")]
                        else:
                            source = query[index:]
                        if source.endswith('.png') or source.endswith('.jpg') or source.endswith('.gif'):
                            query = query.replace('img:' + source, '<img src="' + source \
                                + '" alt="' + source + '" />')
                        else:
                            query = query.replace('img:'+ source, '<i>Image format not supported: </i><a href="' \
                                + source +'" />', 1)

                    while 'link:' in query:
                        index = query.index('link:') + 5
                        if len(query[index:]) == 0 or query[index] == " ":
                            query = query.replace('link:', 'link&#58;', 1)
                            break
                        if " " in query[index:]:
                            source = query[index:query.index(" ")]
                        else:
                            source = query[index:]
                        query = query.replace('link:' + source, '<a href="' + source \
                                + '" alt="' + source + '" />')

                    handler.messages += '<br />' + self.client_address[0] + '(' + time.strftime("%H:%M:%S")+ '): ' + query
                    handler.previous = query
                f = open(os.path.dirname(__file__) + '/index.html')
                g = open(os.path.dirname(__file__) + '/footer.html')
                self.wfile.write(f.read() + handler.messages + '<br />' + self.client_address[0] + g.read())
                f.close()
                g.close()
                return

def run(server_class=HTTPServer,
        handler_class=BaseHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler)
    httpd.serve_forever()
 
if __name__ == "__main__":
    run()

Valt hier http://personim.googlecode.com/files/personimdev0.tar.gz te downloaden

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #7 Gepost op: 2009/06/29, 13:44:54 »
Het volgende zou moeten werken:
En messages liever niet met hoofdletters schrijven, omdat variabelen met hoofdletters gebruik worden voor variabelen die nooit veranderen (constanten dus)

class handler(BaseHTTPRequestHandler):
    def __init__(self):
        self.messages = 'Conversation started ' + time.strftime("%H:%M:%S")

    def do_POST(self):
        self.messages += '<br />' + query['message'][0]

Dat werkt dus helaas niet, de def_init moet dan een aantal extra variabelen hebben en de POST en GET methoden werken niet meer. Ik heb MESSAGES nu met kleine letters geschreven.

Door zelf een def __init__ te maken overschrijf je de __init__ van de BaseHTTPRequestHandler. Dus zul je zelf de init daarvan moeten uitvoeren

class handler(BaseHTTPRequestHandler):
    def __init__(self):
        BaseHTTPRequestHandler.__init__(self):
        self.messages = 'Conversation started ' + time.strftime("%H:%M:%S")

    def do_POST(self):
        self.messages += '<br />' + query['message'][0]

Ik weet niet welke variabele je de __init__ mee moet geven, maar ik dacht 'self'
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #8 Gepost op: 2009/06/29, 14:03:42 »
Als ik het project zo zie vorderen, denk ik toch dat Django niet zo'n slechte optie is. Vooral in combi met jQuery voor ajax requests. Dit zou een veel stabieler, en meer gestructureerde code opleveren. Tevens is het hierdoor gemakkelijk uitbreidbaar.

Ik ben de laatste tijd ook veel met Django bezig. Als je wilt kan ik je er wel bij helpen
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Mij

  • Lid
Re: IM Server
« Reactie #9 Gepost op: 2009/06/29, 14:27:50 »
Is goed!
Hoe zou je dat in elkaar willen zetten?
Waar zou ik het project hosten (Launchpad, Google etc.)?

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #10 Gepost op: 2009/06/29, 14:32:33 »
Het enige wat we nodig hebben is een versie control systeem. Dus zoek maar een leuke uit. Ik heb zelf geen voorkeur voor Google of Lauchpad. Kies maar een leuke naam en past de link zodat ik mee kan helpen.
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Mij

  • Lid
Re: IM Server
« Reactie #11 Gepost op: 2009/06/29, 14:39:12 »

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #12 Gepost op: 2009/06/29, 14:47:00 »
Kun je mij toevoegen, ik sta bij de subscibers

Volgens mij moeten we een groep aanmaken, en dan een group branche.
« Laatst bewerkt op: 2009/06/29, 14:49:32 door Ronnie »
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Mij

  • Lid
Re: IM Server
« Reactie #13 Gepost op: 2009/06/29, 14:52:32 »
Enig idee hoe je dat doet?

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: IM Server
« Reactie #14 Gepost op: 2009/06/29, 14:54:06 »
Even kijken hoe dat bij Ludem gedaan is, en anders hier:
https://help.launchpad.net/Code/TeamBranches
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline Mij

  • Lid
Re: IM Server
« Reactie #15 Gepost op: 2009/06/29, 15:06:50 »
Je zit nu bij het team.

Offline Mij

  • Lid
Re: IM Server
« Reactie #16 Gepost op: 2009/06/30, 19:41:47 »
Inmiddels is er een aardige basis gelegd.
personim
Je kan de code bemachtigen door
bzr branch lp:~personim/personim/Main
Iedereen die wil meehelpen is natuurlijk welkom, we zitten echter nog in een erg vroege fase.