Datei in eine andere Datei 'verstecken'

Code-Stücke können hier veröffentlicht werden.
Antworten
addi
User
Beiträge: 28
Registriert: Donnerstag 29. März 2018, 22:54

Samstag 11. August 2018, 12:55

Hey Leute, ich habe mal ein kleines Programm erstellt, mit dem man eine Datei in einer anderen 'verstecken' kann. Naja da ich gerne Feedback zum Code hätte (Anti pattern usw.) stelle ich das einfach mal vor:

Code: Alles auswählen

import argparse
import os

PYGANOS = '''
  /$$$$$$  /$$   /$$  /$$$$$$   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$$
 /$$__  $$| $$  | $$ /$$__  $$ |____  $$| $$__  $$ /$$__  $$ /$$_____/
| $$  \ $$| $$  | $$| $$  \ $$  /$$$$$$$| $$  \ $$| $$  \ $$|  $$$$$$
| $$  | $$| $$  | $$| $$  | $$ /$$__  $$| $$  | $$| $$  | $$ \____  $$
| $$$$$$$/|  $$$$$$$|  $$$$$$$|  $$$$$$$| $$  | $$|  $$$$$$/ /$$$$$$$/
| $$____/  \____  $$ \____  $$ \_______/|__/  |__/ \______/ |_______/
| $$       /$$  | $$ /$$  \ $$
| $$      |  $$$$$$/|  $$$$$$/  A simple hiding program.
|__/       \______/  \______/

'''

def pack(file1, file2):
    #to save the file names which are important for the output
    output = file1
    hide_name = file2
    print(f"\n\nHiding {file2} in {file1}.")
    file1 = open(file1, 'rb').read()
    file2 = open(file2, 'rb').read()
    with open(f'output/{output}', 'wb') as data:
        data.write(file1)
        #when unpack then it is the starting poin and here also the name of the file is saved
        data.write(f'\npyganos-start\n{hide_name}\n'.encode())
        data.write(file2)
    print("\nDone!")


def unpack(output):
    is_pyganos = False
    with open(output, 'rb') as file:
        searchlines = file.readlines()
        for i, line in enumerate(searchlines):
            if 'pyganos-start'.encode() in line:
                filename = searchlines[i+1].decode().strip()
                unpacked = searchlines[i+2:]
                is_pyganos = True
                print(f"\n\nSuccesfully unhide {filename} - Look into the output folder, there will be {filename}!")
    if is_pyganos == True:
        with open(f'output/{filename}', 'wb') as output:
            for line in unpacked:
                output.write(line)
    else:
        print('\n\nIt isn\'t a pyganos File! Please try an other one.')

def checkdir():
    if not os.path.isdir('output'):
        os.mkdir('output')
        
cmdinput = argparse.ArgumentParser(description='A program which can hide one file in an other.')
cmdinput.add_argument('--h', '--hide', nargs = 2, help='This command is for packing /hiding the data. You have to insert two files. Eg. python pyganos.py -h file.png file2.txt')
cmdinput.add_argument('--u', '--unhide', nargs = 1, help='This command is for unpacking you hiding data! Usage python pyganos -u file1.png - The output will be saved in the folder output.')
args = vars(cmdinput.parse_args())

checkdir()

if args['h']:
    print(PYGANOS)
    filenames = args['h']
    file1 = filenames[0]
    file2 = filenames[1]
    pack(file1, file2)

elif args['u']:
    print(PYGANOS)
    filename = args['u']
    unpack(filename[0])

else:
    print(PYGANOS)
    while True:
        user = input('Do you like to hide or unhide a file? [H|U]> ')
        if user.upper() == 'H':
            while True:
                file1_exists = False
                file2_exists = False
                file1 = input('Your first file in which the second will be hided (If not in same dir an pyganos, please give in also the dir!)> ')
                if os.path.exists(file1):
                    file1_exists = True
                file2 = input('You file which you would like to hide (If not in same dir an pyganos, please give in also the dir!)> ')
                if os.path.exists(file2):
                    file2_exists = True
                if file1_exists == False and file2_exists == False:
                    print(f'Can\'t find {file1} and {file2}!\n')
                elif file1_exists == False:
                    print(f'Can\'t find {file1}!\note')
                elif file2_exists == False:
                    print(f'Can\'t find {file2}!\n')
                else:
                    break
            pack(file1, file2)
            break
        elif user.upper() == 'U':
            while True:
                file_exists = False
                file = input('Which file you\'d like to unhide?> ')
                if os.path.exists(file):
                    file_exists = True
                if file_exists == False:
                    print(f'Can\'t find {file}!\n')
                else:
                    break
            unpack(file)
            break
        else:
            print('Please insert H or U !')
Sirius3
User
Beiträge: 8264
Registriert: Sonntag 21. Oktober 2012, 17:20

Samstag 11. August 2018, 14:05

Wie gewünscht:

In ›pack‹ heißen die Argumente kryptisch file1 und file1 um sie dann gleich in sinnvollere Namen, output und hide_name umzubennen, warum nicht gleich richtige Namen verwenden? Warum ist ›output‹ eigentlich der Name der Input-Datei?
›file1‹ und ›file2‹ sind dann später auch noch der Inhalt der Dateien. Gleiche Variablennamen sollten nicht in der selben Funktion an unterschiedliche Dinge gebunden sein. Dateien werden nicht wieder geschlossen. Warum benutzt Du nicht immer with?
Ist ›output‹ eine Datei mit Pfad, funktioniert das Zusammenstückeln der Ausgabedatei nicht mehr. Zum Zusammensetzen von Pfaden nimmt man das Modul ›pathlib‹.
Statt beide Dateien komplett in den Speicher zu lesen, besser nacheinander, blockweise und gleich speichern. Dafür gibt es auch schon was fertiges in ›shutils‹.

In ›unpack‹ ist output eigentlich auch wieder der input_filename. `in` ist der falsche Operator, wenn man prüfen will, ob die komplette Zeile "pyganos-start" enthält. Statt nach einem Fund solltest Du die Schleife abbrechen. Mit einem else-Block der for-Scheife ist das Flag »is_pygano« überflüssig.
Statt die ganze Datei auf einmal zu lesen, solltest Du auch hier Zeilenweise lesen, statt des Indexes würde man dann einfach die nächste Zeile als Dateiname, alle weiteren als Inhalt der zweiten Datei nehmen.

›checkdir‹ ist der falsche Name für eine Funktion, die ein Verzeichnis erzeugt, `ensure_dir_exists` wäre passender. Existiert schon eine Datei mit dem Namen ›output‹, kommt es zu einer Fehlermeldung.

Alles folgende sollte in einer Funktion, die man üblicherweise ›main‹ nennt, stehen. Was ist der Sinn des `vars`-Aufrufs?
Die äußere while-True-Schleife ist viel zu lang. Da sollte eigentlich nur die Abfrage nach h oder u drinstehen. Der Code in den ifs gehört dann auch in eigene Funktionen.
Warum fragst Du nochmal beide Dateinamen ab, wenn einer von beiden nicht existiert?
Das einzelne Abfragen gibt dann auch einfachere Schleifen, ohne dass man Flags braucht.
Python kennt 4 verschieden Arten, literale Strings zu definieren, Anführungszeichen braucht man daher fast nie escapen, wenn man die richtigen nimmt.
Benutzeravatar
__blackjack__
User
Beiträge: 1049
Registriert: Samstag 2. Juni 2018, 10:21

Samstag 11. August 2018, 17:35

Binärdateien und Zeilen lesen passt nicht zusammen. `unpack()` ist also IMHO falsch implementiert.

Edit: Und es funktioniert auch nicht grundsätzlich. Man kann nicht bei jedem Dateiformat einfach so eine zweite Datei dazu kopieren ohne das es deutlich auffällt und/oder die ”Hostdatei” unlesbar wird.
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Antworten