Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions froide/helper/redaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ def try_redacting_file(pdf_file, outpath, instructions):
if rewritten_pdf_file is None:
# Possibly encrypted with password, let's just try it anyway
rewritten_pdf_file = pdf_file
return _redact_file(rewritten_pdf_file, outpath, instructions)

output_filename = os.path.join(outpath, "final.pdf")
with open(output_filename, "wb") as output_file:
_redact_file(rewritten_pdf_file, output_file, instructions)
return output_filename
except PDFException as e:
tries += 1
if tries > 2:
Expand All @@ -98,7 +102,7 @@ def try_redacting_file(pdf_file, outpath, instructions):
pdf_file = next_pdf_file


def _redact_file(pdf_file, outpath, instructions, tries=0):
def _redact_file(pdf_file, output_file, instructions):
dpi = 300
load_invisible_font()
output = PdfWriter()
Expand Down Expand Up @@ -149,11 +153,7 @@ def get_page_iterator(page_instructions, image_generator):
raise PDFException(e, "rewrite") from None

output.add_page(page)

output_filename = os.path.join(outpath, "final.pdf")
with open(output_filename, "wb") as f:
output.write(f)
return output_filename
output.write(output_file)


def get_redacted_page(image_filename, instr, dpi):
Expand Down
73 changes: 73 additions & 0 deletions froide/helper/tests/test_redaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import os
from io import BytesIO
from pathlib import Path
from unittest import TestCase

import pytest

from froide.helper.redaction import _redact_file

redaction_test_data_path = (
Path(os.path.dirname(os.path.realpath(__file__))) / "testdata" / "redaction"
)
hello_world_pdf_path = redaction_test_data_path / "minimal_hello_world.pdf"
hello_world_pdf_empty_instructions_redacted_path = (
redaction_test_data_path / "minimal_hello_world_empty_instructions_redacted.pdf"
)
hello_world_pdf_right_halve_redacted_path = (
redaction_test_data_path / "minimal_hello_world_right_halve_redacted.pdf"
)


def get_file_content(file):
file.seek(0)
return file.read()


class Test(TestCase):
def setUp(self):
self.input = hello_world_pdf_path.open("rb", buffering=0)
self.expected = hello_world_pdf_empty_instructions_redacted_path.read_bytes()

def tearDown(self):
self.input.close()

@pytest.mark.asyncio(loop_scope="session")
def test__redact_file_empty_instructions(self):
in_memory_outfile = BytesIO()
empty_instructions = {"pages": [{"width": 1, "rects": []}]}

_redact_file(self.input, in_memory_outfile, empty_instructions)

self.assertEqual(
hello_world_pdf_empty_instructions_redacted_path.read_bytes(),
get_file_content(in_memory_outfile),
)

@pytest.mark.asyncio(loop_scope="session")
def test__redact_file_right_halve_rect_instructions(self):
in_memory_outfile = BytesIO()
right_halve = (150, 0, 300, 144)
text_position = (175, 72, 72, 10)
instructions = {
"pages": [
{
"width": 300,
"rects": [right_halve],
"texts": [
{
"text": "right halve redacted",
"fontSize": "6px",
"pos": text_position,
}
],
}
]
}

_redact_file(self.input, in_memory_outfile, instructions)

self.assertEqual(
hello_world_pdf_right_halve_redacted_path.read_bytes(),
get_file_content(in_memory_outfile),
)
7 changes: 7 additions & 0 deletions froide/helper/tests/testdata/redaction/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Minimal PDF

## minimal_hello_world.pdf
It's from https://brendanzagaeski.appspot.com/0004.html under MIT License.
License: ./minimal_hello_world_license.txt

Other redaction test pdf's in this folder are derived from it and share the license.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) Brendan Zagaeski

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Binary file not shown.