mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
184 lines
4.2 KiB
Python
Executable file
184 lines
4.2 KiB
Python
Executable file
#!/usr/bin/python -O
|
|
#
|
|
# Description:
|
|
# ------------
|
|
# This is the client-side portion of the Trusted User package
|
|
# manager. The TUs will use this program to upload packages into
|
|
# the AUR. For more information, see the ../README.txt file.
|
|
#
|
|
# Python Indentation:
|
|
# -------------------
|
|
# For a vim: line to be effective, it must be at the end of the
|
|
# file. See the end of the file for more information.
|
|
#
|
|
|
|
import sys
|
|
import socket
|
|
import os
|
|
import struct
|
|
import os.path
|
|
import cgi
|
|
import urllib
|
|
import md5
|
|
import getopt
|
|
|
|
class ClientFile:
|
|
def __init__(self, pathname):
|
|
self.pathname = pathname
|
|
self.filename = os.path.basename(pathname)
|
|
self.fd = open(pathname, "rb")
|
|
self.fd.seek(0, 2)
|
|
self.size = self.fd.tell()
|
|
self.fd.seek(0)
|
|
self.makeMd5()
|
|
|
|
def makeMd5(self):
|
|
md5sum = md5.new()
|
|
while self.fd.tell() != self.size:
|
|
md5sum.update(self.fd.read(1024))
|
|
self.md5 = md5sum.hexdigest()
|
|
|
|
class ClientSocket:
|
|
def __init__(self, files, host, port, username, password):
|
|
self.files = files
|
|
self.host = host
|
|
self.port = port
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
self.username = username
|
|
self.password = password
|
|
|
|
def connect(self):
|
|
self.socket.connect((self.host, self.port))
|
|
|
|
def reliableRead(self, size):
|
|
totalread = ""
|
|
while len(totalread) < size:
|
|
read = self.socket.recv(size-len(totalread))
|
|
if read == 0:
|
|
raise RuntimeError, "socket connection broken"
|
|
totalread += read
|
|
return totalread
|
|
|
|
def sendMsg(self, msg):
|
|
if type(msg) == dict:
|
|
msg = urllib.unquote(urllib.urlencode(msg,1))
|
|
length = struct.pack("H", socket.htons(len(msg)))
|
|
self.socket.sendall(length)
|
|
self.socket.sendall(msg)
|
|
|
|
def readMsg(self, format=0):
|
|
initsize = self.reliableRead(2)
|
|
(length,) = struct.unpack("H", initsize)
|
|
length = socket.ntohs(length)
|
|
data = self.reliableRead(length)
|
|
if format == 1:
|
|
qs = cgi.parse_qs(data)
|
|
return qs
|
|
else:
|
|
return data
|
|
|
|
def close(self):
|
|
self.socket.close()
|
|
|
|
def auth(self):
|
|
msg = {'username': self.username, 'password': self.password}
|
|
self.sendMsg(msg)
|
|
reply = self.readMsg(1)
|
|
if reply['result'] == ["PASS"]:
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
def sendFileMeta(self):
|
|
msg = {'numpkgs': len(self.files)}
|
|
for i, v in enumerate(self.files):
|
|
msg['name'+str(i)] = v.filename
|
|
msg['size'+str(i)] = v.size
|
|
msg['md5sum'+str(i)] = v.md5
|
|
self.sendMsg(msg)
|
|
reply = self.readMsg(1)
|
|
print reply
|
|
for i in reply:
|
|
if i[:4] == 'size':
|
|
self.files[int(i[4:])].cur_done = int(reply[i][0])
|
|
|
|
def sendFiles(self):
|
|
for i in self.files:
|
|
i.fd.seek(i.cur_done)
|
|
while i.fd.tell() < i.size:
|
|
self.socket.sendall(i.fd.read(1024))
|
|
reply = self.readMsg(1)
|
|
print reply
|
|
self.sendMsg("ack")
|
|
|
|
def usage():
|
|
print "usage: tupkg [options] <package file>"
|
|
print "options:"
|
|
print " -u, --user Connect with username"
|
|
print " -P, --password Connect with password"
|
|
print " -h, --host Connect to host"
|
|
print " -p, --port Connect to host on port (default 1034)"
|
|
|
|
def main(argv=None):
|
|
if argv is None:
|
|
argv = sys.argv
|
|
|
|
confdict = {}
|
|
confdict['user'] = ""
|
|
confdict['password'] = ""
|
|
confdict['host'] = ''
|
|
confdict['port'] = 1034
|
|
|
|
if len(argv) == 1:
|
|
usage()
|
|
return 1
|
|
|
|
try:
|
|
optlist, args = getopt.getopt(argv[1:], "u:P:h:p:", ["user=", "password=", "host=", "port="])
|
|
except getopt.GetoptError:
|
|
usage()
|
|
return 1
|
|
|
|
for i, k in optlist:
|
|
if i in ('-u', '--user'):
|
|
confdict['user'] = k
|
|
if i in ('-P', '--password'):
|
|
confdict['password'] = k
|
|
if i in ('-h', '--host'):
|
|
confdict['host'] = k
|
|
if i in ('-p', '--port'):
|
|
confdict['port'] = int(k)
|
|
|
|
files = []
|
|
for i in args:
|
|
try:
|
|
files.append(ClientFile(i))
|
|
except IOError, err:
|
|
print "Error: " + err.strerror + ": '" + err.filename + "'"
|
|
usage()
|
|
return 1
|
|
|
|
cs = ClientSocket(files, confdict['host'], confdict['port'], confdict['user'], confdict['password'])
|
|
cs.connect()
|
|
|
|
if not cs.auth():
|
|
print "Error authenticating you, you bastard"
|
|
return 1
|
|
|
|
cs.sendFileMeta()
|
|
|
|
cs.sendFiles()
|
|
|
|
cs.close()
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|
|
|
|
# Python Indentation:
|
|
# -------------------
|
|
# Use tabs not spaces. If you use vim, the following comment will
|
|
# configure it to use tabs.
|
|
#
|
|
# vim:noet:ts=2 sw=2 ft=python
|