~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/_urllib2_wrappers.py

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Implementaion of urllib2 tailored to bzr needs
18
18
 
105
105
        self.sock = sock
106
106
        self._report_activity = report_activity
107
107
 
108
 
    def send(self, s, *args):
109
 
        self.sock.send(s, *args)
110
 
        self._report_activity(len(s), 'write')
111
 
 
112
108
    def sendall(self, s, *args):
113
 
        self.sock.send(s, *args)
 
109
        self.sock.sendall(s, *args)
114
110
        self._report_activity(len(s), 'write')
115
111
 
116
112
    def recv(self, *args):
257
253
        # Preserve our preciousss
258
254
        sock = self.sock
259
255
        self.sock = None
260
 
        # Let httplib.HTTPConnection do its housekeeping 
 
256
        # Let httplib.HTTPConnection do its housekeeping
261
257
        self.close()
262
258
        # Restore our preciousss
263
259
        self.sock = sock
371
367
 
372
368
    def __init__(self, request):
373
369
        """Constructor
374
 
        
 
370
 
375
371
        :param request: the first request sent to the proxied host, already
376
372
            processed by the opener (i.e. proxied_host is already set).
377
373
        """
698
694
                        connect.proxied_host, self.host))
699
695
            # Housekeeping
700
696
            connection.cleanup_pipe()
701
 
            # Establish the connection encryption 
 
697
            # Establish the connection encryption
702
698
            connection.connect_to_origin()
703
699
            # Propagate the connection to the original request
704
700
            request.connection = connection
983
979
    _max_retry = 3
984
980
    """We don't want to retry authenticating endlessly"""
985
981
 
 
982
    requires_username = True
 
983
    """Whether the auth mechanism requires a username."""
 
984
 
986
985
    # The following attributes should be defined by daughter
987
986
    # classes:
988
987
    # - auth_required_header:  the header received from the server
994
993
        # in such a cycle by default.
995
994
        self._retry_count = None
996
995
 
 
996
    def _parse_auth_header(self, server_header):
 
997
        """Parse the authentication header.
 
998
 
 
999
        :param server_header: The value of the header sent by the server
 
1000
            describing the authenticaion request.
 
1001
 
 
1002
        :return: A tuple (scheme, remainder) scheme being the first word in the
 
1003
            given header (lower cased), remainder may be None.
 
1004
        """
 
1005
        try:
 
1006
            scheme, remainder = server_header.split(None, 1)
 
1007
        except ValueError:
 
1008
            scheme = server_header
 
1009
            remainder = None
 
1010
        return (scheme.lower(), remainder)
 
1011
 
997
1012
    def update_auth(self, auth, key, value):
998
1013
        """Update a value in auth marking the auth as modified if needed"""
999
1014
        old_value = auth.get(key, None)
1034
1049
                # We already tried that, give up
1035
1050
                return None
1036
1051
 
1037
 
            if auth.get('user', None) is None:
 
1052
            if self.requires_username and auth.get('user', None) is None:
1038
1053
                # Without a known user, we can't authenticate
1039
1054
                return None
1040
1055
 
1069
1084
        (digest's nonce is an example, digest's nonce_count is a
1070
1085
        *counter-example*). Such parameters must be updated by
1071
1086
        using the update_auth() method.
1072
 
        
 
1087
 
1073
1088
        :param header: The authentication header sent by the server.
1074
1089
        :param auth: The auth parameters already known. They may be
1075
1090
             updated.
1152
1167
class NegotiateAuthHandler(AbstractAuthHandler):
1153
1168
    """A authentication handler that handles WWW-Authenticate: Negotiate.
1154
1169
 
1155
 
    At the moment this handler supports just Kerberos. In the future, 
 
1170
    At the moment this handler supports just Kerberos. In the future,
1156
1171
    NTLM support may also be added.
1157
1172
    """
1158
1173
 
1159
1174
    handler_order = 480
1160
1175
 
 
1176
    requires_username = False
 
1177
 
1161
1178
    def auth_match(self, header, auth):
1162
 
        scheme = header.lower()
 
1179
        scheme, raw_auth = self._parse_auth_header(header)
1163
1180
        if scheme != 'negotiate':
1164
1181
            return False
1165
1182
        self.update_auth(auth, 'scheme', scheme)
1192
1209
        # If the auth scheme is known, it means a previous
1193
1210
        # authentication was successful, all information is
1194
1211
        # available, no further checks are needed.
1195
 
        return (auth.get('scheme', None) == 'negotiate' and 
 
1212
        return (auth.get('scheme', None) == 'negotiate' and
1196
1213
                auth.get('negotiate_response', None) is not None)
1197
1214
 
1198
1215
 
1209
1226
        return auth_header
1210
1227
 
1211
1228
    def auth_match(self, header, auth):
1212
 
        scheme, raw_auth = header.split(None, 1)
1213
 
        scheme = scheme.lower()
 
1229
        scheme, raw_auth = self._parse_auth_header(header)
1214
1230
        if scheme != 'basic':
1215
1231
            return False
1216
1232
 
1257
1273
class DigestAuthHandler(AbstractAuthHandler):
1258
1274
    """A custom digest authentication handler."""
1259
1275
 
1260
 
    # Before basic as digest is a bit more secure
 
1276
    # Before basic as digest is a bit more secure and should be preferred
1261
1277
    handler_order = 490
1262
1278
 
1263
1279
    def auth_params_reusable(self, auth):
1267
1283
        return auth.get('scheme', None) == 'digest'
1268
1284
 
1269
1285
    def auth_match(self, header, auth):
1270
 
        scheme, raw_auth = header.split(None, 1)
1271
 
        scheme = scheme.lower()
 
1286
        scheme, raw_auth = self._parse_auth_header(header)
1272
1287
        if scheme != 'digest':
1273
1288
            return False
1274
1289