Updated May 20, 2003
Created May 20, 2003
Autogenerated Site Map
Search this Site!:
The following was downloaded from:
http://infomesh.net/2001/QuickPut/QuickPut.txt
#!/usr/bin/python
"""
QuickPut 1.5 - http://infomesh.net/2001/QuickPut/
This is a program that enables one to load files onto a server using
the HTTP PUT method. It supports basic and digest authentication.
Usage: QuickPut [ --help ] [ --v ] file http_uri [ uname pswd ]
--help - Prints this message out
--v - Turns on "verbose" mode
"file" is the local file to upload, and "http_uri" is the target.
"uname" and "pswd" are optional authentication details.
"""
__author__ = 'Sean B. Palmer'
__license__ = 'Copyright (C) 2001 Sean B. Palmer. GNU GPL 2'
__version__ = '1.5'
__cvsid__ = '$Id$'
import sys, string, re, os, base64, md5, sha, time
import httplib, urlparse, urllib, urllib2
UAID = 'QuickPut/'+__version__+' (http://infomesh.net/2001/QuickPut/)'
if ('-v' in sys.argv) or ('--v' in sys.argv): VERBOSE = 1
else: VERBOSE = 0
def perr(s):
"""The standard error printing function.
Can go to STDERR, STDOUT, or both."""
if VERBOSE:
sys.stderr.write(s.strip()+'\n\n')
print s.strip()+'\n'
def precondition(uri, auth=None):
"""HEAD a resource, and return the code
Could be extended to get the ETag, etc."""
perr('Sending HEAD request to: '+uri)
u = urlparse.urlparse(uri)
n, p = u[1], u[2]
if '@' in n: sys.exit(0)
h = httplib.HTTP(n)
h.putrequest('HEAD', p)
if auth:
perr('Auth: '+str(auth))
if 'type' in auth.keys():
if auth['type'] == 'Basic': authtobasic(auth, h)
elif auth['type'] == 'Digest': authtodigest(auth, h, uri, 'HEAD')
h.putheader('Accept', '*/*')
h.putheader('Accept-Encoding', '*,deflate')
h.putheader('TE', 'trailers,deflate')
h.putheader('User-Agent', UAID)
h.putheader('Connection', 'TE,Keep-Alive')
h.endheaders()
errcode, errmsg, headers = h.getreply()
h.close()
perr('HEAD response code: '+str(errcode)+'\nResponse headers: '+str(headers))
if auth:
if ('type' in auth.keys()) and (errcode == 401):
perr('Authorization failed!\n'+'Auth: '+headers['www-authenticate'])
sys.exit(0) # Stops it from contunually looping
return errcode, errmsg, headers
def put(fn, uri, auth=None):
errcode, errmsg, headers = precondition(uri, auth=auth)
if errcode in (301, 302):
if not auth: put(fn, headers['Location'])
else: put(fn, headers['Location'], auth=auth)
elif errcode == 401:
wwwauth = headers['www-authenticate']
match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', wwwauth)
scheme, realm = match.groups()
if scheme.lower() == 'basic':
perr('HTTP Basic authentication spotted')
if not auth:
perr('No authentication details given!')
sys.exit(0) # Stops it from contunually looping
auth['type'] = 'Basic'
put(fn, uri, auth=auth)
elif scheme.lower() == 'digest':
# 2001-07-19 14:08:03 pls support digest auth as well as
# basic. Don't encourage users to send their passwords in the clear.
perr('HTTP Digest authentication spotted')
if not auth:
perr('No authentication details given!')
sys.exit(0)
auth['type'], auth['data'] = 'Digest', wwwauth
put(fn, uri, auth=auth)
elif errcode in (200, 204, 206, 404): putdata(fn, uri, auth=auth)
else: perr('Got error code: '+str(errcode)) # e.g. 403, 501
# Basic Authentication
def authtobasic(auth, h):
"""Converts basic auth data into an HTTP header."""
userpass = auth['uname']+':'+auth['pswd']
userpass = base64.encodestring(urllib.unquote(userpass)).strip()
h.putheader('Authorization', 'Basic '+userpass)
perr('Authorization: Basic '+userpass)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# D I G E S T A U T H E N T I C A T I O N S T U F F
# These functions are based on the stuff in urllib2
#
def authtodigest(auth, h, uri, method):
user, pw, a = auth['uname'], auth['pswd'], auth['data']
x = http_digest_auth(a, uri, user, pw, method)
h.putheader('Authorization', x)
perr('Authorization: '+x)
def http_digest_auth(a, uri, user, pw, method):
token, challenge = a.split(' ', 1)
chal = urllib2.parse_keqv_list(urllib2.parse_http_list(challenge))
a = get_authorization(chal, uri, user, pw, method)
if a: return 'Digest %s' % a
def get_authorization(chal, uri, user, pw, method):
try:
realm, nonce = chal['realm'], chal['nonce']
algorithm, opaque = chal.get('algorithm', 'MD5'), chal.get('opaque', None)
except KeyError: return None
H, KD = get_algorithm_impls(algorithm)
if H is None: return None
A1, A2 = "%s:%s:%s" % (user, realm, pw), "%s:%s" % (method, uri)
respdig = KD(H(A1), "%s:%s" % (nonce, H(A2)))
base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
'response="%s"' % (user, realm, nonce, uri, respdig)
if opaque: base = base + ', opaque="%s"' % opaque
if algorithm != 'MD5': base = base + ', algorithm="%s"' % algorithm
return base
def get_algorithm_impls(algorithm):
if algorithm == 'MD5':
H = lambda x, e=urllib2.encode_digest:e(md5.new(x).digest())
elif algorithm == 'SHA':
H = lambda x, e=urllib2.encode_digest:e(sha.new(x).digest())
KD = lambda s, d, H=H: H("%s:%s" % (s, d))
return H, KD
#
# End of Digest Authentication functions
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def putdata(fn, uri, auth=None):
f, u = open(fn, 'r'), urlparse.urlparse(uri)
b = f.read()
s = str(len(b))
n, p = u[1], u[2]
perr('PUTing to: '+uri+'\nData: Content-Length: '+s+', Snippet: "'+b[:35]+'"')
h = httplib.HTTP(n)
h.putrequest('PUT', p)
h.putheader('Accept', '*/*')
h.putheader('Allow', 'PUT')
if auth:
if 'type' in auth.keys():
if auth['type'] == 'Basic': authtobasic(auth, h)
elif auth['type'] == 'Digest': authtodigest(auth, h, uri, 'PUT')
h.putheader('Accept-Encoding', '*,deflate')
h.putheader('Expect', '100-continue')
h.putheader('User-Agent', UAID)
h.putheader('Connection', 'Keep-Alive')
h.putheader('Content-Type', 'text/html')
h.putheader('Content-Length', s)
h.endheaders()
h.send(b)
perr('Getting reply...')
errcode, errmsg, headers = h.getreply()
# body = h.getfile().read(500)
perr('Got reply')
h.close()
if errcode in (301, 302):
perr('PUT data error code was '+str(errcode))
if not auth: put(fn, headers['Location'])
else: put(fn, headers['Location'], auth=auth)
elif errcode == 401:
perr('Authorization failed!\n'+'Auth: '+headers['www-authenticate'])
sys.exit(0) # Stops it from continually looping
else:
perr('Done: '+str(errcode)+': '+str(errmsg)+'\n'+str(headers))
if errcode in (200, 201, 204):
sys.stderr.write('PUT succeeded!')
# perr(body)
elif errcode == 405: sys.stderr.write('PUT failed!')
elif errcode == 404: perr('PUT failed: 404!')
# Utility functions
def prompt():
"""Prompts for the file name and URI to PUT to."""
sys.stderr.write('Enter the name of the file you want to HTTP PUT: \n')
fn = raw_input()
sys.stderr.write('Enter the URI to HTTP PUT to: \n')
uri = raw_input()
if uri[-1] == '/':
sys.stderr.write('URI ends with a "/"; please enter a file name: \n')
urifn = raw_input()
uri = uri+urifn
sys.stderr.write('Thank you. Saving to: '+uri+'\n')
put(fn, uri)
def help():
print string.strip(__doc__)
sys.exit(0)
def run():
HelpFlags, argv = ('-help', '--help'), sys.argv[:]
for x in sys.argv:
if x in HelpFlags: help()
if x[0] == '-': argv.remove(x)
s = len(argv)-1
# perr(str(argv)+' '+str(VERBOSE))
if s == 2: put(argv[1], argv[2])
elif s == 4: put(argv[1], argv[2], auth={'uname': argv[3], 'pswd': argv[4]})
else: help()
if __name__=="__main__":
run()
Search this Site!:
Homepage: http://www.cpqlinux.com
Site Map: http://www.cpqlinux.com/sitemap.html