1 # -*- coding: utf-8; -*-
4 # Part of ‘dput’, a Debian package upload toolkit.
6 # This is free software, and you are welcome to redistribute it under
7 # certain conditions; see the end of this file for copyright
8 # information, grant of license, and disclaimer of warranty.
10 """ Implementation for HTTP upload method. """
12 from __future__
import absolute_import
20 from ..helper
import dputhelper
23 class PromptingPasswordMgr(urllib2
.HTTPPasswordMgr
):
24 """ Password manager that prompts at the terminal.
26 Custom HTTP password manager that prompts for a password using
27 getpass() if required, and mangles the saved URL so that only
28 one password is prompted for.
32 def __init__(self
, username
):
33 urllib2
.HTTPPasswordMgr
.__init
__(self
)
34 self
.username
= username
36 def find_user_password(self
, realm
, authuri
):
37 # Hack so that we only prompt for a password once
38 authuri
= self
.reduce_uri(authuri
)[0]
39 authinfo
= urllib2
.HTTPPasswordMgr
.find_user_password(
41 if authinfo
!= (None, None):
44 password
= getpass
.getpass(" Password for %s:" % realm
)
45 self
.add_password(realm
, authuri
, self
.username
, password
)
46 return (self
.username
, password
)
49 class AuthHandlerHackAround
:
50 """ Fake request and parent object. """
52 def __init__(self
, url
, resp_headers
, pwman
):
53 # fake request header dict
57 self
.resp_headers
= resp_headers
58 self
.authhandlers
= []
61 for authhandler_class
in [
62 urllib2
.HTTPBasicAuthHandler
, urllib2
.HTTPDigestAuthHandler
]:
63 ah
= authhandler_class(pwman
)
65 self
.authhandlers
.append(ah
)
67 # fake request methods
68 def add_header(self
, k
, v
):
71 def add_unredirected_header(self
, k
, v
):
74 def get_full_url(self
):
78 def open(self
, *args
, **keywords
):
81 # and what we really want
82 def get_auth_headers(self
):
83 for ah
in self
.authhandlers
:
85 ah
.http_error_401(self
, None, 401, None, self
.resp_headers
)
86 except ValueError as e
:
94 fqdn
, login
, incoming
, files_to_upload
, debug
, dummy
,
95 progress
=0, protocol
="http"):
96 """ Upload the files via WebDAV. """
98 # note: requires >= python 2.4 httplib
100 # EXCEPTION HANDLING!
101 if protocol
== 'https':
102 connclass
= httplib
.HTTPSConnection
103 elif protocol
== 'http':
104 connclass
= httplib
.HTTPConnection
106 sys
.stderr
.write("Wrong protocol for upload http[s].py method\n")
108 if not incoming
.startswith('/'):
109 incoming
= '/' + incoming
110 if not incoming
.endswith('/'):
112 unprocessed_files_to_upload
= files_to_upload
[:]
114 pwman
= PromptingPasswordMgr(login
)
115 while unprocessed_files_to_upload
:
116 afile
= unprocessed_files_to_upload
[0]
117 path_to_package
, package_name
= os
.path
.split(afile
)
118 sys
.stdout
.write(" Uploading %s: " % package_name
)
121 size
= os
.stat(afile
).st_size
123 sys
.stderr
.write("Determining size of file '%s' failed\n" % afile
)
125 f
= open(afile
, 'rb')
127 f
= dputhelper
.FileWithProgress(
129 progressf
=sys
.stderr
,
131 url_path
= incoming
+ package_name
132 url
= "%s://%s%s" % (protocol
, fqdn
, url_path
)
134 sys
.stdout
.write("D: HTTP-PUT to URL: %s\n" % url
)
135 conn
= connclass(fqdn
)
136 conn
.putrequest("PUT", url_path
, skip_accept_encoding
=True)
137 # Host: should be automatic
138 conn
.putheader('User-Agent', 'dput')
139 for k
, v
in auth_headers
.items():
141 conn
.putheader('Connection', 'close')
142 conn
.putheader('Content-Length', str(size
))
146 # sending in 64k steps (screws progress a bit)
152 res
= conn
.getresponse()
153 if res
.status
>= 200 and res
.status
< 300:
154 sys
.stdout
.write("done.\n")
155 del unprocessed_files_to_upload
[0]
156 elif res
.status
== 401 and not auth_headers
:
157 sys
.stdout
.write("need authentication.\n")
158 auth_headers
= AuthHandlerHackAround(
159 url
, res
.msg
, pwman
).get_auth_headers()
161 if res
.status
== 401:
163 "Upload failed as unauthorized: %s\n"
164 " Maybe wrong username or password?\n" % res
.reason
)
167 "Upload failed: %d %s\n" % (res
.status
, res
.reason
))
169 # must be done, but we're not interested
173 # Copyright © 2015–2016 Ben Finney <bignose@debian.org>
174 # Copyright © 2008–2012 Y Giridhar Appaji Nag <appaji@debian.org>
175 # Copyright © 2007–2008 Thomas Viehmann <tv@beamnet.de>
177 # This is free software: you may copy, modify, and/or distribute this work
178 # under the terms of the GNU General Public License as published by the
179 # Free Software Foundation; version 2 of that license or any later version.
180 # No warranty expressed or implied. See the file ‘LICENSE.GPL-2’ for details.
187 # vim: fileencoding=utf-8 filetype=python :