I am connecting to a pre-configured server that serves four different file formats with different sizes. Each file is appended with the file size...
Example: lighthouse.jpg
561276ÿØÿà JFIF ` ` ÿî Adobe
The "561276" is the file size and needs to be pruned before saving the file.
Example: randomText.txt
45711111111111111111111111111111111111111111111111111111111
222222222222222222222222222222222222222222222222222222222
33333333333333333333333333333333333333333333333333
44444444444444444444444444444444444444444444444444444444
66666666666666666666
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cvccccccccccccccccccccccccccccccccccccccccccccccc
ddddddddddddddddddddddddddddddddddddddddddddddddddd
The "457" is the file size and needs to be pruned before saving the file.
Some files have a size that is only 3-digits long. Some have a file size that is 6-digits long (as seen here). I want to make my code size-agnostic; regardless of how many digits is in the size.
I've tried using:
while len(buf) < 4:
buf += sock.recv(4 - len(buf))
size = struct.unpack('!i', buf)
but this only prunes the first four digits.
AND
I've tried using
len = sock.recv(4)
data = sock.recv(len)
but once again... only prunes the first four digits
Here is what I have so far:
def get_size():
buf = ''
while len(buf) < 4:
buf += sock.recv(4 - len(buf))
size = struct.unpack('!i', buf)
print "[*] Receiving %s bytes" % size
def download_pic():
size = get_size()
fname = 'tst.jpg'
with open(fname, 'wb') as img:
while True:
data = sock.recv(1024)
if not data:
break
img.write(data)
print '[*] {0} received!'.format(fname)
def main():
doconnectionstuffandprinttoconsole() #establishes connection
answer = input("[>] Your Selection: ")
sock.send(str(answer))
if answer == 2:
download_pic()
sock.close()
Any help in pruning the size from the file(s) would be greatly appreciated!
Jason Harper's suggestion (@jasonharper) got me thinking. When I ran repr(data) on the chunks from randomText.txt, I saw that it had a break in it that looked like...
'457''1111111111111111111111...
The server was attempting to send two different chunks (one at at time) but it kept getting merged into one chunk. So, I increased my sock.recv(64) up to sock.recv(256). And for some reason, it send two chunks!
'457'
'111111111...' [truncated]
NEW AND IMPROVED CODE!
import socket
import sys
import struct
import os
user1 = {'user1': 91827364}
user2 = {'user2': 19283746}
user3 = {'user3': 46372819}
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 2058))
def print_data():
data_rcv = sock.recv(1024)
print "[-] {0}".format(data_rcv)
def download_file(format):
fname = 'download'
fullname = fname + '.' + format
try:
with open(fullname, 'wb') as txt:
len = sock.recv(256)
while True:
data = sock.recv(int(len))
if not data:
break
txt.write(data)
print("[*] {0} successfully downloaded with a length of {1} characters!".format(fullname, len))
except Exception:
print("[!] Error receiving file. Please try again.")
def connect():
print("[*] Sending Length")
sock.send("5")
my_struct = struct.pack('5s i', 'user1', 91827364)
print("[*] Sending User1 Struct")
sock.send(my_struct)
print_data()
def main():
print_data()
connect()
print_data()
answer = input("[>] Your Selection: ")
sock.send(str(answer))
if answer == 2: # Option to download Lighthouse.jpg
download_file("jpg")
elif answer == 4: # Option to download randomText.txt
download_file("txt")
sock.close()
if __name__ == "__main__":
main()
MY OUTPUT
[-] Please enter credentials
[*] Sending Length
[*] Sending User1 Struct
[-] Authenticated
[-] Choose a file to retrieve from the following list (enter the number):
1. photo.png
2. Lighthouse.jpg
3. npp.6.8.5.Installer.exe
4. randomText.txt
[>] Your Selection: 2
[*] download.jpg successfully downloaded with a length of 561276 characters!