Patch #1065257: Support passing open files as body in
HTTPConnection.request().
diff --git a/Doc/lib/libhttplib.tex b/Doc/lib/libhttplib.tex
index 049f6c4..557ee3d 100644
--- a/Doc/lib/libhttplib.tex
+++ b/Doc/lib/libhttplib.tex
@@ -304,9 +304,14 @@
 This will send a request to the server using the HTTP request method
 \var{method} and the selector \var{url}.  If the \var{body} argument is
 present, it should be a string of data to send after the headers are finished.
+Alternatively, it may be an open file object, in which case the
+contents of the file is sent; this file object should support
+\code{fileno()} and \code{read()} methods.
 The header Content-Length is automatically set to the correct value.
 The \var{headers} argument should be a mapping of extra HTTP headers to send
 with the request.
+
+\versionchanged[\var{body} can be a file object]{2.6}
 \end{methoddesc}
 
 \begin{methoddesc}{getresponse}{}
diff --git a/Lib/httplib.py b/Lib/httplib.py
index 5ae5efc..1e0037f 100644
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -704,7 +704,15 @@
         if self.debuglevel > 0:
             print "send:", repr(str)
         try:
-            self.sock.sendall(str)
+            blocksize=8192
+            if hasattr(str,'read') :
+                if self.debuglevel > 0: print "sendIng a read()able"
+                data=str.read(blocksize)
+                while data:
+                    self.sock.sendall(data)
+                    data=str.read(blocksize)
+            else:
+                self.sock.sendall(str)
         except socket.error, v:
             if v[0] == 32:      # Broken pipe
                 self.close()
@@ -879,7 +887,21 @@
         self.putrequest(method, url, **skips)
 
         if body and ('content-length' not in header_names):
-            self.putheader('Content-Length', str(len(body)))
+            thelen=None
+            try:
+                thelen=str(len(body))
+            except TypeError, te:
+                # If this is a file-like object, try to
+                # fstat its file descriptor
+                import os
+                try:
+                    thelen = str(os.fstat(body.fileno()).st_size)
+                except (AttributeError, OSError):
+                    # Don't send a length if this failed
+                    if self.debuglevel > 0: print "Cannot stat!!"
+                    
+            if thelen is not None:
+                self.putheader('Content-Length',thelen)
         for hdr, value in headers.iteritems():
             self.putheader(hdr, value)
         self.endheaders()
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 8d9a706..90a4e55 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -10,9 +10,10 @@
     def __init__(self, text, fileclass=StringIO.StringIO):
         self.text = text
         self.fileclass = fileclass
+        self.data = ''
 
     def sendall(self, data):
-        self.data = data
+        self.data += data
 
     def makefile(self, mode, bufsize=None):
         if mode != 'r' and mode != 'rb':
@@ -133,6 +134,16 @@
             self.fail("Did not expect response from HEAD request")
         resp.close()
 
+    def test_send_file(self):
+        expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
+                   'Accept-Encoding: identity\r\nContent-Length:'
+
+        body = open(__file__, 'rb')
+        conn = httplib.HTTPConnection('example.com')
+        sock = FakeSocket(body)
+        conn.sock = sock
+        conn.request('GET', '/foo', body)
+        self.assertTrue(sock.data.startswith(expected))
 
 class OfflineTest(TestCase):
     def test_responses(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index fdff1c6..3062bd5 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -96,6 +96,9 @@
 Library
 -------
 
+- Patch #1065257: Support passing open files as body in 
+  HTTPConnection.request().
+
 - Bug #1569790: mailbox.py: Maildir.get_folder() and MH.get_folder()
   weren't passing the message factory on to newly created Maildir/MH
   objects.