From aad6761ccea28e0a0da6761570b18adc72e01c37 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 8 May 2000 17:31:04 +0000 Subject: [PATCH] The usual... --- Lib/dos-8x3/basehttp.py | 58 ++- Lib/dos-8x3/cgihttps.py | 17 +- Lib/dos-8x3/configpa.py | 96 +++- Lib/dos-8x3/exceptio.py | 22 +- Lib/dos-8x3/fileinpu.py | 31 +- Lib/dos-8x3/formatte.py | 20 + Lib/dos-8x3/gopherli.py | 280 ++++++------ Lib/dos-8x3/htmlenti.py | 356 ++++++++++----- Lib/dos-8x3/linecach.py | 130 +++--- Lib/dos-8x3/macurl2p.py | 10 +- Lib/dos-8x3/mimepars.py | 246 +++++++++++ Lib/dos-8x3/mimetool.py | 29 +- Lib/dos-8x3/mimetype.py | 41 +- Lib/dos-8x3/multifil.py | 79 ++-- Lib/dos-8x3/nturl2pa.py | 5 +- Lib/dos-8x3/posixfil.py | 120 +++-- Lib/dos-8x3/posixpat.py | 31 +- Lib/dos-8x3/py_compi.py | 2 +- Lib/dos-8x3/queue.py | 4 +- Lib/dos-8x3/regex_sy.py | 10 +- Lib/dos-8x3/rfc822-n.py | 946 ++++++++++++++++++++++++++++++++++++++++ Lib/dos-8x3/rlcomple.py | 17 +- Lib/dos-8x3/robotpar.py | 97 ++++ Lib/dos-8x3/simpleht.py | 7 +- Lib/dos-8x3/socketse.py | 26 +- Lib/dos-8x3/sre_comp.py | 187 ++++++++ Lib/dos-8x3/sre_cons.py | 131 ++++++ Lib/dos-8x3/sre_pars.py | 497 +++++++++++++++++++++ Lib/dos-8x3/statcach.py | 33 +- Lib/dos-8x3/stringio.py | 56 +-- Lib/dos-8x3/stringol.py | 431 ++++++++++++++++++ Lib/dos-8x3/telnetli.py | 1 + Lib/dos-8x3/test_bin.py | 121 +++-- Lib/dos-8x3/test_con.py | 168 +++++++ Lib/dos-8x3/test_cpi.py | 19 +- Lib/dos-8x3/test_ext.py | 143 ++++++ Lib/dos-8x3/test_fcn.py | 3 +- Lib/dos-8x3/test_for.py | 68 +++ Lib/dos-8x3/test_gdb.py | 8 +- Lib/dos-8x3/test_gra.py | 35 +- Lib/dos-8x3/test_lon.py | 12 +- Lib/dos-8x3/test_mma.py | 67 +++ Lib/dos-8x3/test_pye.py | 107 +++++ Lib/dos-8x3/test_rfc.py | 40 ++ Lib/dos-8x3/test_soc.py | 4 +- Lib/dos-8x3/test_typ.py | 25 ++ Lib/dos-8x3/test_uni.py | 401 +++++++++++++++++ Lib/dos-8x3/test_win.py | 147 +++++++ Lib/dos-8x3/test_zip.py | 26 ++ Lib/dos-8x3/test_zli.py | 16 +- Lib/dos-8x3/threadin.py | 7 +- Lib/dos-8x3/threadst.py | 9 + Lib/dos-8x3/tracebac.py | 79 +++- Lib/dos-8x3/userdict.py | 2 +- Lib/dos-8x3/userlist.py | 15 +- Lib/dos-8x3/userstri.py | 158 +++++++ 56 files changed, 5040 insertions(+), 656 deletions(-) create mode 100644 Lib/dos-8x3/mimepars.py create mode 100644 Lib/dos-8x3/rfc822-n.py create mode 100644 Lib/dos-8x3/robotpar.py create mode 100644 Lib/dos-8x3/sre_comp.py create mode 100644 Lib/dos-8x3/sre_cons.py create mode 100644 Lib/dos-8x3/sre_pars.py create mode 100644 Lib/dos-8x3/stringol.py create mode 100644 Lib/dos-8x3/test_con.py create mode 100644 Lib/dos-8x3/test_ext.py create mode 100644 Lib/dos-8x3/test_for.py create mode 100644 Lib/dos-8x3/test_mma.py create mode 100644 Lib/dos-8x3/test_pye.py create mode 100644 Lib/dos-8x3/test_uni.py create mode 100644 Lib/dos-8x3/test_win.py create mode 100644 Lib/dos-8x3/test_zip.py create mode 100644 Lib/dos-8x3/threadst.py create mode 100644 Lib/dos-8x3/userstri.py diff --git a/Lib/dos-8x3/basehttp.py b/Lib/dos-8x3/basehttp.py index 4c9645ddeed..10a706e1f8d 100755 --- a/Lib/dos-8x3/basehttp.py +++ b/Lib/dos-8x3/basehttp.py @@ -68,7 +68,6 @@ import sys import time import socket # For gethostbyaddr() import string -import rfc822 import mimetools import SocketServer @@ -94,12 +93,16 @@ class HTTPServer(SocketServer.TCPServer): host, port = self.socket.getsockname() if not host or host == '0.0.0.0': host = socket.gethostname() - hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) - if '.' not in hostname: - for host in hostnames: - if '.' in host: - hostname = host - break + try: + hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) + except socket.error: + hostname = host + else: + if '.' not in hostname: + for host in hostnames: + if '.' in host: + hostname = host + break self.server_name = hostname self.server_port = port @@ -169,7 +172,7 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): This server parses the request and the headers, and then calls a function specific to the request type (). Specifically, - a request SPAM will be handled by a method handle_SPAM(). If no + a request SPAM will be handled by a method do_SPAM(). If no such method exists the server sends an error response to the client. If it exists, it is called with no arguments: @@ -216,16 +219,17 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): # where each string is of the form name[/version]. server_version = "BaseHTTP/" + __version__ - def handle(self): - """Handle a single HTTP request. + def parse_request(self): + """Parse a request (internal). - You normally don't need to override this method; see the class - __doc__ string for information on how to handle specific HTTP - commands such as GET and POST. + The request should be stored in self.raw_request; the results + are in self.command, self.path, self.request_version and + self.headers. + + Return value is 1 for success, 0 for failure; on failure, an + error is sent back. """ - - self.raw_requestline = self.rfile.readline() self.request_version = version = "HTTP/0.9" # Default requestline = self.raw_requestline if requestline[-2:] == '\r\n': @@ -238,21 +242,35 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): [command, path, version] = words if version[:5] != 'HTTP/': self.send_error(400, "Bad request version (%s)" % `version`) - return + return 0 elif len(words) == 2: [command, path] = words if command != 'GET': self.send_error(400, "Bad HTTP/0.9 request type (%s)" % `command`) - return + return 0 else: self.send_error(400, "Bad request syntax (%s)" % `requestline`) - return + return 0 self.command, self.path, self.request_version = command, path, version self.headers = self.MessageClass(self.rfile, 0) - mname = 'do_' + command + return 1 + + def handle(self): + """Handle a single HTTP request. + + You normally don't need to override this method; see the class + __doc__ string for information on how to handle specific HTTP + commands such as GET and POST. + + """ + + self.raw_requestline = self.rfile.readline() + if not self.parse_request(): # An error code has been sent, just exit + return + mname = 'do_' + self.command if not hasattr(self, mname): - self.send_error(501, "Unsupported method (%s)" % `command`) + self.send_error(501, "Unsupported method (%s)" % `self.command`) return method = getattr(self, mname) method() diff --git a/Lib/dos-8x3/cgihttps.py b/Lib/dos-8x3/cgihttps.py index 806ef575556..fa30cbdddae 100755 --- a/Lib/dos-8x3/cgihttps.py +++ b/Lib/dos-8x3/cgihttps.py @@ -3,6 +3,9 @@ This module builds on SimpleHTTPServer by implementing GET and POST requests to cgi-bin scripts. +If the os.fork() function is not present, this module will not work; +SystemError will be raised instead. + """ @@ -10,15 +13,18 @@ __version__ = "0.3" import os -import sys -import time -import socket import string import urllib import BaseHTTPServer import SimpleHTTPServer +try: + os.fork +except AttributeError: + raise SystemError, __name__ + " requires os.fork()" + + class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): """Complete HTTP server with GET, HEAD and POST commands. @@ -150,6 +156,9 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): ua = self.headers.getheader('user-agent') if ua: env['HTTP_USER_AGENT'] = ua + co = filter(None, self.headers.getheaders('cookie')) + if co: + env['HTTP_COOKIE'] = string.join(co, ', ') # XXX Other HTTP_* headers decoded_query = string.replace(query, '+', ' ') try: @@ -177,7 +186,7 @@ def nobody_uid(): import pwd try: nobody = pwd.getpwnam('nobody')[2] - except pwd.error: + except KeyError: nobody = 1 + max(map(lambda x: x[2], pwd.getpwall())) return nobody diff --git a/Lib/dos-8x3/configpa.py b/Lib/dos-8x3/configpa.py index dd8b6d86672..e1ce9ddc7e9 100644 --- a/Lib/dos-8x3/configpa.py +++ b/Lib/dos-8x3/configpa.py @@ -33,11 +33,24 @@ ConfigParser -- responsible for for parsing a list of sections() return all the configuration section names, sans DEFAULT + has_section(section) + return whether the given section exists + options(section) return list of configuration options for the named section + has_option(section, option) + return whether the given section has the given option + read(filenames) - read and parse the list of named configuration files + read and parse the list of named configuration files, given by + name. A single filename is also allowed. Non-existing files + are ignored. + + readfp(fp, filename=None) + read and parse one configuration file, given as a file object. + The filename defaults to fp.name; it is only used in error + messages (if fp has no `name' attribute, the string `' is used). get(section, option, raw=0, vars=None) return a string value for the named option. All % interpolations are @@ -158,6 +171,7 @@ class ConfigParser: return self.__sections.has_key(section) def options(self, section): + """Return a list of option names for the given section name.""" try: opts = self.__sections[section].copy() except KeyError: @@ -165,16 +179,49 @@ class ConfigParser: opts.update(self.__defaults) return opts.keys() + def has_option(self, section, option): + """Return whether the given section has the given option.""" + try: + opts = self.__sections[section] + except KeyError: + raise NoSectionError(section) + return opts.has_key(option) + def read(self, filenames): - """Read and parse a list of filenames.""" + """Read and parse a filename or a list of filenames. + + Files that cannot be opened are silently ignored; this is + designed so that you can specify a list of potential + configuration file locations (e.g. current directory, user's + home directory, systemwide directory), and all existing + configuration files in the list will be read. A single + filename may also be given. + """ if type(filenames) is type(''): filenames = [filenames] - for file in filenames: + for filename in filenames: try: - fp = open(file, 'r') - self.__read(fp) + fp = open(filename) except IOError: - pass + continue + self.__read(fp, filename) + fp.close() + + def readfp(self, fp, filename=None): + """Like read() but the argument must be a file-like object. + + The `fp' argument must have a `readline' method. Optional + second argument is the `filename', which if not given, is + taken from fp.name. If fp has no `name' attribute, `' is + used. + + """ + if filename is None: + try: + filename = fp.name + except AttributeError: + filename = '' + self.__read(fp, filename) def get(self, section, option, raw=0, vars=None): """Get an option value for a given section. @@ -199,7 +246,7 @@ class ConfigParser: # Update with the entry specific variables if vars: d.update(vars) - option = string.lower(option) + option = self.optionxform(option) try: rawval = d[option] except KeyError: @@ -212,7 +259,7 @@ class ConfigParser: depth = 0 while depth < 10: # Loop through this until it's done depth = depth + 1 - if not string.find(value, "%("): + if string.find(value, "%(") >= 0: try: value = value % d except KeyError, key: @@ -236,25 +283,28 @@ class ConfigParser: raise ValueError, 'Not a boolean: %s' % v return val + def optionxform(self, optionstr): + return string.lower(optionstr) + # # Regular expressions for parsing section headers and options. Note a # slight semantic change from the previous version, because of the use # of \w, _ is allowed in section header names. - __SECTCRE = re.compile( + SECTCRE = re.compile( r'\[' # [ - r'(?P
[-\w]+)' # `-', `_' or any alphanum + r'(?P
[-\w_.*,(){}]+)' # a lot of stuff found by IvL r'\]' # ] ) - __OPTCRE = re.compile( - r'(?P