diff --git a/bin/fix-submits b/bin/fix-submits
new file mode 100755
index 0000000000000000000000000000000000000000..eb4476f3ae9056f9a3417b26dd099ba203c7f633
--- /dev/null
+++ b/bin/fix-submits
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+import argparse
+import datetime
+import os
+from sqlalchemy.orm import joinedload
+import subprocess
+import tempfile
+
+import mo.db as db
+import mo.submit
+import mo.util
+
+parser = argparse.ArgumentParser(description='Pokusí se opravit rozbitá PDF')
+parser.add_argument(dest='id', type=int, nargs='?', help='ID papíru k opravení')
+args = parser.parse_args()
+
+mo.util.init_standalone()
+sess = db.get_session()
+
+
+def fix_paper(id: int):
+    paper = (sess.query(db.Paper)
+             .options(joinedload(db.Paper.for_user_obj))
+             .get(id))
+    assert paper is not None
+    print(f"=== Paper #{id} ({paper.file_name})")
+
+    sol = (sess.query(db.Solution)
+           .filter_by(task_id=paper.for_task, user_id=paper.for_user)
+           .one())
+    if paper.paper_id not in [sol.final_submit, sol.final_feedback]:
+        print('--> not final\n')
+        sess.rollback()
+        return
+
+    tmp_file = tempfile.NamedTemporaryFile(dir=mo.util.data_dir('tmp'), prefix='fix-')
+
+    res = subprocess.run(['qpdf', os.path.join(mo.util.data_dir('submits'), paper.file_name), tmp_file.name])
+    if res.returncode in [0, 3]:
+        sub = mo.submit.Submitter()
+        new_paper = db.Paper(task=paper.task,
+                             for_user_obj=paper.for_user_obj,
+                             type=paper.type,
+                             uploaded_by_obj=paper.uploaded_by_obj,
+                             uploaded_at=paper.uploaded_at + datetime.timedelta(seconds=1),
+                             note='Automatická konverze rozbitého PDF')
+        sub.submit_paper(new_paper, tmp_file.name)
+        assert not new_paper.broken
+
+        sess.add(new_paper)
+        if new_paper.type == db.PaperType.solution:
+            sol.final_submit_obj = new_paper
+        elif new_paper.type == db.PaperType.feedback:
+            sol.final_feedback_obj = new_paper
+        else:
+            assert False
+
+        print('--> OK')
+        sess.commit()
+    else:
+        print(f'--> ERROR: qpdf failed with exit code {res.returncode}')
+        sess.rollback()
+
+    print("")
+
+
+if args.id is not None:
+    fix_paper(args.id)
+else:
+    papers = sess.query(db.Paper).filter_by(broken=True).all()
+    sess.rollback()
+    for p in papers:
+        fix_paper(p.paper_id)