From 52b8c29ca7172b4a6821e3e34b293562f3ae9a3f Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 29 Jun 2001 13:06:06 +0000 Subject: [PATCH] Solve SF bug #231249: cgi.py opens too many (temporary) files. class FieldStorage: this patch changes read_lines() and co. to use a StringIO() instead of a real file. The write() calls are redirected to a private method that replaces it with a real, external file only when it gets too big (> 1000 bytes). This avoids problems in forms using the multipart/form-data encoding with many fields. The original code created a temporary file for *every* field (not just for file upload fields), thereby sometimes exceeding the open file limit of some systems. Note that the simpler solution "use a real file only for file uploads" can't be used because the form field parser has no way to tell which fields correspond to file uploads. It's *possible* but extremely unlikely that this would break someone's code; they would have to be stepping way outside the documented interface for FieldStorage and use f.file.fileno(), or depend on overriding make_file() to return a file-like object with additional known properties. --- Lib/cgi.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Lib/cgi.py b/Lib/cgi.py index 4fa696ff1da..35343607a7f 100755 --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -28,7 +28,7 @@ written in Python. # responsible for its maintenance. # -__version__ = "2.5" +__version__ = "2.6" # Imports @@ -633,12 +633,20 @@ class FieldStorage: def read_lines(self): """Internal: read lines until EOF or outerboundary.""" - self.file = self.make_file('') + self.file = self.__file = StringIO() if self.outerboundary: self.read_lines_to_outerboundary() else: self.read_lines_to_eof() + def __write(self, line): + if self.__file is not None: + if self.__file.tell() + len(line) > 1000: + self.file = self.make_file('') + self.file.write(self.__file.getvalue()) + self.__file = None + self.file.write(line) + def read_lines_to_eof(self): """Internal: read lines until EOF.""" while 1: @@ -646,7 +654,7 @@ class FieldStorage: if not line: self.done = -1 break - self.file.write(line) + self.__write(line) def read_lines_to_outerboundary(self): """Internal: read lines until outerboundary.""" @@ -674,7 +682,7 @@ class FieldStorage: line = line[:-1] else: delim = "" - self.file.write(odelim + line) + self.__write(odelim + line) def skip_lines(self): """Internal: skip lines until outer boundary if defined."""