uploading files works (only tested with one but should work just dandy with lots of files)... things like resume and authentication aren't fully implemented yet (server side is missing)

This commit is contained in:
jchu 2004-09-02 09:22:10 +00:00
parent 5d09c247da
commit 2423a686d6
2 changed files with 242 additions and 13 deletions

View file

@ -6,14 +6,148 @@
# 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
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 <package file>"
def main(argv=None):
if argv is None:
argv = sys.argv
if len(argv) == 1:
usage()
return 1
try:
fil = ClientFile(argv[1])
except IOError, err:
print "Error: " + err.strerror + ": '" + err.filename + "'"
usage()
return 1
cs = ClientSocket([fil], 'localhost', 1034, "bfinch@example.net", "B0b")
cs.connect()
if not cs.auth():
print "Error authenticating you, you bastard"
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: ts=2 sw=2 noet ft=python
#
# TODO write the code
#
# vim:noet:ts=2 sw=2 ft=python

View file

@ -18,25 +18,119 @@ import sys
import socket
import threading
import select
import struct
import cgi
import urllib
import md5
CACHEDIR = '/var/cache/tupkgs/'
class ClientFile:
def __init__(self, filename, actual_size, actual_md5):
self.pathname = CACHEDIR + filename
self.filename = filename
self.fd = open(self.pathname, "w+b")
self.actual_size = actual_size
self.actual_md5 = actual_md5
def getSize(self):
cur = self.fd.tell()
self.fd.seek(0,2)
self.size = self.fd.tell()
self.fd.seek(cur)
def makeMd5(self):
md5sum = md5.new()
cur = self.fd.tell()
self.getSize()
self.fd.seek(0)
while self.fd.tell() != self.size:
md5sum.update(self.fd.read(1024))
self.fd.seek(cur)
self.md5 = md5sum.hexdigest()
class ClientSocket(threading.Thread):
def __init__(self, socket, **other):
def __init__(self, sock, **other):
threading.Thread.__init__(self, *other)
self.socket = socket
self.socket = sock
self.running = 1
self.files = []
def close(self):
pass
self.running = 0
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 auth(self):
authdata = self.readMsg()
print authdata
# Do auth stuff here
self.sendMsg("result=PASS")
def readFileMeta(self):
files = self.readMsg(1)
print files
# Actually do file checking, et al
for i in range(int(files['numpkgs'][0])):
self.files.append(ClientFile(files['name'+str(i)][0], int(files['size'+str(i)][0]), files['md5sum'+str(i)][0]))
new_files = files.copy()
for i in files:
if i[:4] == 'size':
new_files[i] = '0'
if i[:6] == 'md5sum':
del new_files[i]
self.sendMsg(new_files)
def readFiles(self):
for i in self.files:
i.fd.write(self.reliableRead(i.actual_size))
i.fd.flush()
reply = {'numpkgs': len(self.files)}
for i, v in enumerate(self.files):
v.makeMd5()
if v.actual_md5 == v.md5:
reply['md5sum'+str(i)] = "PASS"
else:
reply['md5sum'+str(i)] = "FAIL"
self.sendMsg(reply)
print self.readMsg()
def run(self):
while len(self.socket.recv(1)) != 0:
pass
self.auth()
self.readFileMeta()
self.readFiles()
class ServerSocket(threading.Thread):
def __init__(self, port=1034, maxqueue=5, **other):
threading.Thread.__init__(self, *other)
self.running = 1
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((socket.gethostname(), port))
self.socket.bind(('', port))
self.socket.listen(maxqueue)
self.clients = []
@ -47,6 +141,7 @@ class ServerSocket(threading.Thread):
def close(self):
self.socket.close()
self.running = 0
def run(self):
while self.running:
@ -82,7 +177,7 @@ def main(argv=None):
print "Just cleaning up stuff"
servsock.running = 0
servsock.close()
servsock.join()