mp3db / app.py
Sergidev's picture
Update app.py
a99a6f1 verified
import os
import io
import wave
import struct
import logging
import hashlib
from flask import Flask, render_template, request, send_file, jsonify
from werkzeug.utils import secure_filename
from pydub import AudioSegment
import magic
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)
logger = app.logger
UPLOAD_FOLDER = '/tmp'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'mp3', 'wav', 'txt', 'pdf', 'docx'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def index():
return render_template('index.html')
@app.route('/process', methods=['POST'])
def process_file():
logger.info("Processing file request received")
if 'file' not in request.files:
logger.error("No file part in the request")
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
logger.error("No selected file")
return jsonify({'error': 'No selected file'}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
logger.info(f"File saved: {filepath}")
factor = int(request.form['factor'])
is_decrypting = filename.lower().endswith('.mp3')
logger.info(f"Processing file: {'decrypting' if is_decrypting else 'encrypting'} with factor {factor}")
try:
if is_decrypting:
output, output_filename, mimetype = decrypt_file(filepath, factor)
else:
output, output_filename, mimetype = encrypt_file(filepath, factor)
logger.info(f"File processed successfully. Output size: {len(output)} bytes")
os.remove(filepath)
logger.info(f"Temporary file removed: {filepath}")
return send_file(
io.BytesIO(output),
mimetype=mimetype,
as_attachment=True,
download_name=output_filename
)
except Exception as e:
logger.error(f"Error processing file: {str(e)}")
os.remove(filepath)
return jsonify({'error': str(e)}), 500
logger.error("Invalid file type")
return jsonify({'error': 'Invalid file type'}), 400
def calculate_checksum(data):
return hashlib.md5(data).hexdigest()
def encrypt_file(filepath, factor):
logger.info(f"Encrypting file: {filepath}")
with open(filepath, 'rb') as file:
data = file.read()
# Calculate checksum
checksum = calculate_checksum(data)
# Convert data to audio samples
samples = [int(byte * factor) for byte in data]
# Add checksum to the beginning of the samples
checksum_samples = [ord(byte) for byte in checksum.encode('ascii')]
samples = checksum_samples + samples
# Create WAV file
wav_output = io.BytesIO()
with wave.open(wav_output, 'wb') as wav_file:
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(44100)
wav_file.writeframes(struct.pack(f'{len(samples)}h', *samples))
# Convert WAV to MP3
wav_output.seek(0)
audio = AudioSegment.from_wav(wav_output)
mp3_output = io.BytesIO()
audio.export(mp3_output, format="mp3")
logger.info(f"Encryption complete. Output size: {mp3_output.getbuffer().nbytes} bytes")
return mp3_output.getvalue(), 'encrypted.mp3', 'audio/mpeg'
def decrypt_file(filepath, factor):
logger.info(f"Decrypting file: {filepath}")
# Convert MP3 to WAV
audio = AudioSegment.from_mp3(filepath)
wav_output = io.BytesIO()
audio.export(wav_output, format="wav")
wav_output.seek(0)
with wave.open(wav_output, 'rb') as wav_file:
params = wav_file.getparams()
frames = wav_file.readframes(wav_file.getnframes())
samples = struct.unpack(f'{len(frames)//2}h', frames)
# Extract checksum
checksum = ''.join(chr(sample // factor) for sample in samples[:32])
samples = samples[32:]
# Decrypt data
decrypted_bytes = bytearray()
for sample in samples:
byte_value = int(round(sample / factor))
decrypted_bytes.append(max(0, min(byte_value, 255)))
decrypted_data = bytes(decrypted_bytes)
# Verify checksum
if calculate_checksum(decrypted_data) != checksum:
raise ValueError("Checksum verification failed. The file may be corrupted or the wrong factor was used.")
# Detect original file type
mime = magic.Magic(mime=True)
file_type = mime.from_buffer(decrypted_data)
file_extension = file_type.split('/')[-1]
logger.info(f"Decryption complete. Output size: {len(decrypted_data)} bytes")
return decrypted_data, f'decrypted_file.{file_extension}', file_type
if __name__ == '__main__':
app.run(debug=True)