From piers@cs.su.oz.au Thu Jul 11 03:12:15 2002 From: piers@cs.su.oz.au (Piers Lauder) Date: Thu, 11 Jul 2002 12:12:15 +1000 Subject: [Medusa-dev] medusa-0.5.2 errata Message-ID: <1026354174.17.978081823@cs.su.oz.au> I've just downloaded the latest version of medusa from http://oedipus.sourceforge.net/medusa/ and found a problem when using it with Python2.2 (problem also probably applies to other versions). Here's the fix, just in case it helps anyone else. (The diff below is against my previous (fixed) version - medusa-src-20000601.) time.mktime takes a 9-tuple, not 9 args: : gemini medusa ; diff -B -b medusa-src-20000601/logger.py medusa-0.5.2/logger.py 106c105 < return time.mktime((yr,mo,day+1, 0,0,0, 0,0,-1)) --- > return time.mktime(yr,mo,day+1, 0,0,0, 0,0,-1) 108c107 < return time.mktime((yr,mo,day-wd+7, 0,0,0, 0,0,-1)) # wd(monday)==0 --- > return time.mktime(yr,mo,day-wd+7, 0,0,0, 0,0,-1) # wd(monday)==0 110c109 < return time.mktime((yr,mo+1,1, 0,0,0, 0,0,-1)) --- > return time.mktime(yr,mo+1,1, 0,0,0, 0,0,-1) ________________________________________________________________________________ Schl of Inf Tec, Sydney University, Madsen Bldg F09, Sydney NSW 2006, Australia. Phone: +61 2 9351 2824 Fax: +61 2 9351 3838 http://www.it.usyd.edu.au/~piers From akuchlin@mems-exchange.org Thu Jul 11 14:03:08 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Thu, 11 Jul 2002 09:03:08 -0400 Subject: [Medusa-dev] medusa-0.5.2 errata In-Reply-To: <1026354174.17.978081823@cs.su.oz.au> References: <1026354174.17.978081823@cs.su.oz.au> Message-ID: <20020711130308.GC27464@ute.mems-exchange.org> On Thu, Jul 11, 2002 at 12:12:15PM +1000, Piers Lauder wrote: >Here's the fix, just in case it helps anyone else. Applied to CVS; thanks! There have been a few bugfixes since 0.5.2, so we should really make a new release. Does anyone know of other 0.5.2 bugs (or problems with 0.5.2 that aren't formally bugs)? --amk From leslie@linuxkorea.co.kr Fri Jul 12 23:06:54 2002 From: leslie@linuxkorea.co.kr (=?euc-kr?B?wMy1v8HY?=) Date: Sat, 13 Jul 2002 07:06:54 +0900 Subject: [Medusa-dev] medusa-0.5.2 has critical Bug. Message-ID: <005901c229f0$6fd36510$4b1dd8d2@leslie> When I send a packet larger than buffer size, your module DON'T SEND trailing packet! (This bug appear in HTTP Server, XML-RPC Server). medusa-0.5.2/procuder.py. ==================================== class composite_producer: "combine a fifo of producers into one" def __init__ (self, producers): self.producers = producers def more (self): while len(self.producers): < p = self.procuders.pop(0) --- > p = self.producers[0] d = p.more() if d: return d else: < self.producers.pop() --- > self.producers.pop(0) else: return '' ==================================== Enjoy Python!! From bortzmeyer@nic.fr Fri Jul 26 13:29:04 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Fri, 26 Jul 2002 14:29:04 +0200 Subject: [Medusa-dev] XML-RPC replies silently truncated to 1024 characters Message-ID: <20020726122904.GA31954@nic.fr> I have an XML-RPC application, using Python, xmlrpclib 1.0b4 and Medusa 0.5.2, which was working fine. Suddenly, it started producing not well-formed XML, crashing clients, and I can see why, when running under a debugger: when the response is longer than 1024 characters, it is silently truncated. Where is that bug? I've searched 1024 in the various source files but without finding something convincing. From bortzmeyer@nic.fr Fri Jul 26 09:27:05 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Fri, 26 Jul 2002 10:27:05 +0200 Subject: [Medusa-dev] XML-RPC Validator in Python? Message-ID: <20020726082705.GA29264@nic.fr> Does anyone has a test suite for the Validator written in Python? It is to include in my server for validation. I'll write it if there is none. From bortzmeyer@nic.fr Fri Jul 26 09:04:44 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Fri, 26 Jul 2002 10:04:44 +0200 Subject: [Medusa-dev] Patch for medusa's XML-RPC handler Message-ID: <20020726080444.GA16209@eureg.org> ---------------------- multipart/mixed attachment Hello, Thank you for taking over the maintenance of this very useful tool. I send you a small patch which fixes two things in Medusa's XML-RPC handler, xmlrpc_handler.py: 1) it adds the Content-length header which is mandatory, according to the XML-RPC specification. (The current version of Medusa fails validation, see ) 2) it does not wrap the exception in an xmlrpllib.Fault if the exception is already such a Fault. It allows applications to raise their own xmlrpllib.Fault, with their own faultCode. Thanks again and good luck. ---------------------- multipart/mixed attachment *** /usr/lib/python2.1/site-packages/medusa/xmlrpc_handler.py Wed Mar 20 18:37:48 2002 --- ./xmlrpc_handler.py Fri Jul 26 09:59:30 2002 *************** *** 5,13 **** # Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com) ! VERSION = "$Id: xmlrpc_handler.py,v 1.4 2002/03/20 17:37:48 amk Exp $" ! import http_server import xmlrpclib import string --- 5,15 ---- # Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com) ! # This version modified and maintained byStephane Bortzmeyer ! VERSION = "$Id: xmlrpc_handler.py,v 1.2 2002/07/26 07:59:30 bortzmeyer Exp $" ! ! from medusa import http_server import xmlrpclib import string *************** *** 38,47 **** response = self.call (method, params) if type(response) != type(()): response = (response,) except: ! # report exception back to server response = xmlrpclib.dumps ( ! xmlrpclib.Fault (1, "%s:%s" % (sys.exc_type, sys.exc_value)) ) else: response = xmlrpclib.dumps (response, methodresponse=1) --- 40,51 ---- response = self.call (method, params) if type(response) != type(()): response = (response,) + except xmlrpclib.Fault, e: + response = xmlrpclib.dumps (sys.exc_value) except: ! # report exception back to client response = xmlrpclib.dumps ( ! xmlrpclib.Fault (500, "%s:%s" % (sys.exc_type, sys.exc_value)) ) else: response = xmlrpclib.dumps (response, methodresponse=1) *************** *** 51,56 **** --- 55,61 ---- else: # got a valid XML RPC response request['Content-Type'] = 'text/xml' + request['Content-Length'] = len(str(response)) request.push (response) request.done() ---------------------- multipart/mixed attachment-- From bortzmeyer@nic.fr Fri Jul 26 15:45:24 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Fri, 26 Jul 2002 16:45:24 +0200 Subject: [Medusa-dev] Re: XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020726122904.GA31954@nic.fr> References: <20020726122904.GA31954@nic.fr> Message-ID: <20020726144524.GA1164@nic.fr> On Fri, Jul 26, 2002 at 02:29:04PM +0200, Stephane Bortzmeyer wrote a message of 14 lines which said: > I have an XML-RPC application, using Python, xmlrpclib 1.0b4 and > Medusa 0.5.2, which was working fine. > > Suddenly, it started producing not well-formed XML, crashing clients, > and I can see why, when running under a debugger: when the response is > longer than 1024 characters, it is silently truncated. > > Where is that bug? I've searched 1024 in the various source files but > without finding something convincing. I've ported the application to BaseHTTPServer and it works perfectly. Hence, it is a Medusa bug but I cannot yet tell where it is. From larry.tami@gte.net Sun Aug 11 04:20:45 2002 From: larry.tami@gte.net (Larry Wright) Date: Sat, 10 Aug 2002 22:20:45 -0500 Subject: [Medusa-dev] unix_authorizer and /etc/shadow Message-ID: <200208102220.45155.larry.tami@gte.net> Hello,=20 Has anyone hacked the unix_authorizer class to work with systems using sh= adow=20 passwords? Or is my only option to maintain a separate ftp user/password=20 file? Thanks in advance Larry From abo@minkirri.apana.org.au Mon Aug 12 00:39:08 2002 From: abo@minkirri.apana.org.au (Donovan Baarda) Date: Mon, 12 Aug 2002 09:39:08 +1000 Subject: [Medusa-dev] unix_authorizer and /etc/shadow In-Reply-To: <200208102220.45155.larry.tami@gte.net> References: <200208102220.45155.larry.tami@gte.net> Message-ID: <20020811233908.GA28386@minkirri.apana.org.au> On Sat, Aug 10, 2002 at 10:20:45PM -0500, Larry Wright wrote: > Hello, > Has anyone hacked the unix_authorizer class to work with systems using shadow > passwords? Or is my only option to maintain a separate ftp user/password > file? Hmmm... I haven't looked at that for ages. I would think some sort of PAM setup would be best... there are python PAM modules I believe. -- ---------------------------------------------------------------------- ABO: finger abo@minkirri.apana.org.au for more info, including pgp key ---------------------------------------------------------------------- From sergio.lobo@synergyconsulting.biz Wed Aug 14 11:23:06 2002 From: sergio.lobo@synergyconsulting.biz (Sergio Lobo) Date: Wed, 14 Aug 2002 12:23:06 +0200 Subject: [Medusa-dev] Medusa for Jython Message-ID: Hello, I would like to have medusa installed correctly in Jython. Is that possible? The installation worked perfectly with Python but I am having problems with Jython. Best regards, Sergio Lobo From amk@amk.ca Tue Aug 20 01:23:14 2002 From: amk@amk.ca (Andrew Kuchling) Date: Mon, 19 Aug 2002 20:23:14 -0400 Subject: [Medusa-dev] Medusa for Jython In-Reply-To: Message-ID: <04129FB9-B3D3-11D6-BF9D-000393B6F06C@amk.ca> On Wednesday, August 14, 2002, at 06:23 AM, Sergio Lobo wrote: > I would like to have medusa installed correctly in Jython. Is that > possible? > The installation worked perfectly with Python but I am having problems > with > Jython. I'd be quite surprised if Medusa worked with Jython at all, because it relies heavily on the select module, and select() isn't supported under Java. I believe Jython may have a module that emulates select()'s behaviour using multiple threads, but Medusa is likely to strain it to the breaking point. --amk From hbl@st-andrews.ac.uk Tue Sep 10 18:42:03 2002 From: hbl@st-andrews.ac.uk (Hamish Lawson) Date: Tue, 10 Sep 2002 18:42:03 +0100 Subject: [Medusa-dev] Incomplete response for /status on some Windows browsers Message-ID: <5.1.1.6.0.20020910183552.0356d688@spey.st-andrews.ac.uk> [I sent this message to the list before, but a day later it still hadn't shown up in the web archives. In case my post was rejected because I wasn't subscribed at the time, I've since subscribed and am now sending the message again. My apologies to the list if you have already received this.] When fetching the /status page from a Medusa HTTP server, I'm finding that some browsers get a truncated page or none at all and the browser keeps waiting for the response to complete. The browsers experiencing the problem are IE 5.5 and Opera 6.05, while Netscape 4.8 is fine; these are all running on Windows 2000. Static pages (some of them lengthy) seem to be served fine. The Medusa HTTP server is running on Solaris 8 for Sparc using Python 2.2. Hamish Lawson From bortzmeyer@nic.fr Tue Sep 17 10:35:32 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Tue, 17 Sep 2002 11:35:32 +0200 Subject: [Medusa-dev] [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: References: <20020726122904.GA31954@nic.fr> Message-ID: <20020917093532.GC12553@nic.fr> ---------------------- multipart/mixed attachment On Fri, Jul 26, 2002 at 11:45:54PM +0200, Klaus Alexander Seistrup wrote a message of 50 lines which said: > > Suddenly, it started producing not well-formed XML, crashing > > clients, and I can see why, when running under a debugger: when > > the response is longer than 1024 characters, it is silently > > truncated. > > I had a similar problem with Medusa a couple of months ago: I could ... > I sent a bug report to A.M. Kuchling, but have yet to receive a reply. Here is a patch which works for me. The bug is in http_server which does not check that the default buffer size is sufficient for the reply. I add a test script as well. ---------------------- multipart/mixed attachment --- /home/stephane/tmp/medusa-0.5.2/http_server.py Mon Mar 25 15:26:29 2002 +++ ./http_server.py Sun Sep 15 21:40:59 2002 @@ -156,7 +156,7 @@ def push (self, thing): if type(thing) == type(''): - self.outgoing.append(producers.simple_producer (thing)) + self.outgoing.append(producers.simple_producer(thing,buffer_size=len(thing))) else: self.outgoing.append(thing) ---------------------- multipart/mixed attachment #!/usr/bin/python from xmlrpclib import Server import sys # The bug is in Medusa, produces.py; http_server uses simple_producer which limits to its buffer_size. # Workaround: increase the buffer size # Solution: change http_server to use the buffer size it needs. # If num >= 900, Medusa truncates the reply and of course everything fails ("missing tag") if len(sys.argv) <= 1: num = 8 else: num = int(sys.argv[1]) s=Server('http://localhost:8080/') print s.echoStructTest('X'*num) ---------------------- multipart/mixed attachment-- From akuchlin@mems-exchange.org Wed Sep 18 20:25:29 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Wed, 18 Sep 2002 15:25:29 -0400 Subject: [Medusa-dev] [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020917093532.GC12553@nic.fr> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> Message-ID: <20020918192529.GA25295@ute.mems-exchange.org> On Tue, Sep 17, 2002 at 11:35:32AM +0200, Stephane Bortzmeyer wrote: >Here is a patch which works for me. The bug is in http_server which >does not check that the default buffer size is sufficient for the >reply. I add a test script as well. simple_producer is a very small class, and I see no way it would just truncate data larger than its buffer size. class simple_producer: "producer for a string" def __init__ (self, data, buffer_size=1024): self.data = data self.buffer_size = buffer_size def more (self): if len (self.data) > self.buffer_size: result = self.data[:self.buffer_size] self.data = self.data[self.buffer_size:] return result else: result = self.data self.data = '' return result (Unless this is a multithreaded program, and two threads are running the more() method at the same time... in that case more() might well return bogus results.) The bug must be somewhere else; maybe something is calling .more() exactly once and never again. The only relevant caller of more() I can find is refill_buffer() in asynchat.py, but after a casual reading, that code looks OK. Anyone got some more clues? --amk From akuchlin@mems-exchange.org Wed Sep 18 20:31:33 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Wed, 18 Sep 2002 15:31:33 -0400 Subject: [Medusa-dev] [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020917093532.GC12553@nic.fr> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> Message-ID: <20020918193133.GA25386@ute.mems-exchange.org> Actually, does the patch at http://mail.python.org/pipermail-21/medusa-dev/2002/000776.html help? Or are you seeing this with the current CVS, which has the patch applied? --amk From bortzmeyer@nic.fr Mon Sep 23 09:33:14 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Mon, 23 Sep 2002 10:33:14 +0200 Subject: [Medusa-dev] Re: [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020918193133.GA25386@ute.mems-exchange.org> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> <20020918193133.GA25386@ute.mems-exchange.org> Message-ID: <20020923083314.GA18220@nic.fr> On Wed, Sep 18, 2002 at 03:31:33PM -0400, Andrew Kuchling wrote a message of 6 lines which said: > Or are you seeing this with the current CVS, which has the patch > applied? [Since there is no link to the CVS from , I redirect people to .] The current CVS seems broken, nothing works at all, every client gets a: xmlrpclib.ProtocolError: From bortzmeyer@nic.fr Mon Sep 23 09:33:58 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Mon, 23 Sep 2002 10:33:58 +0200 Subject: [Medusa-dev] Re: [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020918192529.GA25295@ute.mems-exchange.org> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> <20020918192529.GA25295@ute.mems-exchange.org> Message-ID: <20020923083358.GB18220@nic.fr> On Wed, Sep 18, 2002 at 03:25:29PM -0400, Andrew Kuchling wrote a message of 36 lines which said: > simple_producer is a very small class, and I see no way it would just > truncate data larger than its buffer size. The only thing I can say is that my patch "works for me" (tm). > (Unless this is a multithreaded program, No. From akuchlin@mems-exchange.org Mon Sep 23 13:41:55 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Mon, 23 Sep 2002 08:41:55 -0400 Subject: [Medusa-dev] Re: [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020923083314.GA18220@nic.fr> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> <20020918193133.GA25386@ute.mems-exchange.org> <20020923083314.GA18220@nic.fr> Message-ID: <20020923124155.GC3361@ute.mems-exchange.org> On Mon, Sep 23, 2002 at 10:33:14AM +0200, Stephane Bortzmeyer wrote: >The current CVS seems broken, nothing works at all, every client gets >a: >xmlrpclib.ProtocolError: Using what script? The one in xmlrpc_handler.py is working fine for me. --amk From bortzmeyer@nic.fr Wed Sep 25 11:23:45 2002 From: bortzmeyer@nic.fr (Stephane Bortzmeyer) Date: Wed, 25 Sep 2002 12:23:45 +0200 Subject: [Medusa-dev] Re: [Medusa bug and patch] XML-RPC replies silently truncated to 1024 characters In-Reply-To: <20020923124155.GC3361@ute.mems-exchange.org> References: <20020726122904.GA31954@nic.fr> <20020917093532.GC12553@nic.fr> <20020918193133.GA25386@ute.mems-exchange.org> <20020923083314.GA18220@nic.fr> <20020923124155.GC3361@ute.mems-exchange.org> Message-ID: <20020925102345.GA13549@nic.fr> On Mon, Sep 23, 2002 at 08:41:55AM -0400, Andrew Kuchling wrote a message of 14 lines which said: > >The current CVS seems broken, nothing works at all, every client gets > >a: > >xmlrpclib.ProtocolError: > > Using what script? The one in xmlrpc_handler.py is working fine for > me. Fixed, it was a stupid bug from me. Sorry, yes, the CVS version apparently solves the 1024-characters truncation problem. Any release date planned? From rtesh@attbi.com Thu Sep 12 06:14:24 2002 From: rtesh@attbi.com (Robert M. Tesh) Date: Thu, 12 Sep 2002 05:14:24 -0000 Subject: [Medusa-dev] Incomplete response for /status on some Windows browsers Message-ID: <20020912051352.9852BDE35C@resolve.attbi.com> the easy solution is to turn chunking off in http_server.py line 52 - use_chunked = 1 make it - use_chunked = 0. This is a hack - but will get you working... There are other problems with the producer methods in the latest release that the older version did not have...right now the producers - more methods are incorrect and all pages will truncate at 64K. I'm using medusa-0.5.2 see [Medusa-dev] medusa-0.5.2 has critical Bug. by leslie@linuxkorea.co.kr From giles_brown@hotmail.com Thu Oct 24 10:05:14 2002 From: giles_brown@hotmail.com (Giles Brown) Date: Thu, 24 Oct 2002 09:05:14 +0000 Subject: [Medusa-dev] composite_producer bug? Message-ID: Hello, Reasons why this mail might be redundant: - Only just subscribed to this list. - Couldn't to sourceforge bug list (why? I don't know, got a 404) I downloaded the medusa-0.5.2.tar from http://oedipus.sourceforge.net/medusa/ and found that I was getting a problem serving my pages. Only a portion of the content was getting served. After some investigation I tracked the problem down (I believe) to the medusa.producers.composite_producer class. In an old Sam Rushing era copy of the medusa I had lying about I noticed that the medusa.http_server.http_request class initialised self.outgoing with a medusa.http_server.fifo() instance. At some point has been changed to use a plain list instead, but this list is being passed to a medusa.producers.composite_producer in the medusa.http_server.http_request.done method which is still expecting an object with the medusa.http_server.fifo interface. code from medusa-0.5.2.tar:medusa-0.5.2/producers.py -> class composite_producer: "combine a fifo of producers into one" def __init__ (self, producers): self.producers = producers def more (self): while len(self.producers): p = self.producers.pop(0) ^^^ (1) d = p.more() if d: return d else: self.producers.pop() ^^^ (2) else: return '' (1) This used to be p = self.producers.first(). Which did not remove the producer from the head of the list. Here we end up removing the producer even if it has more to produce (which was the cause of my problem). (2) The fifo defines pop() as removing head of the list that it wraps. For a list the default pop index is the tail of the list so we are removing the wrong producer. Options seem to be: 1) Look to ensure that composite_producer is expecting a list (interface) and not a fifo (interface). Scanning the medusa code composite_producer is only used in one other place *with an http_server.fifo*. This is in auth_handler.py. But what about compatibility with other code using current composite_producer. 2) Write a new composite_list_producer that is used (currently only by http_request) to produce from a list. Change the composite_producer back to using http_server.fifo() interface. 3) Change http_server.http_request back to using http_server.fifo() and change composite_producer back to using http_server.fifo() interface (i.e. .first() and not .pop(0)). Apologies if these things have already been discussed. Best regards, Giles Brown _________________________________________________________________ Unlimited Internet access for only $21.95/month.  Try MSN! http://resourcecenter.msn.com/access/plans/2monthsfree.asp From dsavitsk@mail.e-coli.net Thu Oct 31 01:24:52 2002 From: dsavitsk@mail.e-coli.net (douglas savitsky) Date: Wed, 30 Oct 2002 17:24:52 -0800 Subject: [Medusa-dev] medusa daemon Message-ID: <200210301724.AA2013987108@mail.e-coli.net> hi there, does anyone have a trivial example of running medusa as a daemon (on FreeBSD in my case) process? i found examples of making a python daemon, but i don't understand how the asyncore.loop() comes in to play. an example that would daemonize something like the following would be great. import asyncore from medusa import http_server hs = http_server.http_server ( '/usr/www', 80 ) # Enter async main loop asyncore.loop() thanks, -doug From adamf@pobox.com Thu Oct 31 18:17:12 2002 From: adamf@pobox.com (Adam Feuer) Date: Thu, 31 Oct 2002 10:17:12 -0800 Subject: [Medusa-dev] medusa daemon In-Reply-To: <200210301724.AA2013987108@mail.e-coli.net> Message-ID: > douglas savitsky wrote: > hi there, does anyone have a trivial example of running medusa as a daemon (on FreeBSD in my case) process? i found > examples of making a python daemon, but i don't understand how the asyncore.loop() comes in to play. > an example that would daemonize something like the following would be great. Douglas, The Python Cookbook has a couple of recipes... here's the one that looks best to me: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012 Here's a shorter alternative, but I'm not sure it'll work right: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52216 cheers adam -- Adam Feuer From dsavitsk@mail.e-coli.net Thu Oct 31 18:35:42 2002 From: dsavitsk@mail.e-coli.net (douglas savitsky) Date: Thu, 31 Oct 2002 10:35:42 -0800 Subject: [Medusa-dev] medusa daemon Message-ID: <200210311035.AA3124953284@mail.e-coli.net> ---------- Original Message ---------------------------------- From: "Adam Feuer" Date: Thu, 31 Oct 2002 10:17:12 -0800 >> douglas savitsky wrote: >> hi there, does anyone have a trivial example of running medusa as a daemon > The Python Cookbook has a couple of recipes... here's the one that looks >best to me: > >http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012 right, so in that example, could i just replace the main() function def main(): import time f = open("/tmp/daemon-log", "w") while 1: f.write('%s\n' % time.ctime(time.time())) f.flush() time.sleep(10) with def main(): import asyncore from medusa import http_server hs = http_server.http_server('/usr/www', 80) asyncore.loop() ? -doug From matlinb@comcast.net Tue Nov 12 16:03:05 2002 From: matlinb@comcast.net (Bill Matlin) Date: Tue, 12 Nov 2002 11:03:05 -0500 Subject: [Medusa-dev] Medusa CGI requests Message-ID: <3DD12639.8010200@comcast.net> I have Medusa running on a Windows ME computer and wanted to know where to look for information regarding setting medusa up for use with python scripts via CGI. From matlinb@comcast.net Tue Nov 12 16:03:05 2002 From: matlinb@comcast.net (Bill Matlin) Date: Tue, 12 Nov 2002 11:03:05 -0500 Subject: [Medusa-dev] Medusa CGI requests Message-ID: <3DD12639.8010200@comcast.net> I have Medusa running on a Windows ME computer and wanted to know where to look for information regarding setting medusa up for use with python scripts via CGI. From sfmunoz@teleline.es Fri Nov 22 18:51:16 2002 From: sfmunoz@teleline.es (Sergio Fernandez) Date: Fri, 22 Nov 2002 19:51:16 +0100 Subject: [Medusa-dev] auth_handler.py (auth_handler.handle_request) bug Message-ID: <20021122195116.3fb4db00.sfmunoz@teleline.es> Hello: I have found a bug in auth_handler.py file, class auth_handler, method handle_request (line 51). This bug exists in 0.5.2, 0.5.3 and CVS (Nov 22, 2002) versions. I'm using SuSE 8.0, Python 2.2. Simple Medusa startup script where you can see the problem could be: #!/usr/bin/env python import os import sys import asyncore from medusa import http_server from medusa import filesys from medusa import default_handler from medusa import auth_handler from medusa import logger lg = logger.file_logger(sys.stdout) hs = http_server.http_server ('',8080,None,lg) fs = filesys.os_filesystem('/var/www') dh = default_handler.default_handler(fs) audh = auth_handler.auth_handler({ 'user':'pass'},dh) hs.install_handler (audh) asyncore.loop() If you access medusa_host:8080, you can see it asks you for user/password. When you write them (user is 'user' and password is 'pass' as you can see in startup script) an error appears in the browser: Error response Error code: 500 Message: Internal Server Error. In medusa log you can see: error: Server Error: exceptions.AttributeError, group: file: /usr/lib/python2.2/site-packages/medusa/auth_handler.py line: 51 To fix this bug, I have substituted bug line. Patch is: diff -urN medusa-0.5.3.orig/auth_handler.py medusa-0.5.3/auth_handler.py --- medusa-0.5.3.orig/auth_handler.py Sat Mar 23 16:00:42 2002 +++ medusa-0.5.3/auth_handler.py Sat Nov 16 17:50:48 2002 @@ -48,7 +48,7 @@ if scheme: scheme = string.lower (scheme) if scheme == 'basic': - cookie = AUTHORIZATION.group(2) + cookie = get_header (AUTHORIZATION, request.header, 2) try: decoded = base64.decodestring (cookie) except: This patch works fine for default_handler. But when I have proved it I have found other problem. In order to separate things, I will e-mail it in a different message. Sergio From sfmunoz@teleline.es Fri Nov 22 18:53:47 2002 From: sfmunoz@teleline.es (Sergio Fernandez) Date: Fri, 22 Nov 2002 19:53:47 +0100 Subject: [Medusa-dev] status_handler + auth_handler combination problem Message-ID: <20021122195347.462e9c36.sfmunoz@teleline.es> Hello: When I applied patch I sent in message with Subject: "auth_handler.py (auth_handler.handle_request) bug" I found another problem I couldn't fix. This problem exists in 0.5.2, 0.5.3 and CVS (Nov 22, 2002) versions. I'm using SuSE 8.0, Python 2.2. Simple Medusa startup script where you can see the problem could be: #!/usr/bin/env python import os import sys import asyncore from medusa import http_server from medusa import filesys from medusa import default_handler from medusa import auth_handler from medusa import status_handler from medusa import logger lg = logger.file_logger(sys.stdout) hs = http_server.http_server ('',8080,None,lg) fs = filesys.os_filesystem('/var/www') dh = default_handler.default_handler(fs) audh = auth_handler.auth_handler({ 'user':'pass'},dh) hs.install_handler (audh) sh = status_handler.status_extension([hs]) aush = auth_handler.auth_handler({'status':'status'},sh) hs.install_handler(aush) asyncore.loop() If you access medusa_host:8080/, you can see it asks you for user/password. It you applied patch I sent in last e-mail, you can write 'user' as user and 'pass' as password and get into your pages. The problem comes when you access http://medusa_host:8080/status (in order to see your server status). As you can see in medusa startup script I've sent, user/password is diferent. In this case user is 'status' and password is 'status'. If you write when your browser asks, you get the following message: The document contained no data. Try again later, or contact the server's administrator. In medusa log you can see: error: Server Error: exceptions.AttributeError, fifo instance has no attribute '__getitem__': file: /usr/lib/python2.2/site-packages/medusa/producers.py line: 155 error: uncaptured python exception, closing channel (exceptions.AttributeError:fifo instance has no attribute '__getitem__' [/usr/lib/python2.2/asyncore.py|poll|107] [/usr/lib/python2.2/asyncore.py|handle_write_event|398] [/usr/lib/python2.2/asynchat.py|handle_write|146] [/usr/lib/python2.2/asynchat.py|initiate_send|208] [/usr/lib/python2.2/asynchat.py|refill_buffer|195] [/usr/lib/python2.2/site-packages/medusa/producers.py|more|179] [/usr/lib/python2.2/site-packages/medusa/producers.py|more|203] [/usr/lib/python2.2/site-packages/medusa/producers.py|more|156] [/usr/lib/python2.2/site-packages/medusa/producers.py|more|156] [/usr/lib/python2.2/site-packages/medusa/producers.py|more|155]) Do you have any idea about where the problem comes from? Any hints? Sergio From sfmunoz@teleline.es Sun Nov 24 16:55:57 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Sun, 24 Nov 2002 17:55:57 +0100 Subject: [Medusa-dev] redirecting_handler bug fixed Message-ID: <20021124175557.3b59643d.sfmunoz@teleline.es> Hello: This is a little patch that makes 'redirecting_handler' to work properly in Python 2.2 (SuSE 8.0). The error exists in 0.5.2, 0.5.3 and CVS (Nov 22, 2002) versions. The problem is in handle_request (class redirecting_handler, file redirecting_handler.py). When I tried to use this handler, I got the following error: error: Server Error: exceptions.IndexError, no such group: file: /usr/lib/python2.2/site-packages/medusa/redirecting_handler.py line: 28 192.168.0.1:1042 - - [24/Nov/2002:16:32:15 +0100] "GET /redirect.html HTTP/1.0" 500 311 To fix this error you can apply the following patch: diff -urN medusa-0.5.3.orig/redirecting_handler.py medusa-0.5.3/redirecting_handler.py --- medusa-0.5.3.orig/redirecting_handler.py Wed Mar 20 18:37:48 2002 +++ medusa-0.5.3/redirecting_handler.py Sat Nov 23 17:51:44 2002 @@ -25,7 +25,7 @@ def handle_request (self, request): self.hits.increment() m = self.patreg.match (request.uri) - part = m.group(1) + part = m.group() request['Location'] = self.redirect % part request.error (302) # moved temporarily Sergio From sfmunoz@teleline.es Sun Nov 24 16:56:09 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Sun, 24 Nov 2002 17:56:09 +0100 Subject: [Medusa-dev] unix_user_handler bug fixed Message-ID: <20021124175609.10607e66.sfmunoz@teleline.es> Hello: This is a little patch that makes 'unix_user_handler' to work properly in Python 2.2 (SuSE 8.0). The error exists in 0.5.2, 0.5.3 and CVS (Nov 22, 2002) versions. The problem is in handle_request (class unix_user_handler, file unix_user_handler.py). When I tried to use this handler, I got the following error: error: Server Error: exceptions.AttributeError, group: file: /usr/lib/python2.2/site-packages/medusa/unix_user_handler.py line: 38 192.168.0.1:1050 - - [24/Nov/2002:16:43:24 +0100] "GET /~user/ HTTP/1.0" 500 311 To fix this error you can apply the following patch: diff -urN medusa-0.5.3.orig/unix_user_handler.py medusa-0.5.3/unix_user_handler.py --- medusa-0.5.3.orig/unix_user_handler.py Tue Mar 19 23:49:35 2002 +++ medusa-0.5.3/unix_user_handler.py Sat Nov 23 18:46:02 2002 @@ -35,13 +35,13 @@ def handle_request (self, request): # get the user name - user = user_dir.group(1) - rest = user_dir.group(2) + m = user_dir.match (request.uri) + user = m.group(1) + rest = m.group(2) # special hack to catch those lazy URL typers if not rest: - request['Location'] = 'http://%s/~%s/' % ( - request.channel.server.server_name, + request['Location'] = '/~%s/' % ( user ) request.error (301) Pay special attention: this patch fixes two problems. The first one is that explained in this e-mail. The second one fixes a little problem in request['Location'] calculation. The old method gave me some problems too. With this patch, that problem has been fixed (I think the new way to calculate request['Location'] is a better one). Sergio From amk@amk.ca Mon Nov 25 00:42:05 2002 From: amk@amk.ca (A.M. Kuchling) Date: Sun, 24 Nov 2002 19:42:05 -0500 Subject: [Medusa-dev] unix_user_handler bug fixed In-Reply-To: <20021124175609.10607e66.sfmunoz@teleline.es>; from sfmunoz@teleline.es on Sun, Nov 24, 2002 at 05:56:09PM +0100 References: <20021124175609.10607e66.sfmunoz@teleline.es> Message-ID: <20021124194205.A27392@nyman.amk.ca> On Sun, Nov 24, 2002 at 05:56:09PM +0100, Sergio Fern=E1ndez wrote: >This is a little patch that makes 'unix_user_handler' to work properly >in Python 2.2 (SuSE 8.0). The error exists in 0.5.2, 0.5.3 and CVS (Nov >22, 2002) versions. Applied; thanks! --amk From amk@amk.ca Mon Nov 25 01:02:20 2002 From: amk@amk.ca (A.M. Kuchling) Date: Sun, 24 Nov 2002 20:02:20 -0500 Subject: [Medusa-dev] redirecting_handler bug fixed In-Reply-To: <20021124175557.3b59643d.sfmunoz@teleline.es>; from sfmunoz@teleline.es on Sun, Nov 24, 2002 at 05:55:57PM +0100 References: <20021124175557.3b59643d.sfmunoz@teleline.es> Message-ID: <20021124200220.B27392@nyman.amk.ca> On Sun, Nov 24, 2002 at 05:55:57PM +0100, Sergio Fern=E1ndez wrote: > def handle_request (self, request): > self.hits.increment() > m =3D self.patreg.match (request.uri) >- part =3D m.group(1) >+ part =3D m.group() >=20 > request['Location'] =3D self.redirect % part I don't like this patch because it changes behaviour and will break existing code that uses redirecting_handler. The intention of the code is that the pattern has a group in it, e.g. /long/url/directory/(.*), and the redirect would then be something like /newdir/%s, so /long/url/directory/foo.html will be redirected to /newdir/%s. This should be clarified in a docstring=20 for the redirecting_handler class. I think you could use a pattern like /foo/bar/() if you don't need to get part of the original URL. Or maybe the code should be something like this: if self.patreg.groups > 0: new_url =3D self.redirect % self.patreg.group(1) else: new_url =3D self.redirect Seem reasonable? --amk (www.am= k.ca) To Sherlock Holmes she is always *the* woman. -- From "A Scandal in Bohemia" From sfmunoz@teleline.es Mon Nov 25 07:18:30 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Mon, 25 Nov 2002 08:18:30 +0100 Subject: [Medusa-dev] redirecting_handler bug fixed In-Reply-To: <20021124200220.B27392@nyman.amk.ca> References: <20021124175557.3b59643d.sfmunoz@teleline.es> <20021124200220.B27392@nyman.amk.ca> Message-ID: <20021125081830.7a96f2fd.sfmunoz@teleline.es> On Sun, 24 Nov 2002 20:02:20 -0500 "A.M. Kuchling" wrote: > On Sun, Nov 24, 2002 at 05:55:57PM +0100, Sergio Fernández wrote: > > def handle_request (self, request): > > self.hits.increment() > > m = self.patreg.match (request.uri) > >- part = m.group(1) > >+ part = m.group() > > > > request['Location'] = self.redirect % part > > I don't like this patch because it changes behaviour and will break > existing code that uses redirecting_handler. The intention of the > code is that the pattern has a group in it, > e.g. /long/url/directory/(.*), and the redirect would then be > something like /newdir/%s, so /long/url/directory/foo.html will be > redirected to /newdir/%s. This should be clarified in a docstring > for the redirecting_handler class. > > I think you could use a pattern like /foo/bar/() if you don't need to > get part of the original URL. Or maybe the code should be something > like this: > > if self.patreg.groups > 0: > new_url = self.redirect % self.patreg.group(1) > else: > new_url = self.redirect > > Seem reasonable? > > --amk OK. It seems I didn't understand the way to use this handler. I have followed your explanations and it works fine. I agree with you: it should be clarified in a docstring for the redirecting_handler class. Thank you. Sergio From akuchlin@mems-exchange.org Mon Nov 25 19:39:28 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Mon, 25 Nov 2002 14:39:28 -0500 Subject: [Medusa-dev] status_handler + auth_handler combination problem In-Reply-To: <20021122195347.462e9c36.sfmunoz@teleline.es> References: <20021122195347.462e9c36.sfmunoz@teleline.es> Message-ID: <20021125193928.GB23228@ute.mems-exchange.org> On Fri, Nov 22, 2002 at 07:53:47PM +0100, Sergio Fernandez wrote: > error: Server Error: exceptions.AttributeError, fifo instance has no attribute '__getitem__': file: /usr/lib/python2.2/site-packages/medusa/producers.py line: 155 > error: uncaptured python exception, closing channel Try the patch below. After this patch, the http_server.fifo class seems to be unused, so I'm going to remove it. --amk Index: auth_handler.py =================================================================== RCS file: /cvsroot/oedipus/medusa/auth_handler.py,v retrieving revision 1.5 diff -u -r1.5 auth_handler.py --- auth_handler.py 23 Mar 2002 15:00:42 -0000 1.5 +++ auth_handler.py 25 Nov 2002 19:38:16 -0000 @@ -20,7 +20,6 @@ get_header = default_handler.get_header -import http_server import producers # This is a 'handler' that wraps an authorization method @@ -117,9 +116,7 @@ r.append ( producers.simple_producer ('') ) - return producers.composite_producer ( - http_server.fifo (r) - ) + return producers.composite_producer(r) class dictionary_authorizer: def __init__ (self, dict): From sfmunoz@teleline.es Tue Nov 26 07:30:19 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Tue, 26 Nov 2002 08:30:19 +0100 Subject: [Medusa-dev] status_handler + auth_handler combination problem In-Reply-To: <20021125193928.GB23228@ute.mems-exchange.org> References: <20021122195347.462e9c36.sfmunoz@teleline.es> <20021125193928.GB23228@ute.mems-exchange.org> Message-ID: <20021126083019.7a961a7c.sfmunoz@teleline.es> It works very well! Authentication works fine even when I use it together with status_handler. Thank you. Sergio On Mon, 25 Nov 2002 14:39:28 -0500 Andrew Kuchling wrote: > Try the patch below. From sfmunoz@teleline.es Sun Dec 1 12:56:03 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Sun, 1 Dec 2002 13:56:03 +0100 Subject: [Medusa-dev] Autoindex Message-ID: <20021201135603.5dd0145d.sfmunoz@teleline.es> Hello: I've added autoindex support to Medusa Web Server. Autoindex shows you the content of the directory you are looking for in a web server when there's no index.html/default.html file in that directory. Medusa returned a '404 Not Found' code when there were no index.html/default.html file in the directory. I didn't like it and I wanted to see what content that directory had. So I added autoindex feature to Medusa. Medusa autoindex features: - Very similar to that produced by default Apache autoindex feature (although this patch doesn't produce graphic icons). - It shows file name, last modified, size and type fields. - You can order (asc/desc) the list using any displayed field (name, last modified, size or type). I've only changed default_handler.py file. I've tried to avoid the modification of current code as far as I've been able to (in order to avoid the introduction of bugs in working code). Changes I have made are: - Functions added to default_handler class: __get_params __format_size __format_entry __pad_entry __get_index_order __sort_output_entry_list autoindex - Substituted 'request.error(404) # Not Found' by 'self.autoindex(request.path)' when index.html/default.html is not found (handle_request method in default_handler class). This is the link where autoindex is called. - 'import time' has been added because I needed time conversion tools. - request['Location'] calculation has been changed. This hasn't got anything to do with autoindex feature, but I prefer this new way to calculate it (read the end of the patch to understand the change). I've developed this feature in SuSE 8.0/Python 2.2. I didn't tried it in other platforms. If someone tries it, please tell me how it worked. I've thinking about writting a derived class (autoindex_handler, for example) to introduce autoindex feature. Question to Medusa developers/maintainers: In order to include autoindex feature in Medusa code (if you like it, of course)... do you want me to write a derived class (autoindex_handler) or do you like the way I did it (default_handler modification)? What do you prefer? What's better? If this code is included in Medusa code, it lacks one think. Perhaps you should include a boolean parameter in __init__ method (default_handler class): autoindex, for example. If true, autoindex works. If false, default_handler works as usual (returns 404). Finally, here comes the patch. Regards Sergio diff -urN medusa-cvs-26-11-2002.orig/default_handler.py medusa-cvs-26-11-2002/default_handler.py --- medusa-cvs-26-11-2002.orig/default_handler.py Thu Aug 1 20:15:45 2002 +++ medusa-cvs-26-11-2002/default_handler.py Sun Dec 1 13:10:42 2002 @@ -18,6 +18,7 @@ import http_server import status_handler import producers +import time unquote = http_server.unquote @@ -72,6 +73,285 @@ def match (self, request): return 1 + # get a dictionary from query parameters + def __get_params(self,request): + [path, params, query, fragment] = request.split_uri() + if query == None: + return {} + out = {} + query = string.split(query[1:],"&") + for input in query: + [key,value] = string.split(input,"=") + out[key] = value + return out + + # format size to get a pretty output + def __format_size(self,input): + K = 1024.0 + M = 1048576.0 + T = 1073741824.0 + unit = " " + if input >= T: + out = input/T + unit = "T" + elif input >= M: + out = input/M + unit = "M" + elif input >= K: + out = input/K + unit = "K" + else: + out = input + unit = " " + + if out < 0.1: + output = " 0 " + elif out < 10: + output = "%1.1f%s" % (out,unit) + else: + output = "%3.0f%s" % (out,unit) + + return output + + # make entry sorter if it's so long. + def __format_entry (self,entry,size): + if len(entry) > size+3: + new_entry = entry[:size] + '..>' + else: + new_entry = entry[:] + return new_entry + + # pad entry with spaces. + def __pad_entry (self,entry,size): + return ' '*(size-len(entry)+3) + + # calculate what order user wants from input params. + def __get_index_order(self,request): + params = self.__get_params(request) + order = { \ + 'name' : 0, \ + 'last_modified' : 0, \ + 'size' : 0, \ + 'type' : 0 \ + } + + if params.has_key('C') and params.has_key('O'): + if params['C'] == 'N': + if params['O'] == 'A': + order['name'] = 1 + elif params['O'] == 'D': + order['name'] = -1 + elif params['C'] == 'M': + if params['O'] == 'A': + order['last_modified'] = 1 + elif params['O'] == 'D': + order['last_modified'] = -1 + elif params['C'] == 'S': + if params['O'] == 'A': + order['size'] = 1 + elif params['O'] == 'D': + order['size'] = -1 + elif params['C'] == 'T': + if params['O'] == 'A': + order['type'] = 1 + elif params['O'] == 'D': + order['type'] = -1 + else: + order['name'] = 1 + + return order + + # sort output entry list (as order says) + def __sort_output_entry_list(self,list,order): + key_list = [] + output_list = [] + entry_dict = {} + for entry in list: + if order['name'] != 0: + key = "%s %20d %20d %s" % ( + entry['name'], \ + entry['last_modified'], \ + entry['size'], \ + entry['type'] \ + ) + elif order['last_modified'] != 0: + key = "%20d %s %20d %s" % ( \ + entry['last_modified'], \ + entry['name'], \ + entry['size'], \ + entry['type'] \ + ) + elif order['size'] != 0: + key = "%20d %2d %s %20d %s" % ( \ + entry['size'], \ + 1-entry['is_dir'], \ + entry['name'], \ + entry['last_modified'], \ + entry['type'] \ + ) + elif order['type'] != 0: + key = "%s %s %20d %20d" % ( \ + entry['type'], \ + entry['name'], \ + entry['size'], \ + entry['last_modified'] \ + ) + else: + key = "%s %20d %20d %s" % ( \ + entry['name'], \ + entry['last_modified'], \ + entry['size'], \ + entry['type'] \ + ) + + key_list.append(key) + entry_dict[key] = entry + + key_list.sort() + + order_sum = 0 + for key in order.keys(): + order_sum = order_sum + order[key] + if order_sum < 0: + key_list.reverse() + + for key in key_list: + output_list.append(entry_dict[key]) + return output_list + + # autoindex composition + def autoindex (self, request, path): + if path and path[-1] == '/': + spath = path[:-1] + else: + spath = path[:] + order = self.__get_index_order(request) + NAME_SIZE = 20 + TIME_FORMAT = "%d-%b-%Y %H:%M" + input_entry_list = self.filesystem.listdir(spath).list[:] + output_entry_list = [] + + for input_entry in input_entry_list: + full_input_entry = "%s/%s" % (spath,input_entry) + stat_input_entry = self.filesystem.stat(full_input_entry) + + output_entry = {} + + if self.filesystem.isdir(full_input_entry): + output_entry['is_dir'] = 1 + else: + output_entry['is_dir'] = 0 + + output_entry['name'] = input_entry + + output_entry['last_modified'] = stat_input_entry[stat.ST_MTIME] + + if output_entry['is_dir']: + output_entry['size'] = 0 + else: + output_entry['size'] = int(stat_input_entry[stat.ST_SIZE]) + + if output_entry['is_dir']: + output_entry['type'] = ' ' + else: + typ, encoding = mimetypes.guess_type(full_input_entry) + if typ is None: + typ = 'text/plain' + output_entry['type'] = typ + + output_entry_list.append(output_entry) + + output_entry_list = self.__sort_output_entry_list( + output_entry_list, + order + ) + + request['Content-Type'] = 'text/html' + request.push("\n") + request.push("\n") + request.push("Index of /%s\n" % spath) + request.push("\n") + request.push("\n") + request.push("

Index of /%s

\n" % spath) + request.push("
\n")
+        request.push("    ")
+        if order['name'] == 1:
+            request.push("")
+        else:
+            request.push("")
+        request.push("Name ")
+        request.push(self.__pad_entry("Name",NAME_SIZE))
+        if order['last_modified'] == 1:
+            request.push("")
+        else:
+            request.push("")
+        request.push("Last modified      ")
+        if order['size'] == 1:
+            request.push("")
+        else:
+            request.push("")
+        request.push("Size  ")
+        if order['type'] == 1:
+            request.push("")
+        else:
+            request.push("")
+        request.push("Type")
+        request.push("\n")
+        request.push("
\n") + if spath: + request.push(" Parent directory\n") + + for output_entry in output_entry_list: + if output_entry['is_dir']: + output_entry_is_dir = "[D] " + else: + output_entry_is_dir = " " + + if output_entry['is_dir']: + output_entry_name_link = "%s/" % output_entry['name'] + else: + output_entry_name_link = "%s" % output_entry['name'] + + output_entry_name_view = self.__format_entry( \ + output_entry_name_link, \ + NAME_SIZE \ + ) + + output_entry_last_modified = time.strftime( \ + TIME_FORMAT, \ + time.localtime(output_entry['last_modified']) \ + ) + + if output_entry['is_dir']: + output_entry_size = ' - ' + else: + output_entry_size = "%s" % self.__format_size(output_entry['size']) + + if output_entry['is_dir']: + output_entry_type = ' - ' + else: + output_entry_type = output_entry['type'] + + request.push ( \ + "%s%s%s %s %s %s\n" % ( \ + output_entry_is_dir, \ + output_entry_name_link, \ + output_entry_name_view, \ + self.__pad_entry(output_entry_name_view,NAME_SIZE), \ + output_entry_last_modified, \ + output_entry_size, \ + output_entry_type \ + ) \ + ) + + request.push("
\n") + request.push("
\n") + request.push("
Medusa/%s Server
\n" % http_server.VERSION_STRING) + request.push("\n") + request.push("\n") + request.done() + return + # handle a file request, with caching. def handle_request (self, request): @@ -93,8 +373,7 @@ if self.filesystem.isdir (path): if path and path[-1] != '/': - request['Location'] = 'http://%s/%s/' % ( - request.channel.server.server_name, + request['Location'] = '/%s/' % ( path ) request.error (301) @@ -113,7 +392,7 @@ found = 1 break if not found: - request.error (404) # Not Found + self.autoindex(request,path) return elif not self.filesystem.isfile (path): From sfmunoz@teleline.es Mon Dec 2 07:44:11 2002 From: sfmunoz@teleline.es (Sergio =?ISO-8859-1?B?RmVybuFuZGV6?=) Date: Mon, 2 Dec 2002 08:44:11 +0100 Subject: [Medusa-dev] Autoindex In-Reply-To: <20021201135603.5dd0145d.sfmunoz@teleline.es> References: <20021201135603.5dd0145d.sfmunoz@teleline.es> Message-ID: <20021202084411.5fd7f3be.sfmunoz@teleline.es> I have tried it now and it works fine in Windows'98 too (Python 2.2). Sergio On Sun, 1 Dec 2002 13:56:03 +0100 Sergio Fernández wrote: > I've developed this feature in SuSE 8.0/Python 2.2. I didn't tried it in > other platforms. If someone tries it, please tell me how it worked. From cmiller at tigerbyte.com Sat Dec 7 20:09:35 2002 From: cmiller at tigerbyte.com (Clint Miller) Date: Sat, 7 Dec 2002 14:09:35 -0600 Subject: [Medusa-dev] Newbie question Message-ID: <200212071409.35948.cmiller@tigerbyte.com> Where is the readonly access to the medusa CVS repository? The website does not reveal such information and the sourceforge Medusa site is not this medusa. Thanks! - Clint Miller From troy at gci.net Sat Dec 7 21:55:29 2002 From: troy at gci.net (Troy Melhase) Date: Sat, 07 Dec 2002 12:55:29 -0900 Subject: [Medusa-dev] Newbie question In-Reply-To: <200212071409.35948.cmiller@tigerbyte.com> References: <200212071409.35948.cmiller@tigerbyte.com> Message-ID: <3DF26E51.5090002@gci.net> You can browse the CVS repository on sourceforge: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/oedipus/medusa/ Access instructions are also available via SF: http://sourceforge.net/cvs/?group_id=4592 Good luck. troy Clint Miller wrote: >Where is the readonly access to the medusa CVS repository? The >website does not reveal such information and the sourceforge Medusa >site is not this medusa. > >Thanks! > >- Clint Miller > >_______________________________________________ >Medusa-dev mailing list >Medusa-dev@python.org >http://mail.python.org/mailman/listinfo/medusa-dev > > From Gustavo.Cavazos at emergis.com Mon Dec 9 10:09:16 2002 From: Gustavo.Cavazos at emergis.com (Cavazos, Gustavo) Date: Mon Dec 9 10:29:00 2002 Subject: [Medusa-dev] Medusa FTP/SSL/TLC problem Message-ID: When starting the FTP/SSL version of Medusa, it tries to read the randpool.dat file and gives this error: Traceback (most recent call last): File "ftps_server.py", line 566, in ? Rand.load_file('randpool.dat', -1) M2Crypto.SSL.SSLError: system lib Does anyone have any idea as to what is causing it? If I manually go into Python and import M2Crypto and load the file, it works. It just will not work running from the main program. Also, is reading and writing to the randpool file required to maintain randomness? Can someone help? Thanks, gc -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/medusa-dev/attachments/20021209/c13e54d6/attachment.html From ngps at netmemetic.com Tue Dec 10 20:41:15 2002 From: ngps at netmemetic.com (Ng Pheng Siong) Date: Tue Dec 10 07:40:22 2002 Subject: [Medusa-dev] Medusa FTP/SSL/TLC problem In-Reply-To: References: Message-ID: <20021210124115.GA373@vista.netmemetic.com> On Mon, Dec 09, 2002 at 10:09:16AM -0500, Cavazos, Gustavo wrote: > When starting the FTP/SSL version of Medusa, it tries to > read the randpool.dat file and gives this error: > > Traceback (most recent call last): > File "ftps_server.py", line 566, in ? > Rand.load_file('randpool.dat', -1) > M2Crypto.SSL.SSLError: system lib Have you tried supplying the full pathname to randpool.dat? > Also, is reading and writing to the randpool file required to maintain > randomness? Depends on your operating system. On modern freeware Unices, OpenSSL reads /dev/[u]random automatically, so loading randpool.dat is not necessary. My demo programs load randpool.dat because M2Crypto also runs on Windows, and will croak about 'PRNG not seeded' without that step on that platform. My demo programs write back to randpool.dat in case someone just uses randpool.dat, as supplied, for real: deadline pressure, "Hey, it works finally!" and all that. Writing back to randpool.dat buys a little security. -- Ng Pheng Siong * http://www.netmemetic.com From Gustavo.Cavazos at emergis.com Tue Dec 10 09:25:25 2002 From: Gustavo.Cavazos at emergis.com (Cavazos, Gustavo) Date: Thu Dec 12 09:28:38 2002 Subject: [Medusa-dev] Medusa FTP/SSL/TLC problem Message-ID: I am using Solaris, and If i take out the randpool load, SSL does not complain about 'PRNG not seeded' so I will assume it is used. And. I specified the full path, and is still did not work. Thanks for the help gc > -----Original Message----- > From: Ng Pheng Siong [mailto:ngps@netmemetic.com] > Sent: Tuesday, December 10, 2002 7:41 > To: Cavazos, Gustavo > Cc: 'medusa-dev@python.org' > Subject: Re: [Medusa-dev] Medusa FTP/SSL/TLC problem > > > On Mon, Dec 09, 2002 at 10:09:16AM -0500, Cavazos, Gustavo wrote: > > When starting the FTP/SSL version of Medusa, it tries to > > read the randpool.dat file and gives this error: > > > > Traceback (most recent call last): > > File "ftps_server.py", line 566, in ? > > Rand.load_file('randpool.dat', -1) > > M2Crypto.SSL.SSLError: system lib > > Have you tried supplying the full pathname to randpool.dat? > > > > Also, is reading and writing to the randpool file required > to maintain > > randomness? > > Depends on your operating system. On modern freeware Unices, > OpenSSL reads > /dev/[u]random automatically, so loading randpool.dat is not > necessary. > > My demo programs load randpool.dat because M2Crypto also runs > on Windows, > and will croak about 'PRNG not seeded' without that step on > that platform. > > My demo programs write back to randpool.dat in case someone just uses > randpool.dat, as supplied, for real: deadline pressure, "Hey, it works > finally!" and all that. Writing back to randpool.dat buys a little > security. > > > -- > Ng Pheng Siong * http://www.netmemetic.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/medusa-dev/attachments/20021210/d3384d4d/attachment.html From sav at ulj.menatepspb.com Wed Dec 11 17:41:18 2002 From: sav at ulj.menatepspb.com (Alexander Semenov) Date: Thu Dec 12 09:28:39 2002 Subject: [Medusa-dev] Improving main loop References: Message-ID: <005501c2a123$5daa14b0$1e20a8c0@ulj.menatepspb.com> Hi, I work on tcp/ip server. It must serve about 100 client connections, and make two connections to upstream server to suck some info. Medusa looks like ideal solution for it. Perfomance is perfect, I think it is because of single threaded server But I want some additional functionality from asyncore/asynchat/medusa 1. Timers. I need callbacks in my channels which called every number of seconds. Something like standart module sched tied with asyncore.loop() I need timer to send heartbeat messsages, and looks for clients which was timedout. 2. Autoreconnect. I want my outgoing connections to upstream server reconnects if become broken. My application is a server, but it must maintain client connection to upstream server, and it must run forever. 3. Simplify channel protocol. Why we write accepting server for each of channel types? They all looks the same. I think, most channels need four callbacks: On_Init(self), On_Connected(self), On_Disconnected(self) and On_DataArrived(self, data) plus timer signals. All network API for channels is Send(self, data) and Close(self). Channel can be started in two modes: Listen(addr, channel) and Connect(addr, channel). Maybe sombody succesful in realizing with features in medusa? I made quick hacks and now have working server, but dislike to it.Then, I attempt to write my own framework stealing ideas from asyncore, asynchat and sched. Now it is very slow. I have no idea why. I attached it. Maybe sombody will look to it and send me some critics/comments? Why it is so slow? How I can make this functionality in medusa? What calls/callbacks I forget in my protocol (described in paragraph 3)? Sorry for terrible English, Alexeander Semenov. -------------- next part -------------- '''TCPDispatcher - tcp/ip server which dispatchs channels Ideas stealed from asyncore, asynchat and sched User must derive his channels from Channel. It reacts on def On_Init(self): pass def On_Connected(self): pass def On_Disconnected(self): pass def On_DataArrived(self, data): pass and can use: def Close(self): def Send(self, data): then, user can install his channel with Listen() Connect() and finally, run loop: Serve() ''' import time import socket from bisect import insort from select import select, error from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, EISCONN, EINTR TIMEOUT = 15 # Timeout for connection in seconds _sockets = {} _crontab = [] class Channel: def __init__(self, sock, addr): self._addr = addr self._newsocket(sock) self._outbuff = [] self._inbuff = [] self._terminator = None self.On_Init() def __repr__(self): ret = 'to %s:%d' % self._addr if self._connected: ret = 'connected '+ret ret = '<%s %s at %#x>' % (self.__class__.__name__, ret, id(self)) return ret def _newsocket(self, sock=0): global _sockets try: self._socket.close() except: pass try: del _sockets[self._socket.fileno()] except: pass self._connected = 1 if not sock: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._connected = 0 self._socket = sock _sockets[sock.fileno()] = self self._disconnected = time.time() - TIMEOUT def _killtimers(self): global _crontab _crontab = [t for t in _crontab if not t[2].im_self is self] def handle_read_event(self): if not self._connected: self._connected = 1 self.On_Connected() try: data = self._socket.recv(4096) except socket.error: data = '' if data: if not self._terminator: self.On_DataArrived(data) return pos = data.find(self._terminator[-1:]) if pos < 0: self._inbuff.append(data) return data = ''.join(self._inbuff)+data while 1: pos = data.find(self._terminator) if pos < 0: break else: l = len(self._terminator) self.On_DataArrived(data[:pos+l]) data = data[pos+l:] self._inbuff = [data] else: data = ''.join(self._inbuff) if data: self.On_DataArrived(data) self._connected = 0 self.On_Disconnected() try: del _sockets[self._socket.fileno()] except: pass try: self._socket.close() except: pass if self._reconnectable: self._newsocket() else: self._killtimers() def handle_write_event(self): if not self._connected: self._connected = 1 self.On_Connected() out = ''.join(self._outbuff) sent = self._socket.send(out) out = out[sent:] if out: self._outbuff = [out] else: self._outbuff = [] # API for Cahannel def Close(self): global _sockets try: self._socket.send(''.join(self._outbuff)) except: pass self._killtimers() self._reconnectable = 0 try: del _sockets[self._socket.fileno()] except KeyError: pass except socket.error: pass try: self._socket.close() except: pass def Send(self, data): self._outbuff.append(data) def SetTerminator(self, term=None): self._terminator = term # Channel callbacks def On_Init(self): pass def On_Connected(self): pass def On_Disconnected(self): pass def On_DataArrived(self, data): pass def Shutdown(): global _sockets, _crontab #XXX close connections here for srv in _sockets.values(): try: srv._socket.close() except: pass _sockets = _crontab = {} class Listen: def __init__(self, host, port, channel): global _sockets self._addr = (host, port) self._channel = channel self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket.setblocking(0) _sockets[self._socket.fileno()] = self self._outbuff = [] try: self._socket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, self._socket.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1 ) except: pass self._socket.bind(self._addr) self._reconnectable = 0 self._socket.listen(5) def __repr__(self): return '' % ( self._channel.__name__, self._addr[0], self._addr[1], id(self)) def handle_read_event(self): srv = self._channel(*self._socket.accept()) srv._connected = 1 srv._reconnectable = 0 srv.On_Connected() def Connect(host, port, channel): global _sockets srv = channel(0, (host, port)) srv._connected, srv._disconnected, srv._reconnectable = 0, 0, 1 def Schedule(time_, repeat, func, *args, **kwargs): global _crontab if not time_: time_ = time.time()+repeat insort(_crontab, (time_, repeat, func, args, kwargs)) def process_timers(): global _crontab while _crontab: if _crontab[0][0] References: <005501c2a123$5daa14b0$1e20a8c0@ulj.menatepspb.com> Message-ID: <20021212183539.GB32704@zot.electricrain.com> A lot of what you describe sounds like stuff available in the "Twisted" library rather than medusa. You might want to have a look. http://twistedmatrix.com/ -g On Wed, Dec 11, 2002 at 05:41:18PM +0300, Alexander Semenov wrote: > Hi, > > I work on tcp/ip server. It must serve about 100 client connections, > and make two connections to upstream server to suck some info. > Medusa looks like ideal solution for it. Perfomance is perfect, I think > it is because of single threaded server > > But I want some additional functionality from asyncore/asynchat/medusa > 1. Timers. I need callbacks in my channels which called every number of > seconds. Something like standart module sched tied with asyncore.loop() > I need timer to send heartbeat messsages, and looks for clients which was > timedout. > 2. Autoreconnect. I want my outgoing connections to upstream server > reconnects if become broken. My application is a server, but it must > maintain client connection to upstream server, and it must run forever. > 3. Simplify channel protocol. Why we write accepting server for each of > channel types? They all looks the same. I think, most channels need > four callbacks: On_Init(self), On_Connected(self), On_Disconnected(self) > and On_DataArrived(self, data) plus timer signals. All network API > for channels is Send(self, data) and Close(self). Channel can be started > in two modes: Listen(addr, channel) and Connect(addr, channel). > > Maybe sombody succesful in realizing with features in medusa? > I made quick hacks and now have working server, but dislike to it.Then, I > attempt to write my own framework stealing ideas from asyncore, asynchat > and sched. Now it is very slow. I have no idea why. > > I attached it. Maybe sombody will look to it and send me some > critics/comments? > Why it is so slow? How I can make this functionality in medusa? What > calls/callbacks I forget in my protocol (described in paragraph 3)? > > Sorry for terrible English, > Alexeander Semenov. > '''TCPDispatcher - tcp/ip server which dispatchs channels > Ideas stealed from asyncore, asynchat and sched > > User must derive his channels from Channel. It reacts on > def On_Init(self): pass > def On_Connected(self): pass > def On_Disconnected(self): pass > def On_DataArrived(self, data): pass > and can use: > def Close(self): > def Send(self, data): > then, user can install his channel with > Listen() > Connect() > and finally, run loop: > Serve() > ''' > > import time > import socket > from bisect import insort > from select import select, error > from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, EISCONN, EINTR > > > TIMEOUT = 15 # Timeout for connection in seconds > > _sockets = {} > _crontab = [] > > > class Channel: > def __init__(self, sock, addr): > self._addr = addr > self._newsocket(sock) > self._outbuff = [] > self._inbuff = [] > self._terminator = None > self.On_Init() > > def __repr__(self): > ret = 'to %s:%d' % self._addr > if self._connected: ret = 'connected '+ret > ret = '<%s %s at %#x>' % (self.__class__.__name__, ret, id(self)) > return ret > > def _newsocket(self, sock=0): > global _sockets > > try: self._socket.close() > except: pass > try: del _sockets[self._socket.fileno()] > except: pass > > self._connected = 1 > if not sock: > sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) > self._connected = 0 > self._socket = sock > _sockets[sock.fileno()] = self > self._disconnected = time.time() - TIMEOUT > > def _killtimers(self): > global _crontab > _crontab = [t for t in _crontab if not t[2].im_self is self] > > def handle_read_event(self): > if not self._connected: > self._connected = 1 > self.On_Connected() > try: > data = self._socket.recv(4096) > except socket.error: > data = '' > if data: > if not self._terminator: > self.On_DataArrived(data) > return > pos = data.find(self._terminator[-1:]) > if pos < 0: > self._inbuff.append(data) > return > data = ''.join(self._inbuff)+data > while 1: > pos = data.find(self._terminator) > if pos < 0: > break > else: > l = len(self._terminator) > self.On_DataArrived(data[:pos+l]) > data = data[pos+l:] > self._inbuff = [data] > else: > data = ''.join(self._inbuff) > if data: self.On_DataArrived(data) > self._connected = 0 > self.On_Disconnected() > try: del _sockets[self._socket.fileno()] > except: pass > try: self._socket.close() > except: pass > if self._reconnectable: > self._newsocket() > else: > self._killtimers() > > def handle_write_event(self): > if not self._connected: > self._connected = 1 > self.On_Connected() > out = ''.join(self._outbuff) > sent = self._socket.send(out) > out = out[sent:] > if out: > self._outbuff = [out] > else: > self._outbuff = [] > > # API for Cahannel > def Close(self): > global _sockets > > try: > self._socket.send(''.join(self._outbuff)) > except: > pass > self._killtimers() > self._reconnectable = 0 > try: > del _sockets[self._socket.fileno()] > except KeyError: > pass > except socket.error: > pass > try: > self._socket.close() > except: > pass > > def Send(self, data): > self._outbuff.append(data) > > def SetTerminator(self, term=None): > self._terminator = term > > # Channel callbacks > def On_Init(self): pass > def On_Connected(self): pass > def On_Disconnected(self): pass > def On_DataArrived(self, data): pass > > > def Shutdown(): > global _sockets, _crontab > #XXX close connections here > for srv in _sockets.values(): > try: > srv._socket.close() > except: > pass > _sockets = _crontab = {} > > class Listen: > def __init__(self, host, port, channel): > global _sockets > > self._addr = (host, port) > self._channel = channel > self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) > self._socket.setblocking(0) > _sockets[self._socket.fileno()] = self > self._outbuff = [] > try: > self._socket.setsockopt( > socket.SOL_SOCKET, socket.SO_REUSEADDR, > self._socket.getsockopt(socket.SOL_SOCKET, > socket.SO_REUSEADDR) | 1 > ) > except: pass > self._socket.bind(self._addr) > self._reconnectable = 0 > self._socket.listen(5) > > def __repr__(self): > return '' % ( > self._channel.__name__, self._addr[0], self._addr[1], id(self)) > > def handle_read_event(self): > srv = self._channel(*self._socket.accept()) > srv._connected = 1 > srv._reconnectable = 0 > srv.On_Connected() > > > def Connect(host, port, channel): > global _sockets > > srv = channel(0, (host, port)) > srv._connected, srv._disconnected, srv._reconnectable = 0, 0, 1 > > > def Schedule(time_, repeat, func, *args, **kwargs): > global _crontab > if not time_: > time_ = time.time()+repeat > insort(_crontab, (time_, repeat, func, args, kwargs)) > > def process_timers(): > global _crontab > > while _crontab: > if _crontab[0][0] time_, repeat, func, args, kwargs = _crontab.pop(0) > if repeat: > Schedule(time_+repeat, repeat, func, *args, **kwargs) > func(*args, **kwargs) > else: > return _crontab[0][0]-time.time() > return 0 > > def watch_connections(): > global _sockets > > dead = [] > for fd, srv in _sockets.items(): > if not srv._reconnectable or \ > srv._connected or \ > time.time()-srv._disconnected < TIMEOUT: > continue > err = srv._socket.connect_ex(srv._addr) > if err in (EINPROGRESS, EALREADY, EWOULDBLOCK): > continue > if err in (0, EISCONN): > srv._connected = 1 > srv.On_Connected() > else: > dead.append(srv) > for srv in dead: > srv._newsocket() > > def Serve(): # Main loop > global _sockets, _crontab > > while _sockets or _crontab: > > # Connect new and reconnect broken channels > watch_connections() > > # Do timer events > delay = process_timers() > > wsocks = [fd for fd, srv in _sockets.items() if srv._outbuff] > > try: > rsocks, wsocks, _ = select(_sockets.keys(), wsocks, [], delay) > except error, err: > if err[0] == EINTR: continue > if err[0] == 10038: continue > raise > > [_sockets[rsock].handle_read_event() for rsock in rsocks] > [_sockets[wsock].handle_write_event() for wsock in wsocks] > _______________________________________________ > Medusa-dev mailing list > Medusa-dev@python.org > http://mail.python.org/mailman/listinfo/medusa-dev -- Some mistakes are too much fun to make only once. From Gustavo.Cavazos at emergis.com Fri Dec 13 11:46:20 2002 From: Gustavo.Cavazos at emergis.com (Cavazos, Gustavo) Date: Fri Dec 13 12:22:00 2002 Subject: [Medusa-dev] Medusa FTP server question... Message-ID: Maybe this has been asked before, but anyway... Is it normal for the medusa FTPserver to be CPU bound. As soon as it starts it cosnumes 100% cpu.. even with no one logging in. I am starting it as a standalone process. Any help would be appreciated. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/medusa-dev/attachments/20021213/9dfca98f/attachment.html From abo at minkirri.apana.org.au Sat Dec 14 15:17:48 2002 From: abo at minkirri.apana.org.au (Donovan Baarda) Date: Fri Dec 13 23:24:50 2002 Subject: [Medusa-dev] Medusa FTP server question... In-Reply-To: References: Message-ID: <20021214041748.GA12378@minkirri.apana.org.au> On Fri, Dec 13, 2002 at 11:46:20AM -0500, Cavazos, Gustavo wrote: > Maybe this has been asked before, but anyway... > > Is it normal for the medusa FTPserver to be CPU bound. > As soon as it starts it cosnumes 100% cpu.. even with no > one logging in. No, this is not normal. It sounds like the select polling is either not working, or you are running with a timeout of 0. > I am starting it as a standalone process. > > Any help would be appreciated. What platform? > _______________________________________________ > Medusa-dev mailing list > Medusa-dev@python.org > http://mail.python.org/mailman/listinfo/medusa-dev -- ---------------------------------------------------------------------- ABO: finger abo@minkirri.apana.org.au for more info, including pgp key ---------------------------------------------------------------------- From Gustavo.Cavazos at emergis.com Tue Dec 17 20:38:34 2002 From: Gustavo.Cavazos at emergis.com (Cavazos, Gustavo) Date: Wed Dec 18 08:46:39 2002 Subject: [Medusa-dev] Asyncore looping Message-ID: As it turns out, other programs using asyncore started looping and are now CPU bound, besides the ftp server. I also found this comment on google: >In article <5lr9k84777.fsf@eric.cnri.reston.va.us>, >Guido van Rossum wrote: >aahz@netcom.com (Aahz Maruch) writes: >> >> asyncore (which Medusa is built on) includes this functionality. It can >> be kind of trippy to just telnet to a blind socket and get a Python >> interpreter session. > >Really? I don't see a trace of this in the version of asyncore I have >in the standard Python library! I'd love to have this feature! > >As Fredrik pointed out, it's actually in the Medusa distribution. > >One warning: as is typical with asyncore applications, the monitor >doesn't work if one of the queue objects fails to return. (E.g. stuck >in an infinite loop.) Of interest is this last comment regarding that one of the queue objects fails to return essentially looping the program. This would explain why all of the sudden the program go CPU bound. Can anyone shed light on the subject. BTW, I am using Python 2.2 on Solaris 8 or 9 Thx, gc -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/medusa-dev/attachments/20021217/b414078d/attachment.html From blambert at knowledgetree.org Thu Dec 19 14:25:36 2002 From: blambert at knowledgetree.org (Brent Lambert) Date: Thu Dec 19 16:43:54 2002 Subject: [Medusa-dev] script_handler.py questions Message-ID: Hello, I just had some general questions about the script handler. First of all, is there a reason that the query string from a GET is thrown on the floor? Shouldn't this be passed through stdin to the script? The script handler seems to be halfway between CGI and a custom handler. Should POST/GET parameters be passed in a query string via stdin to the script, or wouldn't it be better to do some pre-processing and pass these in as a dictionary? Brent ********************************* Get your free E-Mail and Homepage Go to http://www.networld.com ********************************* From smithk at attbi.com Fri Dec 20 20:10:43 2002 From: smithk at attbi.com (Kevin Smith) Date: Fri Dec 20 20:11:19 2002 Subject: [Medusa-dev] RE: Medusa CGI requests In-Reply-To: Message-ID: Using the CGI module (FieldStorage class) with Medusa.... I have been able to use the cgi module with medusa but needed to recreate some of the necessary information that medusa had consumed in the request object. try this in your python script.... from cgi import FieldStorage #FieldStorge default is to get the header info from enviroment variables #we can override this in the constructor of the FieldStorage class #the FieldStorage headers object must be a dictionary if it is overridden #the Medusa request.header will need to be converted into a dictionary... #create an empty dictionary object dicHeader = {} #break the request.header tuple apart... for varPart in request.header: #break each reqest header part apart into key/values pairs varKeyValuePair= varPart.split(": ") #Place them in the dictionary dicHeader[varKeyValuePair[0]]=varKeyValuePair[1] # create another dictionary to act as the enviroment variables dicEnvir = {} #Add the Request Method from the request object dicEnvir['REQUEST_METHOD'] = request.command #break up the request uri into parts... [path, params, query, fragment] = request.split_uri() #put the query string in the dictionary... dicEnvir['QUERY_STRING'] = query #create a FieldStorage object with overridden headers and environ object form = FieldStorage(fp=stdin,headers=dicHeader,environ=dicEnvir) if form.has_key("user"): print "user = %s" % form["user"].value I have been using this with HTML form data that is posted like so.... ....
..... good luck Kevin From dsavitsk at mail.e-coli.net Fri Dec 20 17:55:42 2002 From: dsavitsk at mail.e-coli.net (douglas savitsky) Date: Fri Dec 20 20:59:12 2002 Subject: [Medusa-dev] help getting started Message-ID: <200212201755.AA242155574@mail.e-coli.net> Hi all, These are very newbie questions on getting up and running with medusa. If people can help me get a foothold, I will be happy to write up a "getting started with medusa" document to post somewhere. In general, I am trying to run 2 websites www.a.com and www.b.com on a single server (on FreeBSD 4.7 fwiw), but they should stay invisible to each other. a.com should be rooted at /usr/www/a and b.com in /usr/www/b. I would also like to use a directory for each for scripts (/usr/www/a/bin and /usr/www/b/bin most likely.) Here is where I am starting as far as an edit of the "start_medusa.py" script: import os import sys import asyncore from medusa import http_server from medusa import monitor from medusa import filesys from medusa import default_handler from medusa import status_handler from medusa import resolver from medusa import logger HOSTNAME1 = 'www.a.com' HOSTNAME2 = 'www.b.com' IP_ADDRESS = '' PUBLISHING_ROOT1 = '/home/www/a' PUBLISHING_ROOT2 = '/home/www/b' HTTP_PORT = 80 MONITOR_PORT = 9999 rs = resolver.caching_resolver('127.0.0.1') lg = logger.syslog_logger('/dev/log') lg = status_handler.logger_for_status(lg) fsa = filesys.os_filesystem(PUBLISHING_ROOT1) fsb = filesys.os_filesystem(PUBLISHING_ROOT2) dha = default_handler.default_handler(fsa) hsa = http_server.http_server(IP_ADDRESS, HTTP_PORT, rs, lg) hsa.install_handler(dha) dhb = default_handler.default_handler(fsb) hsb = http_server.http_server(IP_ADDRESS, HTTP_PORT, rs, lg) hsb.install_handler(dhb) if os.name == 'posix': from medusa import unix_user_handler uh = unix_user_handler.unix_user_handler('public_html') hsa.install_handler(uh) ms = monitor.secure_monitor_server('password', '', MONITOR_PORT) status_objects = [hsa, hsb, ms, rs, lg] sh = status_handler.status_extension(status_objects) hs.install_handler(sh) if os.name == 'posix': if hasattr (os, 'seteuid'): import pwd [uid, gid] = pwd.getpwnam ('nobody')[2:4] os.setegid(gid) os.seteuid(uid) asyncore.loop() The things that I know are totally wrong are that there is no association from HOSTNAME* to PUBLISHING_ROOT* (and maybe more to the point, is this the proper way to set up 2 distinct domain names), and I don't know how to start adding a scripts directory, or indeed how to structure scripts (that is, can they simply return a string, or is there more to it). I guess there are 3 other questions, 1. how does one allow directory browsing? this seems to not happen by default. Is it simply adding another handler? 2. is there support for server side includes, or will i need to make everything a script to append some generic headers, and 3. are there problems with blocking during script execution, and are threads the proper way to solve this if it is a problem. Thanks for any help to this long and not very interesting list of questions. -doug