Skip to content

Commit

Permalink
Implement PDF export and deprecate TXT export
Browse files Browse the repository at this point in the history
  • Loading branch information
msmannan00 authored and evilaliv3 committed May 24, 2024
1 parent 00792a5 commit d7d1537
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 17 deletions.
96 changes: 95 additions & 1 deletion backend/globaleaks/handlers/recipient/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# API handling export of submissions
import os
import re
from io import BytesIO
from twisted.internet.defer import inlineCallbacks
from twisted.internet.threads import deferToThread
Expand All @@ -27,6 +28,72 @@
from globaleaks.utils.zipstream import ZipStream


try:

import fpdf

class REPORTPDF(fpdf.FPDF):
report_default_font = "Inter-Regular.ttf"
report_fallback_fonts = ["GoNotoKurrent-Regular.ttf"]
report_direction = 'ltr'
report_line_height = 3
report_margin = 10
fonts_characters = {}

def __init__(self, *args, **kwargs):
super(REPORTPDF, self).__init__(*args, **kwargs)

fontspath = os.path.join(Settings.client_path, "fonts")
self.add_font(family="Inter-Regular.ttf", style='', fname=os.path.join(fontspath, "Inter-Regular.ttf"))
self.add_font(family="GoNotoKurrent-Regular.ttf", style='', fname=os.path.join(fontspath, "GoNotoKurrent-Regular.ttf"))

for font in list(self.fonts.keys()):
if font != self.report_default_font and isinstance(self.fonts[font], fpdf.fonts.TTFFont):
self.fonts_characters[font] = len(self.fonts[font].subset)

self.set_font(self.report_default_font, "", 11)
self.set_fallback_fonts(self.report_fallback_fonts)

self.set_auto_page_break(auto=True, margin=15)

self.set_author("GLOBALEAKS")
self.set_creator("GLOBALEAKS")
self.set_lang("EN")

self.set_right_margin(self.report_margin)
self.set_left_margin(self.report_margin)

self.set_text_shaping(use_shaping_engine=True, direction="ltr")

def header(self):
self.cell(80)
self.set_font("courier", "", 9)
self.set_text_shaping(use_shaping_engine=True, direction="ltr")
self.cell(30, 10, self.title, align="C")
self.set_text_shaping(use_shaping_engine=True, direction=self.report_direction)
self.set_font(self.report_default_font, "", 11)
self.ln(20)

def footer(self):
self.set_y(-15)
self.set_font("courier", "", 9)
self.set_text_shaping(use_shaping_engine=True, direction="ltr")
self.cell(0, 10, f"{self.page_no()}/{{nb}}", align="C")
self.set_text_shaping(use_shaping_engine=True, direction=self.report_direction)
self.set_font(self.report_default_font, "", 11)

def output(self, *args, **kwargs):
for font in list(self.fonts.keys()):
if font != self.report_default_font and isinstance(self.fonts[font], fpdf.fonts.TTFFont) and \
self.fonts_characters[font] == len(self.fonts[font].subset):
self.fonts.pop(font)

return super(REPORTPDF, self).output(*args, **kwargs)

except ImportError:
pass


def serialize_rtip_export(session, user, itip, rtip, context, language):
rtip_dict = serializers.serialize_rtip(session, itip, rtip, language)

Expand Down Expand Up @@ -66,6 +133,30 @@ def get_tip_export(session, tid, user_id, itip_id, language):
return user.pgp_key_public, serialize_rtip_export(session, user, itip, rtip, context, language)


def create_pdf_report(input_text, data):
pdf = REPORTPDF(orientation='P', unit='mm', format='A4')

pdf.set_title("REPORT " + str(data['tip']['progressive']) + " (" + str(data['tip']['id']) + ") [CONFIDENTIAL]")

pdf.add_page()

# Process each line
for line in input_text.split('\n'):
if any('\u0590' <= char <= '\u06FF' for char in line): # Check for characters in Hebrew or Arabic blocks
if pdf.report_direction == 'ltr':
pdf.report_direction = 'rtl'
pdf.set_text_shaping(use_shaping_engine=True, direction=pdf.report_direction)
else:
if pdf.report_direction == 'rtl':
pdf.report_direction = 'ltr'
pdf.set_text_shaping(use_shaping_engine=True, direction=pdf.report_direction)

pdf.multi_cell(0, pdf.report_line_height, line.strip(), align='L')
pdf.ln()

return BytesIO(pdf.output())


@inlineCallbacks
def prepare_tip_export(user_session, tip_export):
tip_export['tip']['rfiles'] = list(filter(lambda x: x['visibility'] != 'personal', tip_export['tip']['rfiles']))
Expand Down Expand Up @@ -113,7 +204,10 @@ def prepare_tip_export(user_session, tip_export):
export_template = Templating().format_template(tip_export['notification']['export_template'], tip_export).encode()
export_template = msdos_encode(export_template.decode()).encode()

files.append({'fo': BytesIO(export_template), 'name': 'report.txt'})
if REPORTPDF:
files.append({'fo': create_pdf_report(export_template.decode(), tip_export), 'name': 'report.pdf'})
else:
files.append({'fo': BytesIO(export_template), 'name': 'report.txt'})

return files

Expand Down
1 change: 1 addition & 0 deletions backend/requirements/requirements-noble.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
acme==2.9.0
cryptography==41.0.7
fpdf==2.7.8
h2==4.1.0
idna==3.6
priority==2.0.0
Expand Down
15 changes: 2 additions & 13 deletions client/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,17 +357,6 @@ module.exports = function(grunt) {
},

shell: {
convert_fonts: {
command: function() {
// The directory containing the font files
var fontDir = 'app/fonts';
// FontForge script file
var scriptFile = 'scripts/fontforge';

// Command to find font files and process them with xargs and FontForge
return 'find ' + fontDir + ' -type f -name "*.woff2" | sed "s/.woff2//g" | xargs -I {} sh -c "test -f {}.ttf || fontforge -lang=ff -script scripts/fontforge {}.woff2"'
}
},
npx_build: {
command: "npx ng build --configuration=production --aot"
},
Expand Down Expand Up @@ -967,7 +956,7 @@ module.exports = function(grunt) {
// Run this task to fetch translations from transifex and create application files
grunt.registerTask("updateTranslations", ["fetchTranslations", "makeAppData", "verifyAppData"]);

grunt.registerTask("build", ["clean", "copy:fonts", "shell:convert_fonts", "shell:npx_build", "copy:build", "string-replace", "copy:package", "clean:tmp"]);
grunt.registerTask("build", ["clean", "shell:npx_build", "copy:build", "string-replace", "copy:package", "clean:tmp"]);

grunt.registerTask("build_and_instrument", ["clean", "copy:fonts", "shell:convert_fonts", "shell:npx_build_and_instrument", "copy:build", "string-replace", "copy:package", "clean:tmp"]);
grunt.registerTask("build_and_instrument", ["clean", "shell:npx_build_and_instrument", "copy:build", "string-replace", "copy:package", "clean:tmp"]);
};
Binary file added client/app/fonts/GoNotoKurrent-Regular.ttf
Binary file not shown.
7 changes: 4 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@flowjs/flow.js": "2.14.1",
"@flowjs/ngx-flow": "0.8.1",
"@fontsource/inter": "5.0.18",
"@fontsource/noto-sans": "^5.0.22",
"@fontsource/noto-sans-arabic": "5.0.13",
"@fontsource/noto-sans-armenian": "5.0.14",
"@fontsource/noto-sans-bengali": "5.0.13",
Expand Down Expand Up @@ -60,13 +61,13 @@
"zone.js": "0.14.6"
},
"devDependencies": {
"@angular/cli": "17.3.7",
"@angular/compiler": "17.3.9",
"@angular/compiler-cli": "17.3.9",
"@angular-builders/custom-webpack": "17.0.2",
"@angular-devkit/architect": "0.1703.7",
"@angular-devkit/build-angular": "17.3.7",
"@angular-devkit/core": "17.3.7",
"@angular/cli": "17.3.7",
"@angular/compiler": "17.3.9",
"@angular/compiler-cli": "17.3.9",
"@cypress/code-coverage": "3.12.39",
"@cypress/schematic": "2.5.1",
"@istanbuljs/nyc-config-typescript": "1.0.2",
Expand Down
10 changes: 10 additions & 0 deletions client/scripts/fontforge
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/fontforge

# Open the font file
Open($1)

# Perform some operations, for example, generating a new font
Generate($1:r + ".ttf")

# Close the font
Close()
1 change: 1 addition & 0 deletions debian/controlX/control.noble
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Depends:
lsb-base,
python3-acme,
python3-cryptography,
python3-fpdf,
python3-h2,
python3-nacl,
python3-openssl,
Expand Down

0 comments on commit d7d1537

Please sign in to comment.